Skip to content

Instantly share code, notes, and snippets.

@shima-529

shima-529/usb.c Secret

Created February 11, 2022 13:49
Show Gist options
  • Save shima-529/34569afc4eba1152f253931a061f6578 to your computer and use it in GitHub Desktop.
Save shima-529/34569afc4eba1152f253931a061f6578 to your computer and use it in GitHub Desktop.
USB Device MCU program working on CH559L
#include <string.h>
#include "ch559.h"
#include "uart.h"
#define USE_USB_DEFINE_
#include "usb.h"
#define MIN(x, y) (((x) > (y) ? (y) : (x)))
__xdata unsigned char ep_buffer_[1][65];
__xdata unsigned char *ep0_buffer = ep_buffer_[0];
const unsigned char usb_descrs[][64] = { // Except for String(3)
{0}, // dummy
{18, 1, 0x00, 0x02, 0xFF, 0xFF, 0xFF, 64, 0xb8, 0x04, 0xad, 0xde, 0x01, 0x00, 0, 1, 0, 1}, // Device
{9, 2, 9+9, 0, 1, 1, 0, 0x80, 0x0A,
9, 4, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0
}, // Config
{0}, // dummy
};
const unsigned char usb_str_descrs[][64] = {
{4, 3, 0x11, 0x04}, // wLANGID = Japanese
{12, 3, 'M', 0, 'y', 0, '5', 0, '5', 0, '9', 0},
};
void usb_device_init(void) { /// {{{
USB_CTRL = 0; // release all resets
UEP0_CTRL = 0xF; // send STALL to all packets
USB_INT_EN = (1 << 0) | (1 << 1) | (1 << 4);
// IRQs: BUS RESET, TRANSFER, FIFO OVERFLOW
EA = 1;
IE_EX |= 1 << 2;
UDEV_CTRL = (1 << 4) | (1 << 5); // disable all pull-downs
USB_CTRL = (2 << 4) | (1 << 5) | (1 << 3) | (1 << 0); // enable pull-ups, DMA en
UDEV_CTRL |= 1 << 0; // enable physical port
if( (unsigned int)ep0_buffer & 1 ) {
ep0_buffer++;
}
} // }}}
static void print_usb_buffer(__xdata unsigned char *buf, int len) {
for(int i = 0; i < len; i++) {
char upper = buf[i] >> 4;
char lower = buf[i] & 0xF;
if( upper <= 9 ) uart0_send(upper + '0');
else uart0_send(upper - 10 + 'A');
if( lower <= 9 ) uart0_send(lower + '0');
else uart0_send(lower - 10 + 'A');
uart0_send(' ');
}
uart0_send('\r');
uart0_send('\n');
}
static void uart_print(char *str) {
for(int i = 0; str[i] != '\0'; i++) {
uart0_send(str[i]);
}
}
typedef enum {
RESET, SETUP, IN, OUT, STATUS_IN, STATUS_OUT,
} EP0_State;
EP0_State ep0_state; // holds the next state
void usb_device_isr(void) __interrupt(8) {
static unsigned char addr = 0;
const unsigned char int_fg = USB_INT_FG;
if( int_fg & UIF_BUS_RESET ) { // {{{
uart_print("\r\n\r\n===\r\nReset\r\n");
USB_DEV_AD = 0; // set USB address as 0
UEP0_CTRL = 0; // NAK/STALL: tekitou
UEP0_DMA_H = (unsigned int)(ep0_buffer) >> 8;
UEP0_DMA_L = (unsigned int)(ep0_buffer) & 0xFF;
ep0_state = SETUP;
} // }}}
else{
const unsigned char int_st = USB_INT_ST;
const unsigned char ep_number = USB_INT_ST & 0xF;
const unsigned char rx_len = USB_RX_LEN;
/* uart_print("EP"); */
/* uart0_send(ep_number + '0'); */
if( ep_number == 0 ) {
USBSetupPacket packet;
memcpy(packet.raw, ep0_buffer, 8);
if( (int_st & bUIS_TOKEN) == bUIS_TOKEN_SETUP ) {
switch( packet.bRequest ) {
case SET_ADDRESS:
uart_print("S_A\r\n");
addr = packet.wValue & 0x7F;
UEP0_CTRL = bUEP_T_TOG;
UEP0_T_LEN = 0;
ep0_state = STATUS_IN;
break;
case GET_DESCRIPTOR:
uart_print("G_D\r\n");
print_usb_buffer(ep0_buffer, rx_len);
const char descr_type = packet.wValue >> 8;
if( descr_type == STRING_DESCRIPTOR ) {
const char index = packet.wValue & 0xFF;
const char descr_len = usb_str_descrs[index][0];
memcpy(ep0_buffer, usb_str_descrs[index], descr_len);
UEP0_T_LEN = MIN(descr_len, packet.wLength);
}else if(descr_type == CONFIGURATION_DESCRIPTOR ){
const char descr_len = usb_descrs[descr_type][2];
memcpy(ep0_buffer, usb_descrs[descr_type], descr_len);
UEP0_T_LEN = MIN(descr_len, packet.wLength);
}else{
const char descr_len = usb_descrs[descr_type][0];
memcpy(ep0_buffer, usb_descrs[descr_type], descr_len);
UEP0_T_LEN = MIN(descr_len, packet.wLength);
}
UEP0_CTRL = bUEP_T_TOG;
ep0_state = IN;
break;
case GET_CONFIGURATION:
uart_print("G_C\r\n");
ep0_buffer[0] = 1;
UEP0_T_LEN = 1;
UEP0_CTRL = bUEP_T_TOG;
ep0_state = IN;
break;
default:
uart_print("ELSE\r\n");
print_usb_buffer(ep0_buffer, rx_len);
break;
}
}else if( (int_st & bUIS_TOKEN) == bUIS_TOKEN_IN ) {
if( USB_DEV_AD == 0 && addr != 0 ) USB_DEV_AD = addr;
if( ep0_state == STATUS_IN ) {
UEP0_CTRL = 0;
ep0_state = SETUP;
}else{ // IN
UEP0_CTRL = bUEP_R_TOG;
ep0_state = STATUS_OUT;
}
}else if( (int_st & bUIS_TOKEN) == bUIS_TOKEN_OUT ) {
if( ep0_state == STATUS_OUT ) {
UEP0_CTRL = 0;
ep0_state = SETUP;
}
}
}
}
USB_INT_FG = int_fg;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment