-
-
Save shima-529/34569afc4eba1152f253931a061f6578 to your computer and use it in GitHub Desktop.
USB Device MCU program working on CH559L
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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