From d080dedca0219deef426f54a509e6e27474267a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Th=C3=B6rnblad?= Date: Mon, 24 Mar 2025 16:00:41 +0100 Subject: [PATCH] ch552: Add functionality to dynamically control USB endpoints - Make it possible to enable and disable endpoints on demand - Add internal FPGA<->CH552 communication channel (IO_CH552) - Reorder IO endpoint numbering - Rename endpoint from TKEYCTRL to DEBUG and update related variables - Rename endpoint from HID to FIDO and update related variables --- hw/application_fpga/fw/README.md | 10 +- .../ch552_fw/encode_usb_strings.py | 4 +- hw/usb_interface/ch552_fw/inc/ch554_usb.h | 4 +- hw/usb_interface/ch552_fw/inc/io.h | 14 + hw/usb_interface/ch552_fw/inc/main.h | 8 +- hw/usb_interface/ch552_fw/inc/usb_strings.h | 14 +- hw/usb_interface/ch552_fw/src/main.c | 752 ++++++++++-------- hw/usb_interface/ch552_fw/src/print.c | 7 +- 8 files changed, 449 insertions(+), 364 deletions(-) create mode 100644 hw/usb_interface/ch552_fw/inc/io.h diff --git a/hw/application_fpga/fw/README.md b/hw/application_fpga/fw/README.md index 44effb4..27af0c9 100644 --- a/hw/application_fpga/fw/README.md +++ b/hw/application_fpga/fw/README.md @@ -62,11 +62,11 @@ Mode Protocol. It is used in both directions. The different endpoints: -| *Name* | *Value* | *Comment* | -|--------|---------|---------------------------------------------------------------------| -| CTRL | 0x20 | A USB HID special debug pipe. Useful for debug prints. | -| CDC | 0x40 | USB CDC-ACM, a serial port on the client. | -| HID | 0x80 | A USB HID security token device, useful for FIDO-type applications. | +| *Name* | *Value* | *Comment* | +|--------|---------|----------------------------------------------------------------------| +| DEBUG | 0x20 | A USB HID special debug pipe. Useful for debug prints. | +| CDC | 0x40 | USB CDC-ACM, a serial port on the client. | +| FIDO | 0x80 | A USB FIDO security token device, useful for FIDO-type applications. | On top of the USB Mode Protocol is [the TKey Framing Protocol](https://dev.tillitis.se/protocol/) which is described in the diff --git a/hw/usb_interface/ch552_fw/encode_usb_strings.py b/hw/usb_interface/ch552_fw/encode_usb_strings.py index 98c4feb..8b5d9f2 100755 --- a/hw/usb_interface/ch552_fw/encode_usb_strings.py +++ b/hw/usb_interface/ch552_fw/encode_usb_strings.py @@ -53,8 +53,8 @@ if __name__ == "__main__": "SerialDesc": "68de5d27-e223-4874-bc76-a54d6e84068f", "CdcCtrlInterfaceDesc": "CDC-Ctrl", "CdcDataInterfaceDesc": "CDC-Data", - "FidoHidInterfaceDesc": "FIDO-HID", - "TkeyCtrlInterfaceDesc": "TKEY-Ctrl" + "FidoInterfaceDesc": "FIDO", + "DebugInterfaceDesc": "DEBUG" } with open('inc/usb_strings.h', 'w') as f: diff --git a/hw/usb_interface/ch552_fw/inc/ch554_usb.h b/hw/usb_interface/ch552_fw/inc/ch554_usb.h index b9ca5f2..360c910 100644 --- a/hw/usb_interface/ch552_fw/inc/ch554_usb.h +++ b/hw/usb_interface/ch552_fw/inc/ch554_usb.h @@ -195,8 +195,8 @@ Header file for CH554 microcontrollers. #define USB_IDX_SERIAL_STR 0x03 #define USB_IDX_INTERFACE_CDC_CTRL_STR 0x04 #define USB_IDX_INTERFACE_CDC_DATA_STR 0x05 -#define USB_IDX_INTERFACE_FIDO_HID_STR 0x06 -#define USB_IDX_INTERFACE_TKEY_CTRL_STR 0x07 +#define USB_IDX_INTERFACE_FIDO_STR 0x06 +#define USB_IDX_INTERFACE_DEBUG_STR 0x07 #endif #ifndef USB_DEVICE_ADDR diff --git a/hw/usb_interface/ch552_fw/inc/io.h b/hw/usb_interface/ch552_fw/inc/io.h new file mode 100644 index 0000000..dd1d1b5 --- /dev/null +++ b/hw/usb_interface/ch552_fw/inc/io.h @@ -0,0 +1,14 @@ +#ifndef __IO_H__ +#define __IO_H__ + +enum ioend { + IO_NONE = 0x00, // No endpoint + IO_UART = 0x01, // Only destination, raw UART access + IO_QEMU = 0x02, // Only destination, QEMU debug port + IO_CH552 = 0x10, // Internal CH552 control port + IO_DEBUG = 0x20, // HID debug port + IO_CDC = 0x40, // CDC "serial port" + IO_FIDO = 0x80, // FIDO security token port +}; + +#endif diff --git a/hw/usb_interface/ch552_fw/inc/main.h b/hw/usb_interface/ch552_fw/inc/main.h index aa21f8c..e117118 100644 --- a/hw/usb_interface/ch552_fw/inc/main.h +++ b/hw/usb_interface/ch552_fw/inc/main.h @@ -1,14 +1,14 @@ #ifndef __MAIN_H__ #define __MAIN_H__ -#define USE_DEBUG_PRINT /* Enable to print debug messages */ -#define DEBUG_PRINT_SW /* Enable to print debug messages via FPGA */ -//#define DEBUG_PRINT_HW /* Enable to print debug messages via UART0 */ +//#define USE_DEBUG_PRINT /* Enable to print debug messages */ +//#define DEBUG_PRINT_SW /* Enable to print debug messages via FPGA */ +//#define DEBUG_PRINT_HW /* Enable to print debug messages via UART0 */ #define USE_NUM_U8 //#define USE_NUM_U32 -//#define DEBUG_SETUP /* Enable to debug USB setup flow (printStrSetup,printNumU8HexSetup) */ +//#define DEBUG_SETUP /* Enable to debug USB setup flow (printStrSetup,printNumU8HexSetup) */ #define USE_NUM_U8HEX #define USE_NUM_U16HEX diff --git a/hw/usb_interface/ch552_fw/inc/usb_strings.h b/hw/usb_interface/ch552_fw/inc/usb_strings.h index 2302329..a2e295d 100644 --- a/hw/usb_interface/ch552_fw/inc/usb_strings.h +++ b/hw/usb_interface/ch552_fw/inc/usb_strings.h @@ -46,19 +46,17 @@ unsigned char FLASH CdcDataInterfaceDesc[] = { // "CDC-Data" 'D', 0, 'a', 0, 't', 0, 'a', 0, }; -unsigned char FLASH FidoHidInterfaceDesc[] = { // "FIDO-HID" - 18, // Length of this descriptor (in bytes) +unsigned char FLASH FidoInterfaceDesc[] = { // "FIDO" + 10, // Length of this descriptor (in bytes) 0x03, // Descriptor type (String) 'F', 0, 'I', 0, 'D', 0, 'O', 0, - '-', 0, 'H', 0, 'I', 0, 'D', 0, }; -unsigned char FLASH TkeyCtrlInterfaceDesc[] = { // "TKEY-Ctrl" - 20, // Length of this descriptor (in bytes) +unsigned char FLASH DebugInterfaceDesc[] = { // "DEBUG" + 12, // Length of this descriptor (in bytes) 0x03, // Descriptor type (String) - 'T', 0, 'K', 0, 'E', 0, 'Y', 0, - '-', 0, 'C', 0, 't', 0, 'r', 0, - 'l', 0, + 'D', 0, 'E', 0, 'B', 0, 'U', 0, + 'G', 0, }; #endif diff --git a/hw/usb_interface/ch552_fw/src/main.c b/hw/usb_interface/ch552_fw/src/main.c index 588de6f..bddc041 100644 --- a/hw/usb_interface/ch552_fw/src/main.c +++ b/hw/usb_interface/ch552_fw/src/main.c @@ -13,6 +13,7 @@ #include "debug.h" #include "flash.h" +#include "io.h" #include "lib.h" #include "main.h" #include "mem.h" @@ -20,14 +21,14 @@ #include "usb_strings.h" XDATA AT0000 uint8_t Ep0Buffer[3*MAX_PACKET_SIZE] = { 0 }; // Endpoint 0, Default endpoint, OUT & IN buffer[64], must be an even address + - // Endpoint 4, TKEYCTRL, buffer OUT[64]+IN[64], must be an even address -XDATA AT00C0 uint8_t Ep1Buffer[DEFAULT_EP1_SIZE] = { 0 }; // Endpoint 1, CDC Ctrl, IN[8] buffer -XDATA AT00C8 uint8_t Ep2Buffer[2*MAX_PACKET_SIZE] = { 0 }; // Endpoint 2, CDC Data, buffer OUT[64]+IN[64], must be an even address -XDATA AT0148 uint8_t Ep3Buffer[2*MAX_PACKET_SIZE] = { 0 }; // Endpoint 3, HID, buffer OUT[64]+IN[64], must be an even address + // Endpoint 4, DEBUG endpoint, buffer OUT[64]+IN[64], must be an even address +XDATA AT00C0 uint8_t Ep1Buffer[DEFAULT_EP1_SIZE] = { 0 }; // Endpoint 1, CDC Ctrl endpoint, IN[8] buffer +XDATA AT00C8 uint8_t Ep2Buffer[2*MAX_PACKET_SIZE] = { 0 }; // Endpoint 2, CDC Data endpoint, buffer OUT[64]+IN[64], must be an even address +XDATA AT0148 uint8_t Ep3Buffer[2*MAX_PACKET_SIZE] = { 0 }; // Endpoint 3, FIDO endpoint, buffer OUT[64]+IN[64], must be an even address -uint16_t SetupLen = 0; -uint8_t SetupReq = 0; -uint8_t UsbConfig = 0; +IDATA uint16_t SetupLen = 0; +IDATA uint8_t SetupReq = 0; +IDATA uint8_t UsbConfig = 0; const uint8_t *pDescr = NULL; // USB configuration flag #define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer) @@ -44,32 +45,38 @@ const uint8_t *pDescr = NULL; // USB configuration flag #define CDC_DATA_EPIN_ADDR 0x82 // CDC Data Endpoint IN Address #define CDC_DATA_EPIN_SIZE MAX_PACKET_SIZE // CDC Data Endpoint IN Size -#define HID_EPOUT_ADDR 0x03 // HID Endpoint OUT Address -#define HID_EPOUT_SIZE MAX_PACKET_SIZE // HID Endpoint OUT Size +#define FIDO_EPOUT_ADDR 0x03 // FIDO Endpoint OUT Address +#define FIDO_EPOUT_SIZE MAX_PACKET_SIZE // FIDO Endpoint OUT Size -#define HID_EPIN_ADDR 0x83 // HID Endpoint IN Address -#define HID_EPIN_SIZE MAX_PACKET_SIZE // HID Endpoint IN Size +#define FIDO_EPIN_ADDR 0x83 // FIDO Endpoint IN Address +#define FIDO_EPIN_SIZE MAX_PACKET_SIZE // FIDO Endpoint IN Size -#define TKEYCTRL_EPOUT_ADDR 0x04 // TKEYCTRL Endpoint OUT Address -#define TKEYCTRL_EPOUT_SIZE MAX_PACKET_SIZE // TKEYCTRL Endpoint OUT Size +#define DEBUG_EPOUT_ADDR 0x04 // DEBUG Endpoint OUT Address +#define DEBUG_EPOUT_SIZE MAX_PACKET_SIZE // DEBUG Endpoint OUT Size -#define TKEYCTRL_EPIN_ADDR 0x84 // TKEYCTRL Endpoint IN Address -#define TKEYCTRL_EPIN_SIZE MAX_PACKET_SIZE // TKEYCTRL Endpoint IN Size +#define DEBUG_EPIN_ADDR 0x84 // DEBUG Endpoint IN Address +#define DEBUG_EPIN_SIZE MAX_PACKET_SIZE // DEBUG Endpoint IN Size #define CDC_CTRL_FS_BINTERVAL 32 // Gives 32 ms polling interval at Full Speed for interrupt transfers #define CDC_DATA_FS_BINTERVAL 0 // bInterval is ignored for BULK transfers -#define HID_FS_BINTERVAL 2 // Gives 2 ms polling interval at Full Speed for interrupt transfers -#define TKEYCTRL_FS_BINTERVAL 2 // Gives 2 ms polling interval at Full Speed for interrupt transfers +#define FIDO_FS_BINTERVAL 2 // Gives 2 ms polling interval at Full Speed for interrupt transfers +#define DEBUG_FS_BINTERVAL 2 // Gives 2 ms polling interval at Full Speed for interrupt transfers -#define CFGDESC_SIZE 139U // Size of CfgDesc +#define CFG_DESC_SIZE 139U // Size of Cfg_Desc #define NUM_INTERFACES 4 // Number of interfaces -#define HID_REPORT_DESC_SIZE 47 // Size of HID_ReportDesc -#define TKEYCTRL_REPORT_DESC_SIZE 34 // Size of TKEYCTRL_ReportDesc +#define FIDO_REPORT_DESC_SIZE 47 // Size of FidoReportDesc +#define DEBUG_REPORT_DESC_SIZE 34 // Size of DebugReportDesc #define LOBYTE(x) ((uint8_t)( (x) & 0x00FFU)) #define HIBYTE(x) ((uint8_t)(((x) & 0xFF00U) >> 8U)) +IDATA uint8_t FidoInterfaceNum = 0; +IDATA uint8_t DebugInterfaceNum = 0; + +XDATA uint8_t ActiveCfgDesc[CFG_DESC_SIZE]; +XDATA uint8_t ActiveCfgDescSize = 0; + // Device Descriptor FLASH uint8_t DevDesc[] = { 0x12, /* bLength */ @@ -86,9 +93,9 @@ FLASH uint8_t DevDesc[] = { 0x88, /* idProduct */ // PID HIBYTE 0x00, /* bcdDevice (device release number in binary-coded decimal (BCD) format, low byte, i.e. YY) rel. XX.YY */ 0x01, /* bcdDevice (device release number in binary-coded decimal (BCD) format, high byte, i.e. XX) rel. XX.YY */ - 0x01, /* Index of manufacturer string */ - 0x02, /* Index of product string */ - 0x03, /* Index of serial number string */ + USB_IDX_MFC_STR, /* Index of manufacturer string */ + USB_IDX_PRODUCT_STR, /* Index of product string */ + USB_IDX_SERIAL_STR, /* Index of serial number string */ 0x01, /* bNumConfigurations */ }; @@ -97,16 +104,20 @@ FLASH uint8_t CfgDesc[] = { /******************** Configuration Descriptor ********************/ 0x09, /* bLength: Configuration Descriptor size */ USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */ - CFGDESC_SIZE, /* wTotalLength (low byte): Bytes returned */ + CFG_DESC_SIZE, /* wTotalLength (low byte): Bytes returned */ 0x00, /* wTotalLength (high byte): Bytes returned */ - NUM_INTERFACES, /* bNumInterfaces: 4 interfaces (1 CDC Ctrl, 1 CDC Data, 1 HID, 1 HID (TKEYCTRL) ) */ + NUM_INTERFACES, /* bNumInterfaces: 4 interfaces (1 CDC Ctrl, 1 CDC Data, 1 FIDO, 1 DEBUG ) */ 0x01, /* bConfigurationValue: Configuration value */ 0x00, /* iConfiguration: Index of string descriptor describing the configuration */ 0xA0, /* bmAttributes: Bus powered and Support Remote Wake-up */ 0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */ + /* 9 */ +}; + +// CDC Descriptor +FLASH uint8_t CdcDesc[] = { /******************** IAD (Interface Association Descriptor), should be positioned just before the CDC interfaces ********************/ /******************** This is to associate the two CDC interfaces with the CDC class ********************/ - /* 9 */ 0x08, /* bLength: IAD Descriptor size */ USB_DESC_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType: Interface Association */ 0x00, /* bFirstInterface: 0 */ @@ -116,7 +127,7 @@ FLASH uint8_t CfgDesc[] = { 0x01, /* bFunctionProtocol: Common AT commands */ 0x00, /* iFunction: Index of string descriptor */ /******************** Interface 0, CDC Ctrl Descriptor (one endpoint) ********************/ - /* 17 */ + /* 8 */ 0x09, /* bLength: Interface Descriptor size */ USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ 0x00, /* bInterfaceNumber: Number of Interface */ @@ -125,16 +136,16 @@ FLASH uint8_t CfgDesc[] = { USB_DEV_CLASS_CDC_CONTROL, /* bInterfaceClass: Communications and CDC Control */ 0x02, /* bInterfaceSubClass : Abstract Control Model */ 0x01, /* bInterfaceProtocol : AT Commands: V.250 etc */ - 0x04, /* iInterface: Index of string descriptor */ + USB_IDX_INTERFACE_CDC_CTRL_STR, /* iInterface: Index of string descriptor */ /******************** Header Functional Descriptor ********************/ - /* 26 */ + /* 17 */ 0x05, /* bFunctionLength: Size of this descriptor in bytes */ USB_DESC_TYPE_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE (24h) */ 0x00, /* bDescriptorSubtype: Header Functional Descriptor */ 0x10, /* bcdCDC (low byte): CDC version 1.10 */ 0x01, /* bcdCDC (high byte): CDC version 1.10 */ /******************** Call Management Functional Descriptor (no data interface, bmCapabilities=03, bDataInterface=01) ********************/ - /* 31 */ + /* 22 */ 0x05, /* bFunctionLength: Size of this descriptor */ USB_DESC_TYPE_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE (24h) */ 0x01, /* bDescriptorSubtype: Call Management Functional Descriptor */ @@ -146,7 +157,7 @@ FLASH uint8_t CfgDesc[] = { 1 - Device handles call management itself) */ 0x00, /* bDataInterface: Interface number of Data Class interface optionally used for call management */ /******************** Abstract Control Management Functional Descriptor ********************/ - /* 36 */ + /* 27 */ 0x04, /* bLength */ 0x24, /* bDescriptorType: CS_INTERFACE (24h) */ 0x02, /* bDescriptorSubtype: Abstract Control Management Functional Descriptor */ @@ -157,14 +168,14 @@ FLASH uint8_t CfgDesc[] = { D1 : 0x01 (1 - Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State) D0 : 0x00 (1 - Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature) */ /******************** Union Functional Descriptor. CDC Ctrl interface numbered 0; CDC Data interface numbered 1 ********************/ - /* 40 */ + /* 31 */ 0x05, /* bLength */ 0x24, /* bDescriptorType: CS_INTERFACE (24h) */ 0x06, /* bDescriptorSubtype: Union Functional Descriptor */ 0x00, /* bControlInterface: Interface number 0 (Control interface) */ 0x01, /* bSubordinateInterface0: Interface number 1 (Data interface) */ /******************** CDC Ctrl Endpoint descriptor (IN) ********************/ - /* 45 */ + /* 36 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ CDC_CTRL_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */ @@ -173,7 +184,7 @@ FLASH uint8_t CfgDesc[] = { HIBYTE(CDC_CTRL_EPIN_SIZE), /* wMaxPacketSize (high byte): 8 Byte max */ CDC_CTRL_FS_BINTERVAL, /* bInterval: Polling Interval */ /******************** Interface 1, CDC Data Descriptor (two endpoints) ********************/ - /* 52 */ + /* 43 */ 0x09, /* bLength: Interface Descriptor size */ USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ 0x01, /* bInterfaceNumber: Number of Interface */ @@ -182,9 +193,9 @@ FLASH uint8_t CfgDesc[] = { USB_DEV_CLASS_CDC_DATA, /* bInterfaceClass: CDC Data */ 0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ 0x00, /* bInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ - 0x05, /* iInterface: Index of string descriptor */ + USB_IDX_INTERFACE_CDC_DATA_STR, /* iInterface: Index of string descriptor */ /******************** CDC Data Endpoint descriptor (OUT) ********************/ - /* 61 */ + /* 52 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ CDC_DATA_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (OUT) */ @@ -193,7 +204,7 @@ FLASH uint8_t CfgDesc[] = { HIBYTE(CDC_DATA_EPOUT_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */ CDC_DATA_FS_BINTERVAL, /* bInterval: Polling Interval */ /******************** CDC Data Endpoint descriptor (IN) ********************/ - /* 68 */ + /* 59 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ CDC_DATA_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */ @@ -201,8 +212,12 @@ FLASH uint8_t CfgDesc[] = { LOBYTE(CDC_DATA_EPIN_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */ HIBYTE(CDC_DATA_EPIN_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */ CDC_DATA_FS_BINTERVAL, /* bInterval: Polling Interval */ - /******************** Interface 2, HID Descriptor (two endpoints) ********************/ - /* 75 */ + /* 66 */ +}; + +// FIDO Descriptor +FLASH uint8_t FidoDesc[] = { + /******************** Interface 2, FIDO Descriptor (two endpoints) ********************/ 0x09, /* bLength: Interface Descriptor size */ USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ 0x02, /* bInterfaceNumber: Number of Interface */ @@ -211,9 +226,9 @@ FLASH uint8_t CfgDesc[] = { USB_DEV_CLASS_HID, /* bInterfaceClass: Human Interface Device */ 0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ 0x00, /* bInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ - 0x06, /* iInterface: Index of string descriptor */ - /******************** HID Device Descriptor ********************/ - /* 84 */ + USB_IDX_INTERFACE_FIDO_STR, /* iInterface: Index of string descriptor */ + /******************** FIDO Device Descriptor ********************/ + /* 9 */ 0x09, /* bLength: HID Descriptor size */ USB_DESC_TYPE_HID, /* bDescriptorType: HID */ 0x11, /* bcdHID (low byte): HID Class Spec release number */ @@ -221,28 +236,32 @@ FLASH uint8_t CfgDesc[] = { 0x00, /* bCountryCode: Hardware target country */ 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ USB_DESC_TYPE_REPORT, /* bDescriptorType: Report */ - LOBYTE(HID_REPORT_DESC_SIZE), /* wDescriptorLength (low byte): Total length of Report descriptor */ - HIBYTE(HID_REPORT_DESC_SIZE), /* wDescriptorLength (high byte): Total length of Report descriptor */ - /******************** HID Endpoint Descriptor (OUT) ********************/ - /* 93 */ + LOBYTE(FIDO_REPORT_DESC_SIZE), /* wDescriptorLength (low byte): Total length of Report descriptor */ + HIBYTE(FIDO_REPORT_DESC_SIZE), /* wDescriptorLength (high byte): Total length of Report descriptor */ + /******************** FIDO Endpoint Descriptor (OUT) ********************/ + /* 18 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ - HID_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (OUT) */ + FIDO_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (OUT) */ USB_EP_TYPE_INTERRUPT, /* bmAttributes: Interrupt endpoint */ - LOBYTE(HID_EPOUT_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */ - HIBYTE(HID_EPOUT_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */ - HID_FS_BINTERVAL, /* bInterval: Polling Interval */ - /******************** HID Endpoint Descriptor (IN) ********************/ - /* 100 */ + LOBYTE(FIDO_EPOUT_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */ + HIBYTE(FIDO_EPOUT_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */ + FIDO_FS_BINTERVAL, /* bInterval: Polling Interval */ + /******************** FIDO Endpoint Descriptor (IN) ********************/ + /* 25 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ - HID_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */ + FIDO_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */ USB_EP_TYPE_INTERRUPT, /* bmAttributes: Interrupt endpoint */ - LOBYTE(HID_EPIN_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */ - HIBYTE(HID_EPIN_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */ - HID_FS_BINTERVAL, /* bInterval: Polling Interval */ - /******************** Interface 3, HID (TKEYCTRL) Descriptor (two endpoints) ********************/ - /* 107 */ + LOBYTE(FIDO_EPIN_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */ + HIBYTE(FIDO_EPIN_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */ + FIDO_FS_BINTERVAL, /* bInterval: Polling Interval */ + /* 32 */ +}; + +// DEBUG Descriptor +FLASH uint8_t DebugDesc[] = { + /******************** Interface 3, DEBUG Descriptor (two endpoints) ********************/ 0x09, /* bLength: Interface Descriptor size */ USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */ 0x03, /* bInterfaceNumber: Number of Interface */ @@ -251,9 +270,9 @@ FLASH uint8_t CfgDesc[] = { USB_DEV_CLASS_HID, /* bInterfaceClass: Human Interface Device */ 0x00, /* bInterfaceSubClass : 1=BOOT, 0=no boot */ 0x00, /* bInterfaceProtocol : 0=none, 1=keyboard, 2=mouse */ - 0x07, /* iInterface: Index of string descriptor */ - /******************** HID (TKEYCTRL) Device Descriptor ********************/ - /* 116 */ + USB_IDX_INTERFACE_DEBUG_STR, /* iInterface: Index of string descriptor */ + /******************** DEBUG Device Descriptor ********************/ + /* 9 */ 0x09, /* bLength: HID Descriptor size */ USB_DESC_TYPE_HID, /* bDescriptorType: HID */ 0x11, /* bcdHID (low byte): HID Class Spec release number */ @@ -261,31 +280,31 @@ FLASH uint8_t CfgDesc[] = { 0x00, /* bCountryCode: Hardware target country */ 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ USB_DESC_TYPE_REPORT, /* bDescriptorType: Report */ - LOBYTE(TKEYCTRL_REPORT_DESC_SIZE),/* wDescriptorLength (low byte): Total length of Report descriptor */ - HIBYTE(TKEYCTRL_REPORT_DESC_SIZE),/* wDescriptorLength (high byte): Total length of Report descriptor */ - /******************** HID (TKEYCTRL) Endpoint Descriptor (OUT) ********************/ - /* 125 */ + LOBYTE(DEBUG_REPORT_DESC_SIZE), /* wDescriptorLength (low byte): Total length of Report descriptor */ + HIBYTE(DEBUG_REPORT_DESC_SIZE), /* wDescriptorLength (high byte): Total length of Report descriptor */ + /******************** DEBUG Endpoint Descriptor (OUT) ********************/ + /* 18 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ - TKEYCTRL_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (OUT) */ + DEBUG_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (OUT) */ USB_EP_TYPE_INTERRUPT, /* bmAttributes: Interrupt endpoint */ - LOBYTE(TKEYCTRL_EPOUT_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */ - HIBYTE(TKEYCTRL_EPOUT_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */ - TKEYCTRL_FS_BINTERVAL, /* bInterval: Polling Interval */ - /******************** HID (TKEYCTRL) Endpoint Descriptor (IN) ********************/ - /* 132 */ + LOBYTE(DEBUG_EPOUT_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */ + HIBYTE(DEBUG_EPOUT_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */ + DEBUG_FS_BINTERVAL, /* bInterval: Polling Interval */ + /******************** DEBUG Endpoint Descriptor (IN) ********************/ + /* 25 */ 0x07, /* bLength: Endpoint Descriptor size */ USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */ - TKEYCTRL_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */ + DEBUG_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */ USB_EP_TYPE_INTERRUPT, /* bmAttributes: Interrupt endpoint */ - LOBYTE(TKEYCTRL_EPIN_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */ - HIBYTE(TKEYCTRL_EPIN_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */ - TKEYCTRL_FS_BINTERVAL, /* bInterval: Polling Interval */ - /* 139 */ + LOBYTE(DEBUG_EPIN_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */ + HIBYTE(DEBUG_EPIN_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */ + DEBUG_FS_BINTERVAL, /* bInterval: Polling Interval */ + /* 32 */ }; -// HID Device Descriptor (copy from CfgDesc) -FLASH uint8_t HID_CfgDesc[] = { +// FIDO Device Descriptor (copy from FidoDesc) +FLASH uint8_t FidoCfgDesc[] = { 0x09, /* bLength: HID Descriptor size */ USB_DESC_TYPE_HID, /* bDescriptorType: HID */ 0x11, /* bcdHID (low byte): HID Class Spec release number */ @@ -293,11 +312,11 @@ FLASH uint8_t HID_CfgDesc[] = { 0x00, /* bCountryCode: Hardware target country */ 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ USB_DESC_TYPE_REPORT, /* bDescriptorType: Report */ - LOBYTE(HID_REPORT_DESC_SIZE), /* wDescriptorLength (low byte): Total length of Report descriptor */ - HIBYTE(HID_REPORT_DESC_SIZE), /* wDescriptorLength (high byte): Total length of Report descriptor */ + LOBYTE(FIDO_REPORT_DESC_SIZE), /* wDescriptorLength (low byte): Total length of Report descriptor */ + HIBYTE(FIDO_REPORT_DESC_SIZE), /* wDescriptorLength (high byte): Total length of Report descriptor */ }; -FLASH uint8_t HID_ReportDesc[] ={ +FLASH uint8_t FidoReportDesc[] ={ 0x06, 0xD0, 0xF1, /* Usage Page (FIDO Alliance Page) */ 0x09, 0x01, /* Usage (U2F Authenticator Device) */ 0xA1, 0x01, /* Collection (Application) */ @@ -327,8 +346,8 @@ FLASH uint8_t HID_ReportDesc[] ={ /* 47 */ }; -// TKEYCTRL Device Descriptor (copy from CfgDesc) -FLASH uint8_t TKEYCTRL_CfgDesc[] = { +// DEBUG Device Descriptor (copy from DebugDesc) +FLASH uint8_t DebugCfgDesc[] = { 0x09, /* bLength: HID Descriptor size */ USB_DESC_TYPE_HID, /* bDescriptorType: HID */ 0x11, /* bcdHID (low byte): HID Class Spec release number */ @@ -336,31 +355,31 @@ FLASH uint8_t TKEYCTRL_CfgDesc[] = { 0x00, /* bCountryCode: Hardware target country */ 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ USB_DESC_TYPE_REPORT, /* bDescriptorType: Report */ - LOBYTE(TKEYCTRL_REPORT_DESC_SIZE),/* wDescriptorLength (low byte): Total length of Report descriptor */ - HIBYTE(TKEYCTRL_REPORT_DESC_SIZE),/* wDescriptorLength (high byte): Total length of Report descriptor */ + LOBYTE(DEBUG_REPORT_DESC_SIZE), /* wDescriptorLength (low byte): Total length of Report descriptor */ + HIBYTE(DEBUG_REPORT_DESC_SIZE), /* wDescriptorLength (high byte): Total length of Report descriptor */ }; -// TKEYCTRL Report Descriptor -FLASH uint8_t TKEYCTRL_ReportDesc[] ={ - 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */ - 0x09, 0x01, /* Usage (Vendor Usage 1) */ - 0xA1, 0x01, /* Collection (Application) */ +// DEBUG Report Descriptor +FLASH uint8_t DebugReportDesc[] ={ + 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined 0xFF00) */ + 0x09, 0x01, /* Usage (Vendor Usage 1) */ + 0xA1, 0x01, /* Collection (Application) */ /* 7 */ - 0x09, 0x02, /* Usage (Output Report Data), 0x02 defines that the output report carries raw data from the host to the device. */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ - 0x75, 0x08, /* Report Size (8 bits) */ - 0x95, MAX_PACKET_SIZE, /* Report Count (64 bytes) */ - 0x91, 0x02, /* Output (Data, Variable, Absolute) */ + 0x09, 0x02, /* Usage (Output Report Data), 0x02 defines that the output report carries raw data from the host to the device. */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ + 0x75, 0x08, /* Report Size (8 bits) */ + 0x95, MAX_PACKET_SIZE, /* Report Count (64 bytes) */ + 0x91, 0x02, /* Output (Data, Variable, Absolute) */ /* 20 */ - 0x09, 0x03, /* Usage (Input Report), 0x03 defines that the input report carries raw data for the host. */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ - 0x75, 0x08, /* Report Size (8 bits) */ - 0x95, MAX_PACKET_SIZE, /* Report Count (64 bytes) */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ + 0x09, 0x03, /* Usage (Input Report), 0x03 defines that the input report carries raw data for the host. */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ + 0x75, 0x08, /* Report Size (8 bits) */ + 0x95, MAX_PACKET_SIZE, /* Report Count (64 bytes) */ + 0x81, 0x02, /* Input (Data, Variable, Absolute) */ /* 33 */ - 0xC0 /* End Collection */ + 0xC0 /* End Collection */ /* 34 */ }; @@ -372,16 +391,12 @@ FLASH uint8_t LangDesc[] = { }; // CDC Parameters: The initial baud rate is 500000, 1 stop bit, no parity, 8 data bits. -XDATA uint8_t LineCoding[7] = { 0x20, 0xA1, 0x07, 0x00, /* Data terminal rate, in bits per second: 500000 */ +FLASH uint8_t LineCoding[7] = { 0x20, 0xA1, 0x07, 0x00, /* Data terminal rate, in bits per second: 500000 */ 0x00, /* Stop bits: 0 - 1 Stop bit, 1 - 1.5 Stop bits, 2 - 2 Stop bits */ 0x00, /* Parity: 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space */ 0x08, /* Data bits (5, 6, 7, 8 or 16) */ }; -#define TKEYCTRL_FRAME_SIZE 64 -#define HID_FRAME_SIZE 64 -#define MAX_CDC_FRAME_SIZE 64 - #define UART_TX_BUF_SIZE 64 // Serial transmit buffer #define UART_RX_BUF_SIZE 140 // Serial receive buffer @@ -397,49 +412,46 @@ volatile IDATA uint8_t UartRxBufOutputPointer = 0; // Take pointer out of circu volatile IDATA uint8_t UartRxBufByteCount = 0; // Number of unprocessed bytes remaining in the buffer /** Debug UART */ +#ifdef DEBUG_PRINT_HW #define DEBUG_UART_RX_BUF_SIZE 8 XDATA uint8_t DebugUartRxBuf[DEBUG_UART_RX_BUF_SIZE] = { 0 }; volatile IDATA uint8_t DebugUartRxBufInputPointer = 0; volatile IDATA uint8_t DebugUartRxBufOutputPointer = 0; volatile IDATA uint8_t DebugUartRxBufByteCount = 0; +#endif /** Endpoint handling */ volatile IDATA uint8_t UsbEp2ByteCount = 0; // Represents the data received by USB endpoint 2 (CDC) -volatile IDATA uint8_t UsbEp3ByteCount = 0; // Represents the data received by USB endpoint 3 (HID) -volatile IDATA uint8_t UsbEp4ByteCount = 0; // Represents the data received by USB endpoint 4 (TKEYCTRL) +volatile IDATA uint8_t UsbEp3ByteCount = 0; // Represents the data received by USB endpoint 3 (FIDO) +volatile IDATA uint8_t UsbEp4ByteCount = 0; // Represents the data received by USB endpoint 4 (DEBUG) volatile IDATA uint8_t Endpoint2UploadBusy = 0; // Whether the upload endpoint 2 (CDC) is busy -volatile IDATA uint8_t Endpoint3UploadBusy = 0; // Whether the upload endpoint 3 (HID) is busy -volatile IDATA uint8_t Endpoint4UploadBusy = 0; // Whether the upload endpoint 4 (TKEYCTRL) is busy +volatile IDATA uint8_t Endpoint3UploadBusy = 0; // Whether the upload endpoint 3 (FIDO) is busy +volatile IDATA uint8_t Endpoint4UploadBusy = 0; // Whether the upload endpoint 4 (DEBUG) is busy -/** TKEYCTRL variables */ -XDATA uint8_t TkeyCtrlRxBuf[TKEYCTRL_FRAME_SIZE] = { 0 }; -IDATA uint8_t TkeyCtrlRxBufLength = 0; -IDATA uint8_t TkeyCtrlDataAvailable = 0; +/** CH552 variables */ +IDATA uint8_t CH552DataAvailable = 0; + +/** DEBUG variables */ +IDATA uint8_t DebugDataAvailable = 0; /** CDC variables */ -XDATA uint8_t CdcRxBuf[MAX_CDC_FRAME_SIZE] = { 0 }; -IDATA uint8_t CdcRxBufLength = 0; IDATA uint8_t CdcDataAvailable = 0; -/** HID variables */ -XDATA uint8_t HidRxBuf[HID_FRAME_SIZE] = { 0 }; -IDATA uint8_t HidRxBufLength = 0; -IDATA uint8_t HidDataAvailable = 0; +/** FIDO variables */ +IDATA uint8_t FidoDataAvailable = 0; /** Frame data */ +#define MAX_FRAME_SIZE 64 +XDATA uint8_t FrameBuf[MAX_FRAME_SIZE] = { 0 }; +IDATA uint8_t FrameBufLength = 0; -#define MODE_TKEYCTRL 0x20 -#define MODE_CDC 0x40 -#define MODE_HID 0x80 -#define MODE_MASK 0xC0 -#define NUM_MASK 0x3F - -volatile IDATA uint8_t FrameMode = 0; -volatile IDATA uint8_t FrameLength = 0; -volatile IDATA uint8_t FrameRemainingBytes = 0; -volatile IDATA uint8_t FrameStarted = 0; -volatile IDATA uint8_t Halted = 0; +IDATA uint8_t FrameMode = 0; +IDATA uint8_t FrameLength = 0; +IDATA uint8_t FrameRemainingBytes = 0; +IDATA uint8_t FrameStarted = 0; +IDATA uint8_t FrameDiscard = 0; +IDATA uint8_t DiscardDataAvailable = 0; uint32_t increment_pointer(uint32_t pointer, uint32_t increment, uint32_t buffer_size); uint32_t decrement_pointer(uint32_t pointer, uint32_t decrement, uint32_t buffer_size); @@ -516,7 +528,48 @@ void USBDeviceEndPointCfg() UEP2_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK; // Endpoint 2, automatically flips the synchronization flag, IN transaction returns NAK, OUT returns ACK UEP3_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK; // Endpoint 3, automatically flips the synchronization flag, IN transaction returns NAK, OUT returns ACK UEP4_CTRL = UEP_T_RES_NAK | UEP_R_RES_ACK; // Endpoint 4, manual flip, OUT transaction returns ACK, IN transaction returns NAK +} +void CreateCfgDescriptor(uint8_t ep_config) +{ + uint8_t num_iface = 0; // Interface number + + FidoInterfaceNum = 0xFF; // Set as invalid until we have parsed each interface + DebugInterfaceNum = 0xFF; // Set as invalid until we have parsed each interface + + memset(ActiveCfgDesc, 0, CFG_DESC_SIZE); // Clean the descriptor + + uint8_t cfg_desc_size = sizeof(CfgDesc); + memcpy(ActiveCfgDesc, CfgDesc, cfg_desc_size); + ActiveCfgDescSize += cfg_desc_size; + + if (ep_config & IO_CDC) { + uint8_t cdc_desc_size = sizeof(CdcDesc); + memcpy(ActiveCfgDesc + ActiveCfgDescSize, CdcDesc, cdc_desc_size); + num_iface += 2; + ActiveCfgDescSize += cdc_desc_size; + } + + if (ep_config & IO_FIDO) { + uint8_t fido_desc_size = sizeof(FidoDesc); + memcpy(ActiveCfgDesc + ActiveCfgDescSize, FidoDesc, fido_desc_size); + ActiveCfgDesc[ActiveCfgDescSize + 2] = num_iface; + FidoInterfaceNum = num_iface; + num_iface++; + ActiveCfgDescSize += fido_desc_size; + } + + if (ep_config & IO_DEBUG) { + uint8_t debug_desc_size = sizeof(DebugDesc); + memcpy(ActiveCfgDesc + ActiveCfgDescSize, DebugDesc, debug_desc_size); + ActiveCfgDesc[ActiveCfgDescSize + 2] = num_iface; + DebugInterfaceNum = num_iface; + num_iface++; + ActiveCfgDescSize += debug_desc_size; + } + + ActiveCfgDesc[2] = ActiveCfgDescSize; + ActiveCfgDesc[4] = num_iface; } /******************************************************************************* @@ -606,8 +659,8 @@ void usb_irq_setup_handler(void) printStrSetup("DevDesc\n"); break; case USB_DESC_TYPE_CONFIGURATION: // Configuration descriptor - pDescr = CfgDesc; // Send the configuration descriptor to the buffer to be sent - len = sizeof(CfgDesc); + pDescr = ActiveCfgDesc; // Send the configuration descriptor to the buffer to be sent + len = sizeof(ActiveCfgDesc); printStrSetup("CfgDesc\n"); break; case USB_DESC_TYPE_STRING: // String descriptors @@ -635,48 +688,38 @@ void usb_irq_setup_handler(void) pDescr = CdcDataInterfaceDesc; len = sizeof(CdcDataInterfaceDesc); printStrSetup("CdcDataInterfaceDesc\n"); - } else if (UsbSetupBuf->wValueL == USB_IDX_INTERFACE_FIDO_HID_STR) { - pDescr = FidoHidInterfaceDesc; - len = sizeof(FidoHidInterfaceDesc); + } else if (UsbSetupBuf->wValueL == USB_IDX_INTERFACE_FIDO_STR) { + pDescr = FidoInterfaceDesc; + len = sizeof(FidoInterfaceDesc); printStrSetup("FidoHidInterfaceDesc\n"); - } else if (UsbSetupBuf->wValueL == USB_IDX_INTERFACE_TKEY_CTRL_STR) { - pDescr = TkeyCtrlInterfaceDesc; - len = sizeof(TkeyCtrlInterfaceDesc); - printStrSetup("TkeyCtrlInterfaceDesc\n"); + } else if (UsbSetupBuf->wValueL == USB_IDX_INTERFACE_DEBUG_STR) { + pDescr = DebugInterfaceDesc; + len = sizeof(DebugInterfaceDesc); + printStrSetup("DebugInterfaceDesc\n"); } else { printStrSetup("Error: USB_DESC_TYPE_STRING\n"); } break; case USB_DESC_TYPE_HID: - switch (UsbSetupBuf->wIndexL) { - case 0x02: // Interface 2 (HID) - pDescr = HID_CfgDesc; - len = sizeof(HID_CfgDesc); - printStrSetup("HID_CfgDesc\n"); - break; - case 0x03: // Interface 3 (TKEYCTRL) - pDescr = TKEYCTRL_CfgDesc; - len = sizeof(TKEYCTRL_CfgDesc); - printStrSetup("TKEYCTRL_CfgDesc\n"); - break; - default: - break; + if (UsbSetupBuf->wIndexL == FidoInterfaceNum) { // Interface number for FIDO + pDescr = FidoCfgDesc; + len = sizeof(FidoCfgDesc); + printStrSetup("FidoCfgDesc\n"); + } else if (UsbSetupBuf->wIndexL == DebugInterfaceNum) { // Interface number for DEBUG + pDescr = DebugCfgDesc; + len = sizeof(DebugCfgDesc); + printStrSetup("DebugCfgDesc\n"); } break; case USB_DESC_TYPE_REPORT: - switch (UsbSetupBuf->wIndexL) { - case 0x02: // Interface 2 (HID) - pDescr = HID_ReportDesc; - len = sizeof(HID_ReportDesc); - printStrSetup("HID_ReportDesc\n"); - break; - case 0x03: // Interface 3 (TKEYCTRL) - pDescr = TKEYCTRL_ReportDesc; - len = sizeof(TKEYCTRL_ReportDesc); - printStrSetup("TKEYCTRL_ReportDesc\n"); - break; - default: - break; + if (UsbSetupBuf->wIndexL == FidoInterfaceNum) { // Interface number for FIDO + pDescr = FidoReportDesc; + len = sizeof(FidoReportDesc); + printStrSetup("FidoReportDesc\n"); + } else if (UsbSetupBuf->wIndexL == DebugInterfaceNum) { // Interface number for DEBUG + pDescr = DebugReportDesc; + len = sizeof(DebugReportDesc); + printStrSetup("DebugReportDesc\n"); } break; default: @@ -1002,8 +1045,8 @@ void DeviceInterrupt(void)IRQ_USB // USB interrupt service routine, using regist UartRxBufOutputPointer = 0; // Circular buffer read pointer UartRxBufByteCount = 0; // The number of bytes remaining in the current buffer to be fetched UsbEp2ByteCount = 0; // USB endpoint 2 (CDC) received length - UsbEp3ByteCount = 0; // USB endpoint 3 (HID) received length - UsbEp4ByteCount = 0; // USB endpoint 4 (TKEYCTRL) received length + UsbEp3ByteCount = 0; // USB endpoint 3 (FIDO) received length + UsbEp4ByteCount = 0; // USB endpoint 4 (DEBUG) received length Endpoint2UploadBusy = 0; // Clear busy flag Endpoint3UploadBusy = 0; // Clear busy flag Endpoint4UploadBusy = 0; // Clear busy flag @@ -1043,7 +1086,7 @@ void DeviceInterrupt(void)IRQ_USB // USB interrupt service routine, using regist * Function Name : Uart0_ISR() * Description : Serial debug port receiving interrupt function to realize circular buffer receiving *******************************************************************************/ -#if 1 +#ifdef DEBUG_PRINT_HW #ifdef BUILD_CODE #define IRQ_UART0 __interrupt(INT_NO_UART0) #else @@ -1127,7 +1170,6 @@ void circular_copy(uint8_t *dest, uint8_t *src, uint32_t src_size, uint32_t star } } - // Function to increment a pointer and wrap around the buffer uint32_t increment_pointer(uint32_t pointer, uint32_t increment, uint32_t buffer_size) { @@ -1160,20 +1202,29 @@ void check_cts_stop(void) void main() { - // Enable GPIO signalling on p1.4 and p1.5 - gpio_init_p1_4_in(); // Init GPIO p1.4 to input mode for FPGA_CTS - gpio_init_p1_5_out(); // Init GPIO p1.5 to output mode for CH552_CTS - cts_start(); // Signal OK to send - CfgFsys(); // CH559 clock selection configuration mDelaymS(5); // Modify the main frequency and wait for the internal crystal to stabilize, which must be added -#if 0 +#ifdef DEBUG_PRINT_HW mInitSTDIO(); // Serial port 0, can be used for debugging #endif UART1Setup(); // For communication with FPGA UART1Clean(); // Clean register from spurious data - printStr("\n\nStartup...\n"); + printStrSetup("Startup\n"); + + uint8_t ActiveEndpoints = RESET_KEEP; + + // Always enable CDC endpoint + if ((ActiveEndpoints & IO_CDC) == 0x0) { + ActiveEndpoints |= IO_CDC; + } + + // Always enable CH552 endpoint + if ((ActiveEndpoints & IO_CH552) == 0x0) { + ActiveEndpoints |= IO_CH552; + } + + CreateCfgDescriptor(ActiveEndpoints); USBDeviceCfg(); USBDeviceEndPointCfg(); // Endpoint configuration @@ -1185,6 +1236,10 @@ void main() UEP3_T_LEN = 0; // Transmit length must be cleared (Endpoint 3) UEP4_T_LEN = 0; // Transmit length must be cleared (Endpoint 4) + gpio_init_p1_4_in(); // Init GPIO p1.4 to input mode for FPGA_CTS + gpio_init_p1_5_out(); // Init GPIO p1.5 to output mode for CH552_CTS + cts_start(); // Signal OK to send + while (1) { if (UsbConfig) { @@ -1194,31 +1249,31 @@ void main() memcpy(UartTxBuf, Ep2Buffer, Ep2ByteLen); UsbEp2ByteCount = 0; - CH554UART1SendByte(MODE_CDC); // Send CDC mode header + CH554UART1SendByte(IO_CDC); // Send CDC mode header CH554UART1SendByte(Ep2ByteLen); // Send length CH554UART1SendBuffer(UartTxBuf, Ep2ByteLen); UEP2_CTRL = (UEP2_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_ACK; // Enable Endpoint 2 to ACK again } - // Check if Endpoint 3 (HID) has received data + // Check if Endpoint 3 (FIDO) has received data if (UsbEp3ByteCount) { Ep3ByteLen = UsbEp3ByteCount; // UsbEp3ByteCount can be maximum 64 bytes memcpy(UartTxBuf, Ep3Buffer, Ep3ByteLen); UsbEp3ByteCount = 0; - CH554UART1SendByte(MODE_HID); // Send HID mode header + CH554UART1SendByte(IO_FIDO); // Send FIDO mode header CH554UART1SendByte(Ep3ByteLen); // Send length (always 64 bytes) CH554UART1SendBuffer(UartTxBuf, Ep3ByteLen); UEP3_CTRL = (UEP3_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_ACK; // Enable Endpoint 3 to ACK again } - // Check if Endpoint 4 (TKEYCTRL) has received data + // Check if Endpoint 4 (DEBUG) has received data if (UsbEp4ByteCount) { Ep4ByteLen = UsbEp4ByteCount; // UsbEp4ByteCount can be maximum 64 bytes memcpy(UartTxBuf, Ep0Buffer+64, Ep4ByteLen); // Endpoint 4 receive is at address UEP0_DMA+64 UsbEp4ByteCount = 0; - CH554UART1SendByte(MODE_TKEYCTRL); // Send TKEYCTRL mode header + CH554UART1SendByte(IO_DEBUG); // Send DEBUG mode header CH554UART1SendByte(Ep4ByteLen); // Send length (always 64 bytes) CH554UART1SendBuffer(UartTxBuf, Ep4ByteLen); UEP4_CTRL = (UEP4_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_ACK; // Enable Endpoint 4 to ACK again @@ -1228,9 +1283,11 @@ void main() if ((UartRxBufByteCount >= 2) && !FrameStarted) { // If we have data and the header is not yet validated FrameMode = UartRxBuf[UartRxBufOutputPointer]; // Extract frame mode - if ((FrameMode == MODE_CDC) || - (FrameMode == MODE_HID) || - (FrameMode == MODE_TKEYCTRL)) { + if ((FrameMode == IO_CDC) || + (FrameMode == IO_FIDO) || + (FrameMode == IO_DEBUG) || + (FrameMode == IO_CH552)) { + FrameLength = UartRxBuf[increment_pointer(UartRxBufOutputPointer, 1, UART_RX_BUF_SIZE)]; // Extract frame length @@ -1240,63 +1297,52 @@ void main() UART_RX_BUF_SIZE); // Start at valid data so skip the mode and length byte UartRxBufByteCount -= 2; // Subtract the frame mode and frame length bytes from the total byte count FrameStarted = 1; - } else { // Invalid mode - if (!Halted) { - printStr("Invalid header: 0x"); - printNumU8Hex(FrameMode); - printStr(", len = "); - printNumU8Hex(UartRxBuf[increment_pointer(UartRxBufOutputPointer, - 1, - UART_RX_BUF_SIZE)]); - printStr("\n"); - uint16_t i; - uint8_t print_char_count_out = 0; - for (i=0; i= 16) { - printStr("\n"); - print_char_count_out = 0; - } - } - if (print_char_count_out != 0) { - printStr("\n"); - } - printStr("Halting!\n"); - Halted = 1; + + // Mark that we should discard data if destination for the frame is not active + if ((FrameMode & ActiveEndpoints) == 0) { + FrameDiscard = 1; } + + } else { // Invalid frame mode + + cts_stop(); + + // Reset CH552 to start from a known state + SAFE_MOD = 0x55; + SAFE_MOD = 0xAA; + GLOBAL_CFG = bSW_RESET; + while (1) + ; } } - // Copy CDC data from UartRxBuf to CdcRxBuf - if (FrameStarted && !CdcDataAvailable) { - if (FrameMode == MODE_CDC) { - if ((FrameRemainingBytes >= MAX_PACKET_SIZE) && - (UartRxBufByteCount >= MAX_PACKET_SIZE)) { - circular_copy(CdcRxBuf, + // Copy CDC data from UartRxBuf to FrameBuf + if (FrameStarted && !FrameDiscard && !CdcDataAvailable) { + if (FrameMode == IO_CDC) { + if ((FrameRemainingBytes >= MAX_FRAME_SIZE) && + (UartRxBufByteCount >= MAX_FRAME_SIZE)) { + circular_copy(FrameBuf, UartRxBuf, UART_RX_BUF_SIZE, UartRxBufOutputPointer, - MAX_PACKET_SIZE); - CdcRxBufLength = MAX_PACKET_SIZE; + MAX_FRAME_SIZE); + FrameBufLength = MAX_FRAME_SIZE; // Update output pointer UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer, - MAX_PACKET_SIZE, + MAX_FRAME_SIZE, UART_RX_BUF_SIZE); - FrameRemainingBytes -= MAX_PACKET_SIZE; + FrameRemainingBytes -= MAX_FRAME_SIZE; CdcDataAvailable = 1; cts_start(); } - else if ((FrameRemainingBytes < MAX_PACKET_SIZE) && + else if ((FrameRemainingBytes < MAX_FRAME_SIZE) && (UartRxBufByteCount >= FrameRemainingBytes)) { - circular_copy(CdcRxBuf, + circular_copy(FrameBuf, UartRxBuf, UART_RX_BUF_SIZE, UartRxBufOutputPointer, FrameRemainingBytes); - CdcRxBufLength = FrameRemainingBytes; + FrameBufLength = FrameRemainingBytes; // Update output pointer UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer, FrameRemainingBytes, @@ -1308,79 +1354,141 @@ void main() } } - // Copy HID data from UartRxBuf to HidRxBuf - if (FrameStarted && !HidDataAvailable) { - if (FrameMode == MODE_HID) { + // Copy FIDO data from UartRxBuf to FrameBuf + if (FrameStarted && !FrameDiscard && !FidoDataAvailable) { + if (FrameMode == IO_FIDO) { // Check if a complete frame has been received if (UartRxBufByteCount >= FrameRemainingBytes) { - circular_copy(HidRxBuf, + circular_copy(FrameBuf, UartRxBuf, UART_RX_BUF_SIZE, UartRxBufOutputPointer, FrameRemainingBytes); - HidRxBufLength = MAX_PACKET_SIZE; + FrameBufLength = MAX_FRAME_SIZE; // Update output pointer UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer, FrameRemainingBytes, UART_RX_BUF_SIZE); - HidDataAvailable = 1; + FidoDataAvailable = 1; cts_start(); } } } - // Copy TKEYCTRL data from UartRxBuf to TkeyCtrlRxBuf - if (FrameStarted && !TkeyCtrlDataAvailable) { - if (FrameMode == MODE_TKEYCTRL) { - if ((FrameRemainingBytes >= MAX_PACKET_SIZE) && - (UartRxBufByteCount >= MAX_PACKET_SIZE)) { - circular_copy(TkeyCtrlRxBuf, + // Copy DEBUG data from UartRxBuf to FrameBuf + if (FrameStarted && !FrameDiscard && !DebugDataAvailable) { + if (FrameMode == IO_DEBUG) { + if ((FrameRemainingBytes >= MAX_FRAME_SIZE) && + (UartRxBufByteCount >= MAX_FRAME_SIZE)) { + circular_copy(FrameBuf, UartRxBuf, UART_RX_BUF_SIZE, UartRxBufOutputPointer, - MAX_PACKET_SIZE); - TkeyCtrlRxBufLength = MAX_PACKET_SIZE; + MAX_FRAME_SIZE); + FrameBufLength = MAX_FRAME_SIZE; // Update output pointer UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer, - MAX_PACKET_SIZE, + MAX_FRAME_SIZE, UART_RX_BUF_SIZE); - FrameRemainingBytes -= MAX_PACKET_SIZE; - TkeyCtrlDataAvailable = 1; + FrameRemainingBytes -= MAX_FRAME_SIZE; + DebugDataAvailable = 1; cts_start(); } - else if ((FrameRemainingBytes < MAX_PACKET_SIZE) && + else if ((FrameRemainingBytes < MAX_FRAME_SIZE) && (UartRxBufByteCount >= FrameRemainingBytes)) { - circular_copy(TkeyCtrlRxBuf, + circular_copy(FrameBuf, UartRxBuf, UART_RX_BUF_SIZE, UartRxBufOutputPointer, FrameRemainingBytes); - TkeyCtrlRxBufLength = FrameRemainingBytes; + FrameBufLength = FrameRemainingBytes; // Update output pointer UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer, FrameRemainingBytes, UART_RX_BUF_SIZE); FrameRemainingBytes -= FrameRemainingBytes; - TkeyCtrlDataAvailable = 1; + DebugDataAvailable = 1; cts_start(); } } } + // Copy CH552 data from UartRxBuf to FrameBuf + if (FrameStarted && !FrameDiscard && !CH552DataAvailable) { + if (FrameMode == IO_CH552) { + if ((FrameRemainingBytes >= MAX_FRAME_SIZE) && + (UartRxBufByteCount >= MAX_FRAME_SIZE)) { + circular_copy(FrameBuf, + UartRxBuf, + UART_RX_BUF_SIZE, + UartRxBufOutputPointer, + MAX_FRAME_SIZE); + FrameBufLength = MAX_FRAME_SIZE; + // Update output pointer + UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer, + MAX_FRAME_SIZE, + UART_RX_BUF_SIZE); + FrameRemainingBytes -= MAX_FRAME_SIZE; + CH552DataAvailable = 1; + cts_start(); + } + else if ((FrameRemainingBytes < MAX_FRAME_SIZE) && + (UartRxBufByteCount >= FrameRemainingBytes)) { + circular_copy(FrameBuf, + UartRxBuf, + UART_RX_BUF_SIZE, + UartRxBufOutputPointer, + FrameRemainingBytes); + FrameBufLength = FrameRemainingBytes; + // Update output pointer + UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer, + FrameRemainingBytes, + UART_RX_BUF_SIZE); + FrameRemainingBytes -= FrameRemainingBytes; + CH552DataAvailable = 1; + cts_start(); + } + } + } + + // Discard frame + if (FrameStarted && FrameDiscard && !DiscardDataAvailable) { + if ((FrameRemainingBytes >= MAX_FRAME_SIZE) && + (UartRxBufByteCount >= MAX_FRAME_SIZE)) { + // Update output pointer + UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer, + MAX_FRAME_SIZE, + UART_RX_BUF_SIZE); + FrameRemainingBytes -= MAX_FRAME_SIZE; + DiscardDataAvailable = 1; + cts_start(); + } + else if ((FrameRemainingBytes < MAX_FRAME_SIZE) && + (UartRxBufByteCount >= FrameRemainingBytes)) { + // Update output pointer + UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer, + FrameRemainingBytes, + UART_RX_BUF_SIZE); + FrameRemainingBytes -= FrameRemainingBytes; + DiscardDataAvailable = 1; + cts_start(); + } + } + // Check if we should upload data to Endpoint 2 (CDC) if (CdcDataAvailable && !Endpoint2UploadBusy) { // Write upload endpoint memcpy(Ep2Buffer + MAX_PACKET_SIZE, /* Copy to IN buffer of Endpoint 2 */ - CdcRxBuf, - CdcRxBufLength); + FrameBuf, + FrameBufLength); Endpoint2UploadBusy = 1; // Set busy flag - UEP2_T_LEN = CdcRxBufLength; // Set the number of data bytes that Endpoint 2 is ready to send + UEP2_T_LEN = FrameBufLength; // Set the number of data bytes that Endpoint 2 is ready to send UEP2_CTRL = (UEP2_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK; // Answer ACK CdcDataAvailable = 0; - CdcRxBufLength = 0; + FrameBufLength = 0; if (FrameRemainingBytes == 0) { // Complete frame sent, get next header and data @@ -1388,46 +1496,47 @@ void main() } } - // Check if we should upload data to Endpoint 3 (HID) - if (HidDataAvailable && !Endpoint3UploadBusy) { + // Check if we should upload data to Endpoint 3 (FIDO) + if (FidoDataAvailable && !Endpoint3UploadBusy) { // Write upload endpoint memcpy(Ep3Buffer + MAX_PACKET_SIZE, /* Copy to IN buffer of Endpoint 3 */ - HidRxBuf, - HidRxBufLength); + FrameBuf, + FrameBufLength); Endpoint3UploadBusy = 1; // Set busy flag UEP3_T_LEN = MAX_PACKET_SIZE; // Set the number of data bytes that Endpoint 3 is ready to send UEP3_CTRL = (UEP3_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK; // Answer ACK - HidDataAvailable = 0; + FidoDataAvailable = 0; + FrameBufLength = 0; // Get next header and data FrameStarted = 0; } - // Check if we should upload data to Endpoint 4 (TKEYCTRL) - if (TkeyCtrlDataAvailable && !Endpoint4UploadBusy) { + // Check if we should upload data to Endpoint 4 (DEBUG) + if (DebugDataAvailable && !Endpoint4UploadBusy) { - if (TkeyCtrlRxBufLength == MAX_PACKET_SIZE) { + if (FrameBufLength == MAX_PACKET_SIZE) { // Write upload endpoint memcpy(Ep0Buffer + 128, /* Copy to IN (TX) buffer of Endpoint 4 */ - TkeyCtrlRxBuf, - TkeyCtrlRxBufLength); + FrameBuf, + FrameBufLength); } else { memset(Ep0Buffer + 128, 0, MAX_PACKET_SIZE); // Write upload endpoint memcpy(Ep0Buffer + 128, /* Copy to IN (TX) buffer of Endpoint 4 */ - TkeyCtrlRxBuf, - TkeyCtrlRxBufLength); + FrameBuf, + FrameBufLength); } Endpoint4UploadBusy = 1; // Set busy flag UEP4_T_LEN = MAX_PACKET_SIZE; // Set the number of data bytes that Endpoint 4 is ready to send UEP4_CTRL = (UEP4_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_ACK; // Answer ACK - TkeyCtrlDataAvailable = 0; - TkeyCtrlRxBufLength = 0; + DebugDataAvailable = 0; + FrameBufLength = 0; if (FrameRemainingBytes == 0) { // Complete frame sent, get next header and data @@ -1435,88 +1544,53 @@ void main() } } -#if 0 - DebugUartRxBufByteCount = debug_uart_byte_count(); - if (DebugUartRxBufByteCount) { - switch(DebugUartRxBuf[DebugUartRxBufOutputPointer]) { - case 'h': - printStr("h Show help\n"); - printStr("r Reset UART1\n"); - printStr("s Show status\n"); + // Check if we should handle CH552 data + if (CH552DataAvailable) { + + switch(FrameBuf[0]) { + + case 0x01: { // Enable endpoints + cts_stop(); // Stop UART data from FPGA + RESET_KEEP = FrameBuf[1]; // Save endpoints to persistent register + SAFE_MOD = 0x55; // Start reset sequence + SAFE_MOD = 0xAA; + GLOBAL_CFG = bSW_RESET; + while (1) + ; + } break; - case 'r': - /** UART */ - UartRxBufInputPointer = 0; - UartRxBufOutputPointer = 0; - /** Frame */ - FrameMode = 0; - FrameLength = 0; - FrameStarted = 0; - /** CDC */ - CdcDataAvailable = 0; - CdcRxBufLength = 0; - CdcLoopCount = 0; - /** HID */ - HidDataAvailable = 0; - /** Timeout */ - LoopCounter = 0; - LastReceiveCounter = 0; - /** Endpoints */ - UEP2_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK; - UEP3_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK; - UEP4_CTRL = UEP_T_RES_NAK | UEP_R_RES_ACK; - UIF_TRANSFER = 0; // Writing 0 clears the interrupt - UIF_BUS_RST = 0; // Clear interrupt flag - Endpoint2UploadBusy = 0; - Endpoint3UploadBusy = 0; - UsbEp2ByteCount = 0; // USB endpoint 2 (CDC) received length - UsbEp3ByteCount = 0; // USB endpoint 3 (HID) received length - - /** Misc */ - Halted = 0; - printStr("Reset done!\n"); + default: { + } break; - case 's': - printStr("Endpoint2UploadBusy = "); printNumU32(Endpoint2UploadBusy); printStr("\n"); - printStr("UsbEp2ByteCount = "); printNumU32(UsbEp2ByteCount); printStr("\n"); - printStr("UEP2_CTRL = 0x"); printNumHex(UEP2_CTRL); printStr("\n"); - - printStr("Endpoint3UploadBusy = "); printNumU32(Endpoint3UploadBusy); printStr("\n"); - printStr("UsbEp3ByteCount = "); printNumU32(UsbEp3ByteCount); printStr("\n"); - printStr("UEP3_CTRL = 0x"); printNumHex(UEP3_CTRL); printStr("\n"); - - printStr("Endpoint4UploadBusy = "); printNumU32(Endpoint4UploadBusy); printStr("\n"); - printStr("UsbEp4ByteCount = "); printNumU32(UsbEp4ByteCount); printStr("\n"); - printStr("UEP4_CTRL = 0x"); printNumHex(UEP4_CTRL); printStr("\n"); - - printStr("UartRxBufInputPointer = "); printNumU32(UartRxBufInputPointer); printStr("\n"); - printStr("UartRxBufOutputPointer = "); printNumU32(UartRxBufOutputPointer); printStr("\n"); - - printStr("UartRxBufByteCount = "); printNumU32(UartRxBufByteCount); printStr("\n"); - printStr("FrameMode = 0x"); printNumHex(FrameMode); printStr("\n"); - printStr("FrameLength = "); printNumU32(FrameLength); printStr("\n"); - printStr("FrameStarted = "); printNumU32(FrameStarted); printStr("\n"); - - printStr("CdcDataAvailable = "); printNumU32(CdcDataAvailable); printStr("\n"); - printStr("HidDataAvailable = "); printNumU32(HidDataAvailable); printStr("\n"); - - printStr("Halted = "); printNumU32(Halted); printStr("\n"); - break; - - default: - printStr("\n"); - break; } - // Update out pointer - DebugUartRxBufOutputPointer = increment_pointer(DebugUartRxBufOutputPointer, - DebugUartRxBufByteCount, - DEBUG_UART_RX_BUF_SIZE); + CH552DataAvailable = 0; + FrameBufLength = 0; + + memset(FrameBuf, 0, MAX_FRAME_SIZE); + + if (FrameRemainingBytes == 0) { + // Complete frame sent, get next header and data + FrameStarted = 0; + } } -#endif + + if (DiscardDataAvailable) { + + DiscardDataAvailable = 0; + printStr("Frame discarded!\n"); + + if (FrameRemainingBytes == 0) { + // Complete frame discarded, get next header and data + FrameStarted = 0; + // Stop discarding frames + FrameDiscard = 0; + } + } + } /* END if (UsbConfig) */ } /* END while (1) */ } diff --git a/hw/usb_interface/ch552_fw/src/print.c b/hw/usb_interface/ch552_fw/src/print.c index 11c9cc8..9cc0a92 100644 --- a/hw/usb_interface/ch552_fw/src/print.c +++ b/hw/usb_interface/ch552_fw/src/print.c @@ -2,13 +2,12 @@ #include #include "debug.h" +#include "io.h" #include "lib.h" #include "main.h" #include "mem.h" #include "print.h" -#define MODE_CH552 0x10 - void printStr(uint8_t *str) { #ifdef USE_DEBUG_PRINT @@ -19,7 +18,7 @@ void printStr(uint8_t *str) } #elif defined(DEBUG_PRINT_SW) uint32_t str_len = strlen(str); - CH554UART1SendByte(MODE_CH552); + CH554UART1SendByte(IO_CH552); CH554UART1SendByte(str_len); CH554UART1SendBuffer(str, str_len); #endif @@ -34,7 +33,7 @@ void printChar(uint8_t c) #if defined(DEBUG_PRINT_HW) CH554UART0SendByte(c); #elif defined(DEBUG_PRINT_SW) - CH554UART1SendByte(MODE_CH552); + CH554UART1SendByte(IO_CH552); CH554UART1SendByte(1); CH554UART1SendByte(c); #endif