├── .gitignore ├── src └── CH552duinoKeyboardCore │ ├── KeyboardCore.h │ ├── via.h │ ├── USBconstant.h │ ├── USBHIDKeyboardMouse.h │ ├── USBhandler.h │ ├── KeyboardCore.c │ ├── via.c │ ├── USBHIDKeyboardMouse.c │ ├── USBconstant.c │ └── USBhandler.c ├── KeyboardConfig.h.sample ├── README.md ├── CH552duinoKeyboard.ino └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | KeyboardConfig.h 2 | 3 | -------------------------------------------------------------------------------- /src/CH552duinoKeyboardCore/KeyboardCore.h: -------------------------------------------------------------------------------- 1 | void keyboard_init(void); 2 | void keyboard_scan(void); 3 | -------------------------------------------------------------------------------- /src/CH552duinoKeyboardCore/via.h: -------------------------------------------------------------------------------- 1 | void raw_hid_receive(void); 2 | uint16_t dynamic_keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col); 3 | 4 | -------------------------------------------------------------------------------- /KeyboardConfig.h.sample: -------------------------------------------------------------------------------- 1 | #define ROWS_COUNT 2 2 | #define COLS_COUNT 2 3 | 4 | #define MATRIX_ROWS { 34, 33 } 5 | #define MATRIX_COLS { 31, 30 } 6 | 7 | //#define STATUS_LED_FUNCTION(led) set_led(led) 8 | 9 | void set_led(uint8_t led_status); 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Remap対応CH552マクロパッドファームウェア 2 | 3 | ### できること 4 | 5 | * Remapからのキー割当 6 | * マトリックススキャン 7 | * キーボードのキーの送信 8 | * Modifier+キー (例: Ctrl+A) 9 | 10 | ### 未実装 11 | 12 | * マウスキー 13 | * レイヤー 14 | * ConsumerControl 15 | 16 | ### 使い方 17 | 18 | 1. 本リポジトリをクローン 19 | 1. `KeyboardConfig.h.sample` を `KeyboardConfig.h` としてコピーし, 設定を書き換え 20 | 1. `CH552duinoKeyboard.ino`をArduino IDEで開く 21 | 1. [CH55xduino](https://github.com/DeqingSun/ch55xduino)をインストール 22 | 1. `USB Settings` から `USER CODE w/ 148B ram` を選択 23 | 1. コンパイル・書き込み 24 | 25 | ### 書き込みのコツ 26 | 27 | 1回目の書き込みがダメでも挿し込みから10秒以内にもう一度書き込みをすると大体成功する 28 | 29 | -------------------------------------------------------------------------------- /CH552duinoKeyboard.ino: -------------------------------------------------------------------------------- 1 | /* 2 | HID Keyboard mouse combo example 3 | 4 | 5 | created 2022 6 | by Deqing Sun for use with CH55xduino 7 | 8 | This example code is in the public domain. 9 | 10 | */ 11 | 12 | //For windows user, if you ever played with other HID device with the same PID C55D 13 | //You may need to uninstall the previous driver completely 14 | 15 | 16 | #ifndef USER_USB_RAM 17 | #error "This example needs to be compiled with a USER USB setting" 18 | #endif 19 | 20 | #include "src/CH552duinoKeyboardCore/KeyboardCore.h" 21 | 22 | void setup() { 23 | keyboard_init(); 24 | } 25 | 26 | void loop() { 27 | keyboard_scan(); 28 | delay(50); //naive debouncing 29 | } 30 | -------------------------------------------------------------------------------- /src/CH552duinoKeyboardCore/USBconstant.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_CONST_DATA_H__ 2 | #define __USB_CONST_DATA_H__ 3 | 4 | #include 5 | #include "include/ch5xx.h" 6 | #include "include/ch5xx_usb.h" 7 | 8 | #define EP0_ADDR 0 9 | #define EP1_ADDR 10 10 | 11 | extern __code uint8_t DevDesc[]; 12 | extern __code uint8_t CfgDesc[]; 13 | extern __code uint8_t LangDes[]; 14 | extern __code uint8_t ReportDesc[]; 15 | extern __code uint8_t SerDes[]; 16 | extern __code uint8_t Prod_Des[]; 17 | extern __code uint8_t Manuf_Des[]; 18 | 19 | extern __code uint16_t DevDescLen; 20 | extern __code uint16_t CfgDescLen; 21 | extern __code uint16_t LangDesLen; 22 | extern __code uint16_t ReportDescLen; 23 | extern __code uint16_t SerDesLen; 24 | extern __code uint16_t Prod_DesLen; 25 | extern __code uint16_t Manuf_DesLen; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/CH552duinoKeyboardCore/USBHIDKeyboardMouse.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_HID_KBD_H__ 2 | #define __USB_HID_KBD_H__ 3 | 4 | #include 5 | #include "include/ch5xx.h" 6 | #include "include/ch5xx_usb.h" 7 | 8 | enum MOUSE_BUTTON { 9 | MOUSE_LEFT = 1, 10 | MOUSE_RIGHT = 2, 11 | MOUSE_MIDDLE = 4, 12 | }; 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | void USBInit(void); 19 | 20 | void Keyboard_press(uint8_t kc); 21 | void Keyboard_release(uint8_t kc); 22 | void Keyboard_releaseAll(void); 23 | 24 | uint8_t Mouse_press(uint8_t k); 25 | uint8_t Mouse_release(uint8_t k); 26 | uint8_t Mouse_click(uint8_t k); 27 | uint8_t Mouse_move(int8_t x, int8_t y); 28 | uint8_t Mouse_scroll(int8_t tilt); 29 | 30 | void raw_hid_send(void); 31 | void send_keyboard_report(void); 32 | 33 | #include "USBconstant.h" 34 | 35 | extern __xdata __at (EP0_ADDR) uint8_t Ep0Buffer[]; 36 | extern __xdata __at (EP1_ADDR) uint8_t Ep1Buffer[]; 37 | 38 | #ifdef __cplusplus 39 | } // extern "C" 40 | #endif 41 | 42 | #endif 43 | 44 | -------------------------------------------------------------------------------- /src/CH552duinoKeyboardCore/USBhandler.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_HANDLER_H__ 2 | #define __USB_HANDLER_H__ 3 | 4 | #include 5 | #include "include/ch5xx.h" 6 | #include "include/ch5xx_usb.h" 7 | #include "USBconstant.h" 8 | 9 | extern __xdata __at (EP0_ADDR) uint8_t Ep0Buffer[]; 10 | extern __xdata __at (EP1_ADDR) uint8_t Ep1Buffer[]; 11 | 12 | extern uint16_t SetupLen; 13 | extern uint8_t SetupReq,UsbConfig; 14 | extern const __code uint8_t *pDescr; 15 | 16 | void USB_EP1_IN(void); 17 | void USB_EP1_OUT(void); 18 | 19 | #define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer) 20 | 21 | // Out 22 | #define EP0_OUT_Callback USB_EP0_OUT 23 | #define EP1_OUT_Callback USB_EP1_OUT 24 | #define EP2_OUT_Callback NOP_Process 25 | #define EP3_OUT_Callback NOP_Process 26 | #define EP4_OUT_Callback NOP_Process 27 | 28 | // SOF 29 | #define EP0_SOF_Callback NOP_Process 30 | #define EP1_SOF_Callback NOP_Process 31 | #define EP2_SOF_Callback NOP_Process 32 | #define EP3_SOF_Callback NOP_Process 33 | #define EP4_SOF_Callback NOP_Process 34 | 35 | // IN 36 | #define EP0_IN_Callback USB_EP0_IN 37 | #define EP1_IN_Callback USB_EP1_IN 38 | #define EP2_IN_Callback NOP_Process 39 | #define EP3_IN_Callback NOP_Process 40 | #define EP4_IN_Callback NOP_Process 41 | 42 | // SETUP 43 | #define EP0_SETUP_Callback USB_EP0_SETUP 44 | #define EP1_SETUP_Callback NOP_Process 45 | #define EP2_SETUP_Callback NOP_Process 46 | #define EP3_SETUP_Callback NOP_Process 47 | #define EP4_SETUP_Callback NOP_Process 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | void USBInterrupt(void); 54 | void USBDeviceCfg(); 55 | void USBDeviceIntCfg(); 56 | void USBDeviceEndPointCfg(); 57 | 58 | #ifdef __cplusplus 59 | } // extern "C" 60 | #endif 61 | 62 | #endif 63 | 64 | -------------------------------------------------------------------------------- /src/CH552duinoKeyboardCore/KeyboardCore.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "./via.h" 3 | #include "./USBHIDKeyboardMouse.h" 4 | #include "../../KeyboardConfig.h" 5 | 6 | uint8_t press_status[ROWS_COUNT]; 7 | 8 | __code uint8_t rows[ROWS_COUNT] = MATRIX_ROWS; 9 | __code uint8_t cols[COLS_COUNT] = MATRIX_COLS; 10 | 11 | void press_key(uint8_t row, uint8_t col, bool press) 12 | { 13 | uint16_t keycode = dynamic_keymap_get_keycode(0,row,col); 14 | uint8_t application = (keycode>>8) & 0x00FF; 15 | 16 | if( application ) 17 | { 18 | switch( application & 0xF0 ) 19 | { 20 | case 0x00: 21 | for(uint8_t i=0;i<4;i++) 22 | { 23 | if( application & (1< 2 | #include 3 | #include "include/ch5xx.h" 4 | #include "include/ch5xx_usb.h" 5 | #include "./USBconstant.h" 6 | #include "./USBhandler.h" 7 | #include "Arduino.h" 8 | #include "USBHIDKeyboardMouse.h" 9 | 10 | #include "../../KeyboardConfig.h" 11 | 12 | enum { 13 | ID_GET_PROTOCOL_VERSION = 0x01, 14 | ID_GET_KEYBOARD_VALUE, 15 | ID_SET_KEYBOARD_VALUE, 16 | ID_KEYMAP_GET_KEYCODE, 17 | ID_KEYMAP_SET_KEYCODE, 18 | ID_KEYMAP_RESET, 19 | ID_LIGHTING_SET_VALUE, 20 | ID_LIGHTING_GET_VALUE, 21 | ID_LIGHTING_SAVE, 22 | ID_EEPROM_RESET, 23 | ID_BOOTLOADER_JUMP, 24 | ID_MACRO_GET_COUNT, 25 | ID_MACRO_GET_BUFFER_SIZE, 26 | ID_MACRO_GET_BUFFER, 27 | ID_MACRO_SET_BUFFER, 28 | ID_MACRO_RESET, 29 | ID_KEYMAP_GET_LAYER_COUNT, 30 | ID_KEYMAP_GET_BUFFER, 31 | ID_KEYMAP_SET_BUFFER, 32 | ID_UNHANDLED = 0xFF, 33 | }; 34 | 35 | uint16_t dynamic_keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) { 36 | uint8_t addr = (layer*ROWS_COUNT*COLS_COUNT) + row*COLS_COUNT*2 + col*2; 37 | return eeprom_read_byte(addr)<<8 | eeprom_read_byte(addr+1); 38 | } 39 | 40 | void dynamic_keymap_set_keycode(void) { 41 | uint8_t addr = (Ep1Buffer[2]*ROWS_COUNT*COLS_COUNT) + Ep1Buffer[3]*COLS_COUNT*2 + Ep1Buffer[4]*2; 42 | eeprom_write_byte(addr, Ep1Buffer[5]); 43 | eeprom_write_byte(addr+1, Ep1Buffer[6]); 44 | } 45 | 46 | 47 | void raw_hid_receive(void) { 48 | uint8_t *ResponseBuf = Ep1Buffer+65; 49 | uint16_t keycode; 50 | 51 | for(uint8_t i=0; i<32; i++) { 52 | ResponseBuf[i] = Ep1Buffer[i+1]; 53 | } 54 | 55 | switch( Ep1Buffer[1] ) { 56 | case ID_GET_PROTOCOL_VERSION: 57 | ResponseBuf[1] = 0; 58 | ResponseBuf[2] = 9; 59 | break; 60 | case ID_GET_KEYBOARD_VALUE: 61 | for(uint8_t i=2; i<32;i++) { 62 | ResponseBuf[i] = 0; 63 | } 64 | break; 65 | case ID_SET_KEYBOARD_VALUE: 66 | break; 67 | case ID_KEYMAP_GET_KEYCODE: 68 | keycode = dynamic_keymap_get_keycode(Ep1Buffer[2], Ep1Buffer[3], Ep1Buffer[4]); 69 | ResponseBuf[4] = keycode>>8 & 0x00FF; 70 | ResponseBuf[5] = keycode & 0x00FF; 71 | break; 72 | case ID_KEYMAP_SET_KEYCODE: 73 | dynamic_keymap_set_keycode(); 74 | break; 75 | case ID_MACRO_GET_COUNT: 76 | ResponseBuf[1] = 0; 77 | break; 78 | case ID_MACRO_GET_BUFFER_SIZE: 79 | ResponseBuf[2] = 0; 80 | ResponseBuf[3] = 0; 81 | break; 82 | case ID_MACRO_GET_BUFFER: 83 | break; 84 | case ID_MACRO_SET_BUFFER: 85 | break; 86 | 87 | case ID_KEYMAP_GET_LAYER_COUNT: 88 | ResponseBuf[1] = 1; 89 | break; 90 | case ID_KEYMAP_GET_BUFFER: 91 | for(uint8_t i=0;i 2 | #include 3 | #include "include/ch5xx.h" 4 | #include "include/ch5xx_usb.h" 5 | #include "USBconstant.h" 6 | #include "USBhandler.h" 7 | #include "USBHIDKeyboardMouse.h" 8 | #include "../../KeyboardConfig.h" 9 | #include "via.h" 10 | 11 | volatile __xdata uint8_t UpPoint1_Busy = 0; //Flag of whether upload pointer is busy 12 | 13 | __xdata uint8_t HIDKey[8] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; 14 | __xdata uint8_t HIDMouse[4] = {0x0,0x0,0x0,0x0}; 15 | 16 | __xdata uint8_t statusLED = 0; 17 | 18 | // to avoid CSEG align issue 19 | __data uint8_t padding = 1; 20 | 21 | typedef void( *pTaskFn)( void ); 22 | 23 | void delayMicroseconds(uint16_t us); 24 | 25 | void USBInit(){ 26 | USBDeviceCfg(); //Device mode configuration 27 | USBDeviceEndPointCfg(); //Endpoint configuration 28 | USBDeviceIntCfg(); //Interrupt configuration 29 | UEP0_T_LEN = 0; 30 | UEP1_T_LEN = 0; //Pre-use send length must be cleared 31 | UEP2_T_LEN = 0; 32 | } 33 | 34 | 35 | void USB_EP1_IN(){ 36 | UEP1_T_LEN = 0; 37 | UEP1_CTRL = (UEP1_CTRL & (~MASK_UEP_T_RES)) | UEP_T_RES_ACK; // Default NAK 38 | UpPoint1_Busy = 0; //Clear busy flag 39 | } 40 | 41 | 42 | void USB_EP1_OUT(){ 43 | if ( U_TOG_OK ) // Discard unsynchronized packets 44 | { 45 | switch(Ep1Buffer[0]) { 46 | case 1: 47 | statusLED = Ep1Buffer[1]; 48 | #ifdef STATUS_LED_FUNCTION 49 | STATUS_LED_FUNCTION(statusLED); 50 | #endif 51 | break; 52 | case 8: 53 | raw_hid_receive(); 54 | break; 55 | default: 56 | break; 57 | } 58 | } 59 | } 60 | 61 | 62 | uint8_t USB_EP1_send(uint8_t reportID){ 63 | uint16_t waitWriteCount = 0; 64 | 65 | waitWriteCount = 0; 66 | while (UpPoint1_Busy){//wait for 250ms or give up 67 | waitWriteCount++; 68 | delayMicroseconds(5); 69 | if (waitWriteCount>=50000) return 0; 70 | } 71 | 72 | if (reportID == 1){ 73 | Ep1Buffer[64+0] = 1; 74 | for (uint8_t i=0;i> 8, 20 | 0x01,0x01,0x00,0x80,0x64, //Configuration descriptor (1 interface) 21 | // Interface 1 (HID) descriptor 22 | 0x09,0x04,0x00,0x00,0x02,0x03,0x01,0x01,0x00, // HID Keyboard, 2 endpoints 23 | 0x09,0x21,0x10,0x01,0x21,0x01,0x22,sizeof(ReportDesc) & 0xff,sizeof(ReportDesc) >> 8, //HID Descriptor 24 | // len=7, endpoint, ep1out, interrupt, 64byte, interval(8ms) 25 | 0x07,0x05,0x01,0x03,0x40,0x00,0x08, //endpoint descriptor 26 | // len=7, endpoint, ep1in, interrupt, 64byte, interval(8ms) 27 | 0x07,0x05,0x81,0x03,0x40,0x00,0x08, //endpoint descriptor 28 | }; 29 | 30 | __code uint16_t ReportDescLen = sizeof(ReportDesc); 31 | 32 | __code uint8_t ReportDesc[] ={ 33 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 34 | 0x09, 0x06, // USAGE (Keyboard) 35 | 0xa1, 0x01, // COLLECTION (Application) 36 | 0x85, 0x01, // REPORT_ID (1) 37 | 0x05, 0x07, // USAGE_PAGE (Keyboard) 38 | 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 39 | 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 40 | 0x15, 0x00, // LOGICAL_MINIMUM (0) 41 | 0x25, 0x01, // LOGICAL_MAXIMUM (1) 42 | 0x95, 0x08, // REPORT_COUNT (8) 43 | 0x75, 0x01, // REPORT_SIZE (1) 44 | 0x81, 0x02, // INPUT (Data,Var,Abs) 45 | 0x95, 0x01, // REPORT_COUNT (1) 46 | 0x75, 0x08, // REPORT_SIZE (8) 47 | 0x81, 0x03, // INPUT (Cnst,Var,Abs) 48 | 0x95, 0x06, // REPORT_COUNT (6) 49 | 0x75, 0x08, // REPORT_SIZE (8) 50 | 0x15, 0x00, // LOGICAL_MINIMUM (0) 51 | 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 52 | 0x05, 0x07, // USAGE_PAGE (Keyboard) 53 | 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 54 | 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 55 | 0x81, 0x00, // INPUT (Data,Ary,Abs) 56 | 0x05, 0x08, // USAGE_PAGE (LEDs) 57 | 0x19, 0x01, // USAGE_MINIMUM (Num Lock) 58 | 0x29, 0x05, // USAGE_MAXIMUM (Kana) 59 | 0x15, 0x00, // LOGICAL_MINIMUM (0) 60 | 0x25, 0x01, // LOGICAL_MAXIMUM (1) 61 | 0x95, 0x05, // REPORT_COUNT (5) 62 | 0x75, 0x01, // REPORT_SIZE (1) 63 | 0x91, 0x02, // OUTPUT (Data,Var,Abs) 64 | 0x95, 0x01, // REPORT_COUNT (1) 65 | 0x75, 0x03, // REPORT_SIZE (3) 66 | 0x91, 0x03, // OUTPUT (Cnst,Var,Abs) 67 | 0xc0, // END_COLLECTION 68 | // Mouse 69 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 70 | 0x09, 0x02, // USAGE (Mouse) 71 | 0xa1, 0x01, // COLLECTION (Application) 72 | 0x09, 0x01, // USAGE (Pointer) 73 | 0xa1, 0x00, // COLLECTION (Physical) 74 | 0x85, 0x02, // REPORT_ID (2) 75 | 0x05, 0x09, // USAGE_PAGE (Button) 76 | 0x19, 0x01, // USAGE_MINIMUM (Button 1) 77 | 0x29, 0x03, // USAGE_MAXIMUM (Button 3) 78 | 0x15, 0x00, // LOGICAL_MINIMUM (0) 79 | 0x25, 0x01, // LOGICAL_MAXIMUM (1) 80 | 0x95, 0x03, // REPORT_COUNT (3) 81 | 0x75, 0x01, // REPORT_SIZE (1) 82 | 0x81, 0x02, // INPUT (Data,Var,Abs) 83 | 0x95, 0x01, // REPORT_COUNT (1) 84 | 0x75, 0x05, // REPORT_SIZE (5) 85 | 0x81, 0x03, // INPUT (Cnst,Var,Abs) 86 | 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 87 | 0x09, 0x30, // USAGE (X) 88 | 0x09, 0x31, // USAGE (Y) 89 | 0x15, 0x81, // LOGICAL_MINIMUM (-127) 90 | 0x25, 0x7f, // LOGICAL_MAXIMUM (127) 91 | 0x75, 0x08, // REPORT_SIZE (8) 92 | 0x95, 0x02, // REPORT_COUNT (2) 93 | 0x81, 0x06, // INPUT (Data,Var,Rel) 94 | 0xc0, // END_COLLECTION 95 | 0xc0 // END_COLLECTION 96 | // RAW HID 97 | , 98 | 0x06, 0x60, 0xFF, 99 | 0x09, 0x61, 100 | 0xa1, 0x01, 101 | 0x85, 8, // Report ID: 8 102 | 0x09, 0x62, 103 | 0x15, 0x00, 104 | 0x26, 0xFF, 0x00, 105 | 0x95, 32, // length: 32 106 | 0x75, 0x08, // size: 8 107 | 0x81, 0x06, // INPUT 108 | 0x09, 0x63, 109 | /* 110 | 0x15, 0x00, 111 | 0x26, 0xFF, 0x00, 112 | 0x95, 32, //REPORT_COUNT(32) 113 | 0x75, 0x08, //REPORT_SIZE(8) 114 | */ 115 | 0x91, 0x83, // OUTPUT 116 | 0xC0 // End Collection (Application) 117 | }; 118 | 119 | __code uint16_t CfgDescLen = sizeof(CfgDesc); 120 | 121 | //String Descriptors 122 | __code uint8_t LangDes[]={0x04,0x03,0x09,0x04}; //Language Descriptor 123 | __code uint16_t LangDesLen = sizeof(LangDes); 124 | __code uint8_t SerDes[]={ //Serial String Descriptor 125 | 0x1c,0x03, 126 | 'C',0x00,'H',0x00,'5',0x00,'5',0x00,'x',0x00,' ',0x00,'k',0x00,'b',0x00,'d',0x00,' ',0x00,'m',0x00,'o',0x00,'s',0x00 127 | }; 128 | __code uint16_t SerDesLen = sizeof(SerDes); 129 | __code uint8_t Prod_Des[]={ //Produce String Descriptor 130 | 0x16,0x03, 131 | 'C',0x00,'H',0x00,'5',0x00,'5',0x00,'x',0x00,'d',0x00, 132 | 'u',0x00,'i',0x00,'n',0x00,'o',0x00, 133 | 'k',0x00,'b',0x00,'d',0x00 134 | }; 135 | __code uint16_t Prod_DesLen = sizeof(Prod_Des); 136 | 137 | __code uint8_t Manuf_Des[]={ 138 | 0x0E,0x03, 139 | 'D',0x00,'e',0x00,'q',0x00,'i',0x00,'n',0x00,'g',0x00, 140 | }; 141 | __code uint16_t Manuf_DesLen = sizeof(Manuf_Des); 142 | -------------------------------------------------------------------------------- /src/CH552duinoKeyboardCore/USBhandler.c: -------------------------------------------------------------------------------- 1 | #include "USBhandler.h" 2 | 3 | #include "USBconstant.h" 4 | 5 | //Keyboard functions: 6 | 7 | void USB_EP2_IN(); 8 | void USB_EP2_OUT(); 9 | 10 | __xdata __at (EP0_ADDR) uint8_t Ep0Buffer[8]; 11 | __xdata __at (EP1_ADDR) uint8_t Ep1Buffer[128]; //on page 47 of data sheet, the receive buffer need to be min(possible packet size+2,64), IN and OUT buffer, must be even address 12 | 13 | #if (EP1_ADDR+128) > USER_USB_RAM 14 | #error "This example needs more USB ram. Increase this setting in menu." 15 | #endif 16 | 17 | uint16_t SetupLen; 18 | uint8_t SetupReq,UsbConfig; 19 | 20 | __code uint8_t *pDescr; 21 | 22 | volatile uint8_t usbMsgFlags=0; // uint8_t usbMsgFlags copied from VUSB 23 | 24 | inline void NOP_Process(void) {} 25 | 26 | void USB_EP0_SETUP(){ 27 | uint8_t len = USB_RX_LEN; 28 | if(len == (sizeof(USB_SETUP_REQ))) 29 | { 30 | SetupLen = ((uint16_t)UsbSetupBuf->wLengthH<<8) | (UsbSetupBuf->wLengthL); 31 | len = 0; // Default is success and upload 0 length 32 | SetupReq = UsbSetupBuf->bRequest; 33 | usbMsgFlags = 0; 34 | if ( ( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )//Not standard request 35 | { 36 | 37 | //here is the commnunication starts, refer to usbFunctionSetup of USBtiny 38 | //or usb_setup in usbtiny 39 | 40 | switch( ( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK )) 41 | { 42 | case USB_REQ_TYP_VENDOR: 43 | { 44 | switch( SetupReq ) 45 | { 46 | default: 47 | len = 0xFF; //command not supported 48 | break; 49 | } 50 | break; 51 | } 52 | case USB_REQ_TYP_CLASS: 53 | { 54 | switch( SetupReq ) 55 | { 56 | default: 57 | len = 0xFF; //command not supported 58 | break; 59 | } 60 | break; 61 | } 62 | default: 63 | len = 0xFF; //command not supported 64 | break; 65 | } 66 | 67 | } 68 | else //Standard request 69 | { 70 | switch(SetupReq) //Request ccfType 71 | { 72 | case USB_GET_DESCRIPTOR: 73 | switch(UsbSetupBuf->wValueH) 74 | { 75 | case 1: //Device Descriptor 76 | pDescr = DevDesc; //Put Device Descriptor into outgoing buffer 77 | len = DevDescLen; 78 | break; 79 | case 2: //Configure Descriptor 80 | pDescr = CfgDesc; 81 | len = CfgDescLen; 82 | break; 83 | case 3: 84 | if(UsbSetupBuf->wValueL == 0) 85 | { 86 | pDescr = LangDes; 87 | len = LangDesLen; 88 | } 89 | else if(UsbSetupBuf->wValueL == 1) 90 | { 91 | pDescr = Manuf_Des; 92 | len = Manuf_DesLen; 93 | } 94 | else if(UsbSetupBuf->wValueL == 2) 95 | { 96 | pDescr = Prod_Des; 97 | len = Prod_DesLen; 98 | } 99 | else if(UsbSetupBuf->wValueL == 3) 100 | { 101 | pDescr = SerDes; 102 | len = SerDesLen; 103 | } 104 | else 105 | { 106 | len = 0xff; 107 | } 108 | break; 109 | case 0x22: 110 | if(UsbSetupBuf->wValueL == 0){ 111 | pDescr = ReportDesc; 112 | len = ReportDescLen; 113 | } 114 | else 115 | { 116 | len = 0xff; 117 | } 118 | break; 119 | default: 120 | len = 0xff; // Unsupported descriptors or error 121 | break; 122 | } 123 | if (len != 0xff){ 124 | if ( SetupLen > len ) 125 | { 126 | SetupLen = len; // Limit length 127 | } 128 | len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; //transmit length for this packet 129 | for (uint8_t i=0;iwValueL; // Save the assigned address 138 | break; 139 | case USB_GET_CONFIGURATION: 140 | Ep0Buffer[0] = UsbConfig; 141 | if ( SetupLen >= 1 ) 142 | { 143 | len = 1; 144 | } 145 | break; 146 | case USB_SET_CONFIGURATION: 147 | UsbConfig = UsbSetupBuf->wValueL; 148 | break; 149 | case USB_GET_INTERFACE: 150 | break; 151 | case USB_SET_INTERFACE: 152 | break; 153 | case USB_CLEAR_FEATURE: //Clear Feature 154 | if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE ) // Clear the device featuee. 155 | { 156 | if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x01 ) 157 | { 158 | if( CfgDesc[ 7 ] & 0x20 ) 159 | { 160 | // wake up 161 | } 162 | else 163 | { 164 | len = 0xFF; //Failed 165 | } 166 | } 167 | else 168 | { 169 | len = 0xFF; //Failed 170 | } 171 | } 172 | else if ( ( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )// endpoint 173 | { 174 | switch( UsbSetupBuf->wIndexL ) 175 | { 176 | case 0x84: 177 | UEP4_CTRL = UEP4_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK; 178 | break; 179 | case 0x04: 180 | UEP4_CTRL = UEP4_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK; 181 | break; 182 | case 0x83: 183 | UEP3_CTRL = UEP3_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK; 184 | break; 185 | case 0x03: 186 | UEP3_CTRL = UEP3_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK; 187 | break; 188 | case 0x82: 189 | UEP2_CTRL = UEP2_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK; 190 | break; 191 | case 0x02: 192 | UEP2_CTRL = UEP2_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK; 193 | break; 194 | case 0x81: 195 | UEP1_CTRL = UEP1_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK; 196 | break; 197 | case 0x01: 198 | UEP1_CTRL = UEP1_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK; 199 | break; 200 | default: 201 | len = 0xFF; // Unsupported endpoint 202 | break; 203 | } 204 | } 205 | else 206 | { 207 | len = 0xFF; // Unsupported for non-endpoint 208 | } 209 | break; 210 | case USB_SET_FEATURE: // Set Feature 211 | if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE ) // Set the device featuee. 212 | { 213 | if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x01 ) 214 | { 215 | if( CfgDesc[ 7 ] & 0x20 ) 216 | { 217 | // suspend 218 | 219 | //while ( XBUS_AUX & bUART0_TX ); //Wait till uart0 sending complete 220 | //SAFE_MOD = 0x55; 221 | //SAFE_MOD = 0xAA; 222 | //WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO | bWAK_RXD1_LO; //wake up by USB or RXD0/1 signal 223 | //PCON |= PD; //sleep 224 | //SAFE_MOD = 0x55; 225 | //SAFE_MOD = 0xAA; 226 | //WAKE_CTRL = 0x00; 227 | } 228 | else 229 | { 230 | len = 0xFF; // Failed 231 | } 232 | } 233 | else 234 | { 235 | len = 0xFF; // Failed 236 | } 237 | } 238 | else if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_ENDP ) //endpoint 239 | { 240 | if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x00 ) 241 | { 242 | switch( ( ( uint16_t )UsbSetupBuf->wIndexH << 8 ) | UsbSetupBuf->wIndexL ) 243 | { 244 | case 0x84: 245 | UEP4_CTRL = UEP4_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;// Set endpoint4 IN STALL 246 | break; 247 | case 0x04: 248 | UEP4_CTRL = UEP4_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;// Set endpoint4 OUT Stall 249 | break; 250 | case 0x83: 251 | UEP3_CTRL = UEP3_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;// Set endpoint3 IN STALL 252 | break; 253 | case 0x03: 254 | UEP3_CTRL = UEP3_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;// Set endpoint3 OUT Stall 255 | break; 256 | case 0x82: 257 | UEP2_CTRL = UEP2_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;// Set endpoint2 IN STALL 258 | break; 259 | case 0x02: 260 | UEP2_CTRL = UEP2_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;// Set endpoint2 OUT Stall 261 | break; 262 | case 0x81: 263 | UEP1_CTRL = UEP1_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;// Set endpoint1 IN STALL 264 | break; 265 | case 0x01: 266 | UEP1_CTRL = UEP1_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;// Set endpoint1 OUT Stall 267 | default: 268 | len = 0xFF; // Failed 269 | break; 270 | } 271 | } 272 | else 273 | { 274 | len = 0xFF; // Failed 275 | } 276 | } 277 | else 278 | { 279 | len = 0xFF; // Failed 280 | } 281 | break; 282 | case USB_GET_STATUS: 283 | Ep0Buffer[0] = 0x00; 284 | Ep0Buffer[1] = 0x00; 285 | if ( SetupLen >= 2 ) 286 | { 287 | len = 2; 288 | } 289 | else 290 | { 291 | len = SetupLen; 292 | } 293 | break; 294 | default: 295 | len = 0xff; // Failed 296 | break; 297 | } 298 | } 299 | } 300 | else 301 | { 302 | len = 0xff; //Wrong packet length 303 | } 304 | if(len == 0xff) 305 | { 306 | SetupReq = 0xFF; 307 | UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL;//STALL 308 | } 309 | else if(len <= DEFAULT_ENDP0_SIZE) // Tx data to host or send 0-length packet 310 | { 311 | UEP0_T_LEN = len; 312 | UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;//Expect DATA1, Answer ACK 313 | } 314 | else 315 | { 316 | UEP0_T_LEN = 0; // Tx data to host or send 0-length packet 317 | UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;//Expect DATA1, Answer ACK 318 | } 319 | } 320 | 321 | void USB_EP0_IN(){ 322 | switch(SetupReq) 323 | { 324 | case USB_GET_DESCRIPTOR: 325 | { 326 | uint8_t len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; //send length 327 | for (uint8_t i=0;i 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 489 | USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random 499 | Hacker. 500 | 501 | , 1 April 1990 502 | Ty Coon, President of Vice 503 | 504 | That's all there is to it! 505 | --------------------------------------------------------------------------------