mirror of
https://github.com/tillitis/tillitis-key1.git
synced 2025-02-11 12:28:27 -05:00
![Jonas Thörnblad](/assets/img/avatar_default.png)
Set UART1 IRQ to high priority to not miss any incoming bytes and tune USB polling period (bInterval).
1525 lines
79 KiB
C
1525 lines
79 KiB
C
/********************************** (C) COPYRIGHT *******************************
|
|
* File Name : CDC.C
|
|
* Author : WCH
|
|
* Version : V1.0
|
|
* Date : 2017/03/01
|
|
* Description : CH554 as CDC device to serial port, select serial port 1
|
|
*******************************************************************************/
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include <ch554.h>
|
|
#include <ch554_usb.h>
|
|
|
|
#include "debug.h"
|
|
#include "mem.h"
|
|
#include "print.h"
|
|
#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
|
|
|
|
uint16_t SetupLen = 0;
|
|
uint8_t SetupReq = 0;
|
|
uint8_t UsbConfig = 0;
|
|
const uint8_t *pDescr = NULL; // USB configuration flag
|
|
USB_SETUP_REQ SetupReqBuf = { 0 }; // Temporary Setup package
|
|
|
|
#define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer)
|
|
|
|
#define CDC_CTRL_EPOUT_ADDR 0x01 // CDC Ctrl Endpoint OUT Address
|
|
#define CDC_CTRL_EPOUT_SIZE DEFAULT_EP1_SIZE // CDC Ctrl Endpoint OUT Size
|
|
|
|
#define CDC_CTRL_EPIN_ADDR 0x81 // CDC Ctrl Endpoint IN Address
|
|
#define CDC_CTRL_EPIN_SIZE DEFAULT_EP1_SIZE // CDC Ctrl Endpoint IN Size
|
|
|
|
#define CDC_DATA_EPOUT_ADDR 0x02 // CDC Data Endpoint OUT Address
|
|
#define CDC_DATA_EPOUT_SIZE MAX_PACKET_SIZE // CDC Data Endpoint OUT Size
|
|
|
|
#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 HID_EPIN_ADDR 0x83 // HID Endpoint IN Address
|
|
#define HID_EPIN_SIZE MAX_PACKET_SIZE // HID Endpoint IN Size
|
|
|
|
#define TKEYCTRL_EPOUT_ADDR 0x04 // TKEYCTRL Endpoint OUT Address
|
|
#define TKEYCTRL_EPOUT_SIZE MAX_PACKET_SIZE // TKEYCTRL Endpoint OUT Size
|
|
|
|
#define TKEYCTRL_EPIN_ADDR 0x84 // TKEYCTRL Endpoint IN Address
|
|
#define TKEYCTRL_EPIN_SIZE MAX_PACKET_SIZE // TKEYCTRL 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 CFGDESC_SIZE 139U // Size of CfgDesc
|
|
#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 LOBYTE(x) ((uint8_t)( (x) & 0x00FFU))
|
|
#define HIBYTE(x) ((uint8_t)(((x) & 0xFF00U) >> 8U))
|
|
|
|
// Device Descriptor
|
|
FLASH uint8_t DevDesc[] = {
|
|
0x12, /* bLength */
|
|
USB_DESC_TYPE_DEVICE, /* bDescriptorType: Device */
|
|
0x00, /* bcdUSB (low byte), USB Specification Release Number in Binary-Coded Decimal (2.0 is 200h) */
|
|
0x02, /* bcdUSB (high byte) USB Specification Release Number in Binary-Coded Decimal (2.0 is 200h) */
|
|
USB_DEV_CLASS_MISCELLANEOUS, /* bDeviceClass: Miscellaneous Device Class (Composite) */
|
|
0x02, /* bDeviceSubClass: Common Class */
|
|
0x01, /* bDeviceProtocol: IAD (Interface Association Descriptor) */
|
|
DEFAULT_EP0_SIZE, /* bMaxPacketSize */
|
|
0x07, /* idVendor */ // VID LOBYTE
|
|
0x12, /* idVendor */ // VID HIBYTE
|
|
0x87, /* idProduct */ // PID LOBYTE
|
|
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 */
|
|
0x01, /* bNumConfigurations */
|
|
};
|
|
|
|
// Configuration Descriptor
|
|
FLASH uint8_t CfgDesc[] = {
|
|
/******************** Configuration Descriptor ********************/
|
|
0x09, /* bLength: Configuration Descriptor size */
|
|
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
|
|
CFGDESC_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) ) */
|
|
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 */
|
|
/******************** 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 */
|
|
0x02, /* bInterfaceCount: 2 */
|
|
0x02, /* bFunctionClass: Communications & CDC Control */
|
|
0x02, /* bFunctionSubClass: Abstract Control Model */
|
|
0x01, /* bFunctionProtocol: Common AT commands */
|
|
0x00, /* iFunction: Index of string descriptor */
|
|
/******************** Interface 0, CDC Ctrl Descriptor (one endpoint) ********************/
|
|
/* 17 */
|
|
0x09, /* bLength: Interface Descriptor size */
|
|
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
|
|
0x00, /* bInterfaceNumber: Number of Interface */
|
|
0x00, /* bAlternateSetting: Alternate setting */
|
|
0x01, /* bNumEndpoints */
|
|
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 */
|
|
/******************** Header Functional Descriptor ********************/
|
|
/* 26 */
|
|
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 */
|
|
0x05, /* bFunctionLength: Size of this descriptor */
|
|
USB_DESC_TYPE_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE (24h) */
|
|
0x01, /* bDescriptorSubtype: Call Management Functional Descriptor */
|
|
0x00, /* bmCapabilities:
|
|
D7..2: 0x00 (RESERVED,
|
|
D1 : 0x00 (0 - Device sends/receives call management information only over the Communications Class interface
|
|
1 - Device can send/receive call management information over a Data Class interface)
|
|
D0 : 0x00 (0 - Device does not handle call management itself
|
|
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 */
|
|
0x04, /* bLength */
|
|
0x24, /* bDescriptorType: CS_INTERFACE (24h) */
|
|
0x02, /* bDescriptorSubtype: Abstract Control Management Functional Descriptor */
|
|
0x02, /* bmCapabilities:
|
|
D7..4: 0x00 (RESERVED, Reset to zero)
|
|
D3 : 0x00 (1 - Device supports the notification Network_Connection)
|
|
D2 : 0x00 (1 - Device supports the request Send_Break)
|
|
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 */
|
|
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 */
|
|
0x07, /* bLength: Endpoint Descriptor size */
|
|
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
|
CDC_CTRL_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
|
|
USB_EP_TYPE_INTERRUPT, /* bmAttributes: Interrupt Endpoint */
|
|
LOBYTE(CDC_CTRL_EPIN_SIZE), /* wMaxPacketSize (low byte): 8 Byte max */
|
|
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 */
|
|
0x09, /* bLength: Interface Descriptor size */
|
|
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
|
|
0x01, /* bInterfaceNumber: Number of Interface */
|
|
0x00, /* bAlternateSetting: Alternate setting */
|
|
0x02, /* bNumEndpoints */
|
|
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 */
|
|
/******************** CDC Data Endpoint descriptor (OUT) ********************/
|
|
/* 61 */
|
|
0x07, /* bLength: Endpoint Descriptor size */
|
|
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
|
CDC_DATA_EPOUT_ADDR, /* bEndpointAddress: Endpoint Address (OUT) */
|
|
USB_EP_TYPE_BULK, /* bmAttributes: Bulk Endpoint */
|
|
LOBYTE(CDC_DATA_EPOUT_SIZE), /* wMaxPacketSize (low byte): 64 Byte max */
|
|
HIBYTE(CDC_DATA_EPOUT_SIZE), /* wMaxPacketSize (high byte): 64 Byte max */
|
|
CDC_DATA_FS_BINTERVAL, /* bInterval: Polling Interval */
|
|
/******************** CDC Data Endpoint descriptor (IN) ********************/
|
|
/* 68 */
|
|
0x07, /* bLength: Endpoint Descriptor size */
|
|
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
|
CDC_DATA_EPIN_ADDR, /* bEndpointAddress: Endpoint Address (IN) */
|
|
USB_EP_TYPE_BULK, /* bmAttributes: Bulk Endpoint */
|
|
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 */
|
|
0x09, /* bLength: Interface Descriptor size */
|
|
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
|
|
0x02, /* bInterfaceNumber: Number of Interface */
|
|
0x00, /* bAlternateSetting: Alternate setting */
|
|
0x02, /* bNumEndpoints: 2 */
|
|
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 */
|
|
0x09, /* bLength: HID Descriptor size */
|
|
USB_DESC_TYPE_HID, /* bDescriptorType: HID */
|
|
0x11, /* bcdHID (low byte): HID Class Spec release number */
|
|
0x01, /* bcdHID (high byte): HID Class Spec release number */
|
|
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 */
|
|
0x07, /* bLength: Endpoint Descriptor size */
|
|
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
|
HID_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 */
|
|
0x07, /* bLength: Endpoint Descriptor size */
|
|
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
|
HID_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 */
|
|
0x09, /* bLength: Interface Descriptor size */
|
|
USB_DESC_TYPE_INTERFACE, /* bDescriptorType: Interface */
|
|
0x03, /* bInterfaceNumber: Number of Interface */
|
|
0x00, /* bAlternateSetting: Alternate setting */
|
|
0x02, /* bNumEndpoints: 2 */
|
|
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 */
|
|
0x09, /* bLength: HID Descriptor size */
|
|
USB_DESC_TYPE_HID, /* bDescriptorType: HID */
|
|
0x11, /* bcdHID (low byte): HID Class Spec release number */
|
|
0x01, /* bcdHID (high byte): HID Class Spec release number */
|
|
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 */
|
|
0x07, /* bLength: Endpoint Descriptor size */
|
|
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
|
TKEYCTRL_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 */
|
|
0x07, /* bLength: Endpoint Descriptor size */
|
|
USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: Endpoint */
|
|
TKEYCTRL_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 */
|
|
};
|
|
|
|
// HID Device Descriptor (copy from CfgDesc)
|
|
FLASH uint8_t HID_CfgDesc[] = {
|
|
0x09, /* bLength: HID Descriptor size */
|
|
USB_DESC_TYPE_HID, /* bDescriptorType: HID */
|
|
0x11, /* bcdHID (low byte): HID Class Spec release number */
|
|
0x01, /* bcdHID (high byte): HID Class Spec release number */
|
|
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 */
|
|
};
|
|
|
|
FLASH uint8_t HID_ReportDesc[] ={
|
|
0x06, 0xD0, 0xF1, /* Usage Page (FIDO Alliance Page) */
|
|
0x09, 0x01, /* Usage (U2F Authenticator Device) */
|
|
0xA1, 0x01, /* Collection (Application) */
|
|
/* 7 */
|
|
0x09, 0x20, /* Usage (Input Report Data) */
|
|
0x15, 0x00, /* Logical Minimum (0) */
|
|
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
|
|
0x75, 0x08, /* Report Size (8) */
|
|
0x95, MAX_PACKET_SIZE, /* Report Count (64) */
|
|
0x81, 0x02, /* Input (Data, Variable, Absolute); */
|
|
/* 20 */
|
|
0x09, 0x21, /* Usage (Output Report Data) */
|
|
0x15, 0x00, /* Logical Minimum (0) */
|
|
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
|
|
0x75, 0x08, /* Report Size (8) */
|
|
0x95, MAX_PACKET_SIZE, /* Report Count (64) */
|
|
0x91, 0x02, /* Output (Data, Variable, Absolute) */
|
|
/* 33 */
|
|
0x09, 0x07, /* Usage (7, Reserved) */
|
|
0x15, 0x00, /* Logical Minimum (0) */
|
|
0x26, 0xFF, 0x00, /* Logical Maximum (255) */
|
|
0x75, 0x08, /* Report Size (8) */
|
|
0x95, 0x08, /* Report Count (8) */
|
|
0xB1, 0x02, /* Feature (2) (???) */
|
|
/* 46 */
|
|
0xC0 /* End Collection */
|
|
/* 47 */
|
|
};
|
|
|
|
// TKEYCTRL Device Descriptor (copy from CfgDesc)
|
|
FLASH uint8_t TKEYCTRL_CfgDesc[] = {
|
|
0x09, /* bLength: HID Descriptor size */
|
|
USB_DESC_TYPE_HID, /* bDescriptorType: HID */
|
|
0x11, /* bcdHID (low byte): HID Class Spec release number */
|
|
0x01, /* bcdHID (high byte): HID Class Spec release number */
|
|
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 */
|
|
};
|
|
|
|
// 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) */
|
|
/* 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) */
|
|
/* 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) */
|
|
/* 33 */
|
|
0xC0 /* End Collection */
|
|
/* 34 */
|
|
};
|
|
|
|
// String Descriptor (Language descriptor )
|
|
FLASH uint8_t LangDesc[] = {
|
|
4, // Length of this descriptor (in bytes)
|
|
0x03, // Descriptor type (String)
|
|
0x09, 0x04, // Language ID (English - US)
|
|
};
|
|
|
|
// 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 */
|
|
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
|
|
|
|
/** Communication UART */
|
|
XDATA uint8_t UartTxBuf[UART_TX_BUF_SIZE] = { 0 }; // Serial transmit buffer
|
|
volatile IDATA uint8_t Ep2ByteLen;
|
|
volatile IDATA uint8_t Ep3ByteLen;
|
|
volatile IDATA uint8_t Ep4ByteLen;
|
|
|
|
XDATA uint8_t UartRxBuf[UART_RX_BUF_SIZE] = { 0 }; // Serial receive buffer
|
|
volatile IDATA uint8_t UartRxBufInputPointer = 0; // Circular buffer write pointer, bus reset needs to be initialized to 0
|
|
volatile IDATA uint8_t UartRxBufOutputPointer = 0; // Take pointer out of circular buffer, bus reset needs to be initialized to 0
|
|
volatile IDATA uint8_t UartRxBufByteCount = 0; // Number of unprocessed bytes remaining in the buffer
|
|
volatile IDATA uint8_t UartRxBufOverflow = 0;
|
|
|
|
/** Debug UART */
|
|
#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;
|
|
|
|
/** 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 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
|
|
|
|
/** TKEYCTRL variables */
|
|
XDATA uint8_t TkeyCtrlRxBuf[TKEYCTRL_FRAME_SIZE] = { 0 };
|
|
IDATA uint8_t TkeyCtrlRxBufLength = 0;
|
|
IDATA uint8_t TkeyCtrlDataAvailable = 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;
|
|
|
|
/** Frame data */
|
|
|
|
#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;
|
|
|
|
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);
|
|
void cts_start(void);
|
|
void cts_stop(void);
|
|
void check_cts_stop(void);
|
|
|
|
/*******************************************************************************
|
|
* Function Name : USBDeviceCfg()
|
|
* Description : USB device mode configuration
|
|
* Input : None
|
|
* Output : None
|
|
* Return : None
|
|
*******************************************************************************/
|
|
void USBDeviceCfg()
|
|
{
|
|
USB_CTRL = 0x00; // Clear USB control register
|
|
USB_CTRL &= ~bUC_HOST_MODE; // This bit selects the device mode
|
|
USB_CTRL |= bUC_DEV_PU_EN | bUC_INT_BUSY | bUC_DMA_EN; // USB device and internal pull-up enable, automatically return to NAK before interrupt flag is cleared
|
|
USB_DEV_AD = 0x00; // Device address initialization
|
|
#if 0
|
|
// USB_CTRL |= bUC_LOW_SPEED;
|
|
// UDEV_CTRL |= bUD_LOW_SPEED; // Select low speed 1.5M mode
|
|
#else
|
|
USB_CTRL &= ~bUC_LOW_SPEED;
|
|
UDEV_CTRL &= ~bUD_LOW_SPEED; // Select full speed 12M mode, the default mode
|
|
#endif
|
|
UDEV_CTRL = bUD_PD_DIS; // Disable DP / DM pull-down resistor
|
|
UDEV_CTRL |= bUD_PORT_EN; // Enable physical port
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Function Name : USBDeviceIntCfg()
|
|
* Description : USB device mode interrupt initialization
|
|
* Input : None
|
|
* Output : None
|
|
* Return : None
|
|
*******************************************************************************/
|
|
void USBDeviceIntCfg()
|
|
{
|
|
USB_INT_EN |= bUIE_SUSPEND; // Enable device suspend interrupt
|
|
USB_INT_EN |= bUIE_TRANSFER; // Enable USB transfer completion interrupt
|
|
USB_INT_EN |= bUIE_BUS_RST; // Enable device mode USB bus reset interrupt
|
|
USB_INT_FG |= (UIF_FIFO_OV | UIF_HST_SOF | UIF_SUSPEND | UIF_TRANSFER | UIF_BUS_RST ); // Clear interrupt flag
|
|
IE_USB = 1; // Enable USB interrupt
|
|
EA = 1; // Allow microcontroller interrupt
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Function Name : USBDeviceEndPointCfg()
|
|
* Description : USB device mode endpoint configuration, simulation compatible
|
|
* HID device, in addition to endpoint 0 control transmission,
|
|
* also includes endpoint 2 batch upload
|
|
* Input : None
|
|
* Output : None
|
|
* Return : None
|
|
*******************************************************************************/
|
|
void USBDeviceEndPointCfg()
|
|
{
|
|
// TODO: Is casting the right thing here? What about endianness?
|
|
UEP0_DMA = (uint16_t) Ep0Buffer; // Endpoint 0 data transfer address, Endpoint 4
|
|
UEP1_DMA = (uint16_t) Ep1Buffer; // Endpoint 1 sends data transfer address
|
|
UEP2_DMA = (uint16_t) Ep2Buffer; // Endpoint 2 IN data transfer address
|
|
UEP3_DMA = (uint16_t) Ep3Buffer; // Endpoint 3 IN data transfer address
|
|
|
|
UEP4_1_MOD = bUEP4_TX_EN | bUEP4_RX_EN | bUEP1_TX_EN; // Endpoint 0 single 8-byte send and receive buffer
|
|
// Endpoint 1, transmit enable
|
|
// Endpoint 4, single buffer, transmit+receive enable
|
|
UEP2_3_MOD = bUEP2_TX_EN | bUEP2_RX_EN | bUEP3_TX_EN | bUEP3_RX_EN; // Endpoint 2, single buffer, transmit+receive enable
|
|
// Endpoint 3, single buffer, transmit+receive enable
|
|
|
|
UEP0_CTRL = UEP_T_RES_NAK | UEP_R_RES_ACK; // Endpoint 0, manual flip, OUT transaction returns ACK, IN transaction returns NAK
|
|
UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK; // Endpoint 1, automatically flips the synchronization flag, IN transaction returns NAK
|
|
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
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Function Name : Config_Uart1(uint8_t *cfg_uart)
|
|
* Description : Configure serial port 1 parameters
|
|
* Input : Serial port configuration parameters Four bit baud rate, stop bit, parity, data bit
|
|
* Output : None
|
|
* Return : None
|
|
*******************************************************************************/
|
|
void Config_Uart1(uint8_t *cfg_uart)
|
|
{
|
|
uint32_t uart1_baud = 0;
|
|
*((uint8_t*) &uart1_baud) = cfg_uart[0];
|
|
*((uint8_t*) &uart1_baud + 1) = cfg_uart[1];
|
|
*((uint8_t*) &uart1_baud + 2) = cfg_uart[2];
|
|
*((uint8_t*) &uart1_baud + 3) = cfg_uart[3];
|
|
SBAUD1 = 256 - FREQ_SYS / 16 / uart1_baud; // SBAUD1 = 256 - Fsys / 16 / baud rate
|
|
IE_UART1 = 1; // Enable UART1 interrupt
|
|
}
|
|
|
|
void usb_irq_setup_handler(void)
|
|
{
|
|
uint16_t len = USB_RX_LEN;
|
|
printStrSetup("Setup ");
|
|
|
|
if (len == (sizeof(USB_SETUP_REQ))) {
|
|
SetupLen = ((uint16_t) UsbSetupBuf->wLengthH << 8) | (UsbSetupBuf->wLengthL);
|
|
len = 0; // Defaults to success and uploading 0 length
|
|
SetupReq = UsbSetupBuf->bRequest;
|
|
|
|
// Class-Specific Requests, i.e. HID request, CDC request etc.
|
|
if ((UsbSetupBuf->bmRequestType & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) {
|
|
printStrSetup("Class-Specific ");
|
|
printStrSetup("SetupReq=");
|
|
printStrSetup("0x");
|
|
printNumHexSetup(SetupReq);
|
|
printStrSetup(" ");
|
|
switch(SetupReq) {
|
|
case USB_HID_REQ_TYPE_GET_REPORT:
|
|
printStrSetup("HID Get Report\n");
|
|
break;
|
|
case USB_HID_REQ_TYPE_GET_IDLE:
|
|
printStrSetup("HID Get Idle\n");
|
|
break;
|
|
case USB_HID_REQ_TYPE_GET_PROTOCOL:
|
|
printStrSetup("HID Get Protocol\n");
|
|
break;
|
|
case USB_HID_REQ_TYPE_SET_REPORT:
|
|
printStrSetup("HID Set Report\n");
|
|
break;
|
|
case USB_HID_REQ_TYPE_SET_IDLE:
|
|
printStrSetup("HID Set Idle\n");
|
|
break;
|
|
case USB_HID_REQ_TYPE_SET_PROTOCOL:
|
|
printStrSetup("HID Set Protocol\n");
|
|
break;
|
|
case USB_CDC_REQ_TYPE_SET_LINE_CODING:
|
|
printStrSetup("CDC Set Line Coding\n");
|
|
break;
|
|
case USB_CDC_REQ_TYPE_GET_LINE_CODING:
|
|
printStrSetup("CDC Get Line Coding\n");
|
|
pDescr = LineCoding;
|
|
len = sizeof(LineCoding);
|
|
len = SetupLen >= DEFAULT_EP0_SIZE ? DEFAULT_EP0_SIZE : SetupLen; // The length of this transmission
|
|
memcpy(Ep0Buffer, pDescr, len);
|
|
SetupLen -= len;
|
|
pDescr += len;
|
|
break;
|
|
case USB_CDC_REQ_TYPE_SET_CONTROL_LINE_STATE: // Generates RS-232/V.24 style control signals
|
|
printStrSetup("CDC Set Control Line State\n");
|
|
break;
|
|
default:
|
|
len = 0xFF; // Command not supported
|
|
printStrSetup("Unsupported\n");
|
|
break;
|
|
}
|
|
} // END Non-standard request
|
|
|
|
else { // Standard Requests
|
|
// Request code
|
|
switch (SetupReq) {
|
|
case USB_GET_DESCRIPTOR: {
|
|
switch (UsbSetupBuf->wValueH) {
|
|
case USB_DESC_TYPE_DEVICE: // Device descriptor
|
|
pDescr = DevDesc; // Send the device descriptor to the buffer to be sent
|
|
len = sizeof(DevDesc);
|
|
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);
|
|
printStrSetup("CfgDesc\n");
|
|
break;
|
|
case USB_DESC_TYPE_STRING: // String descriptors
|
|
if (UsbSetupBuf->wValueL == USB_IDX_LANGID_STR) {
|
|
pDescr = LangDesc;
|
|
len = sizeof(LangDesc);
|
|
printStrSetup("LangDesc\n");
|
|
} else if (UsbSetupBuf->wValueL == USB_IDX_MFC_STR) {
|
|
pDescr = ManufDesc;
|
|
len = sizeof(ManufDesc);
|
|
printStrSetup("ManufDesc\n");
|
|
} else if (UsbSetupBuf->wValueL == USB_IDX_PRODUCT_STR) {
|
|
pDescr = ProdDesc;
|
|
len = sizeof(ProdDesc);
|
|
printStrSetup("ProdDesc\n");
|
|
} else if (UsbSetupBuf->wValueL == USB_IDX_SERIAL_STR) {
|
|
pDescr = SerialDesc;
|
|
len = sizeof(SerialDesc);
|
|
printStrSetup("SerialDesc\n");
|
|
} else if (UsbSetupBuf->wValueL == USB_IDX_INTERFACE_CDC_CTRL_STR) {
|
|
pDescr = CdcCtrlInterfaceDesc;
|
|
len = sizeof(CdcCtrlInterfaceDesc);
|
|
printStrSetup("CdcCtrlInterfaceDesc\n");
|
|
} else if (UsbSetupBuf->wValueL == USB_IDX_INTERFACE_CDC_DATA_STR) {
|
|
pDescr = CdcDataInterfaceDesc;
|
|
len = sizeof(CdcDataInterfaceDesc);
|
|
printStrSetup("CdcDataInterfaceDesc\n");
|
|
} else if (UsbSetupBuf->wValueL == USB_IDX_INTERFACE_FIDO_HID_STR) {
|
|
pDescr = FidoHidInterfaceDesc;
|
|
len = sizeof(FidoHidInterfaceDesc);
|
|
printStrSetup("FidoHidInterfaceDesc\n");
|
|
} else if (UsbSetupBuf->wValueL == USB_IDX_INTERFACE_TKEY_CTRL_STR) {
|
|
pDescr = TkeyCtrlInterfaceDesc;
|
|
len = sizeof(TkeyCtrlInterfaceDesc);
|
|
printStrSetup("TkeyCtrlInterfaceDesc\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;
|
|
}
|
|
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;
|
|
}
|
|
break;
|
|
default:
|
|
len = 0xFF; // Unsupported command or error
|
|
printStrSetup("Unsupported\n");
|
|
break;
|
|
}
|
|
|
|
if (SetupLen > len) {
|
|
SetupLen = len; // Limit total length
|
|
}
|
|
|
|
len = SetupLen >= DEFAULT_EP0_SIZE ? DEFAULT_EP0_SIZE : SetupLen; // This transmission length
|
|
memcpy(Ep0Buffer, pDescr, len); // Copy upload data
|
|
SetupLen -= len;
|
|
pDescr += len;
|
|
}
|
|
break;
|
|
|
|
case USB_SET_ADDRESS:
|
|
SetupLen = UsbSetupBuf->wValueL; // Temporary storage of USB device address
|
|
printStrSetup("SetAddress\n");
|
|
break;
|
|
|
|
case USB_GET_CONFIGURATION:
|
|
Ep0Buffer[0] = UsbConfig;
|
|
if (SetupLen >= 1) {
|
|
len = 1;
|
|
}
|
|
printStrSetup("GetConfig\n");
|
|
break;
|
|
|
|
case USB_SET_CONFIGURATION:
|
|
UsbConfig = UsbSetupBuf->wValueL;
|
|
printStrSetup("SetConfig\n");
|
|
break;
|
|
|
|
case USB_GET_INTERFACE:
|
|
printStrSetup("GetInterface\n");
|
|
break;
|
|
|
|
case USB_CLEAR_FEATURE: // Clear Feature
|
|
printStrSetup("ClearFeature\n");
|
|
if ((UsbSetupBuf->bmRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE) { // Remove device
|
|
if ((((uint16_t) UsbSetupBuf->wValueH << 8) | UsbSetupBuf->wValueL) == 0x01) {
|
|
if (CfgDesc[7] & 0x20) {
|
|
// Wake
|
|
} else {
|
|
len = 0xFF; // Operation failed
|
|
printStrSetup("Unsupported\n");
|
|
}
|
|
} else {
|
|
len = 0xFF; // Operation failed
|
|
printStrSetup("Unsupported\n");
|
|
}
|
|
} else if ((UsbSetupBuf->bmRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP) { // Endpoint
|
|
switch (UsbSetupBuf->wIndexL) {
|
|
case 0x84:
|
|
UEP4_CTRL = (UEP4_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK; // Set endpoint 4 IN (TX) NAK
|
|
break;
|
|
case 0x04:
|
|
UEP4_CTRL = (UEP4_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK; // Set endpoint 4 OUT (RX) ACK
|
|
break;
|
|
case 0x83:
|
|
UEP3_CTRL = (UEP3_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK; // Set endpoint 3 IN (TX) NAK
|
|
break;
|
|
case 0x03:
|
|
UEP3_CTRL = (UEP3_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK; // Set endpoint 3 OUT (RX) ACK
|
|
break;
|
|
case 0x82:
|
|
UEP2_CTRL = (UEP2_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK; // Set endpoint 2 IN (TX) NACK
|
|
break;
|
|
case 0x02:
|
|
UEP2_CTRL = (UEP2_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK; // Set endpoint 2 OUT (RX) ACK
|
|
break;
|
|
case 0x81:
|
|
UEP1_CTRL = (UEP1_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK; // Set endpoint 1 IN (TX) NACK
|
|
break;
|
|
case 0x01:
|
|
UEP1_CTRL = (UEP1_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK; // Set endpoint 1 OUT (RX) ACK
|
|
break;
|
|
default:
|
|
len = 0xFF; // Unsupported endpoint
|
|
printStrSetup("Unsupported\n");
|
|
break;
|
|
}
|
|
} else {
|
|
len = 0xFF; // It's not that the endpoint doesn't support it
|
|
printStrSetup("Unsupported\n");
|
|
}
|
|
break;
|
|
|
|
case USB_SET_FEATURE: // Set Feature
|
|
printStrSetup("SetFeature\n");
|
|
if (( UsbSetupBuf->bmRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE) { // Set up the device
|
|
if ((((uint16_t) UsbSetupBuf->wValueH << 8) | UsbSetupBuf->wValueL) == 0x01) {
|
|
if (CfgDesc[7] & 0x20) {
|
|
printStrSetup("Suspend\n");
|
|
while (XBUS_AUX & bUART0_TX) {
|
|
; // Wait for sending to complete
|
|
}
|
|
SAFE_MOD = 0x55;
|
|
SAFE_MOD = 0xAA;
|
|
WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO | bWAK_RXD1_LO; // USB or RXD0/1 can be woken up when there is a signal
|
|
PCON |= PD; // Sleep
|
|
SAFE_MOD = 0x55;
|
|
SAFE_MOD = 0xAA;
|
|
WAKE_CTRL = 0x00;
|
|
} else {
|
|
len = 0xFF; // Operation failed
|
|
}
|
|
} else {
|
|
len = 0xFF; // Operation failed
|
|
}
|
|
} else if (( UsbSetupBuf->bmRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP) { // Set endpoint
|
|
if ((((uint16_t) UsbSetupBuf->wValueH << 8) | UsbSetupBuf->wValueL) == 0x00) {
|
|
switch (((uint16_t) UsbSetupBuf->wIndexH << 8) | UsbSetupBuf->wIndexL) {
|
|
case 0x84:
|
|
UEP4_CTRL = (UEP4_CTRL & ~bUEP_T_TOG) | UEP_T_RES_STALL; // Set endpoint 4 IN (TX) Stall (error)
|
|
break;
|
|
case 0x04:
|
|
UEP4_CTRL = (UEP4_CTRL & ~bUEP_R_TOG) | UEP_R_RES_STALL; // Set endpoint 4 OUT (RX) Stall (error)
|
|
break;
|
|
case 0x83:
|
|
UEP3_CTRL = (UEP3_CTRL & ~bUEP_T_TOG) | UEP_T_RES_STALL; // Set endpoint 3 IN (TX) Stall (error)
|
|
break;
|
|
case 0x03:
|
|
UEP3_CTRL = (UEP3_CTRL & ~bUEP_R_TOG) | UEP_R_RES_STALL; // Set endpoint 3 OUT (RX) Stall (error)
|
|
break;
|
|
case 0x82:
|
|
UEP2_CTRL = (UEP2_CTRL & ~bUEP_T_TOG) | UEP_T_RES_STALL; // Set endpoint 2 IN (TX) Stall (error)
|
|
break;
|
|
case 0x02:
|
|
UEP2_CTRL = (UEP2_CTRL & ~bUEP_R_TOG) | UEP_R_RES_STALL; // Set endpoint 2 OUT (RX) Stall (error)
|
|
break;
|
|
case 0x81:
|
|
UEP1_CTRL = (UEP1_CTRL & ~bUEP_T_TOG) | UEP_T_RES_STALL; // Set endpoint 1 IN (TX) Stall (error)
|
|
break;
|
|
case 0x01:
|
|
UEP1_CTRL = (UEP1_CTRL & ~bUEP_R_TOG) | UEP_R_RES_STALL; // Set endpoint 1 OUT (RX) Stall (error)
|
|
default:
|
|
len = 0xFF; // Operation failed
|
|
break;
|
|
}
|
|
} else {
|
|
len = 0xFF; // Operation failed
|
|
printStrSetup("Unsupported\n");
|
|
}
|
|
} else {
|
|
len = 0xFF; // Operation failed
|
|
printStrSetup("Unsupported\n");
|
|
}
|
|
break;
|
|
|
|
case USB_GET_STATUS:
|
|
printStrSetup("GetStatus\n");
|
|
Ep0Buffer[0] = 0x00;
|
|
Ep0Buffer[1] = 0x00;
|
|
if (SetupLen >= 2) {
|
|
len = 2;
|
|
} else {
|
|
len = SetupLen;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
len = 0xFF; // Operation failed
|
|
printStrSetup("Unsupported\n");
|
|
break;
|
|
|
|
} // END switch (SetupReq)
|
|
} // END Standard request
|
|
} else {
|
|
len = 0xFF; // Packet length error
|
|
}
|
|
|
|
if (len == 0xFF) {
|
|
SetupReq = 0xFF;
|
|
UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL; // STALL
|
|
} else if (len <= DEFAULT_EP0_SIZE) { // Upload data or status phase returns 0 length packet
|
|
UEP0_T_LEN = len;
|
|
UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK; // The default packet is DATA1, return response ACK
|
|
} else {
|
|
UEP0_T_LEN = 0; // Although it has not yet reached the status stage, it is preset to upload 0-length data packets in advance to prevent the host from entering the status stage early.
|
|
UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK; // The default data packet is DATA1, and the response ACK is returned
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Function Name : DeviceInterrupt()
|
|
* Description : CH559USB interrupt processing function
|
|
*******************************************************************************/
|
|
#ifdef BUILD_CODE
|
|
#define IRQ_USB __interrupt(INT_NO_USB)
|
|
#else
|
|
#define IRQ_USB
|
|
#endif
|
|
|
|
void DeviceInterrupt(void)IRQ_USB // USB interrupt service routine, using register set 1
|
|
{
|
|
uint16_t len;
|
|
|
|
if (UIF_TRANSFER) { // Check USB transfer complete flag
|
|
switch (USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) {
|
|
|
|
case UIS_TOKEN_SETUP | 0: // SETUP routine
|
|
usb_irq_setup_handler();
|
|
break;
|
|
|
|
case UIS_TOKEN_IN | 0: // Endpoint 0 IN (TX)
|
|
switch (SetupReq) {
|
|
case USB_GET_DESCRIPTOR:
|
|
len = SetupLen >= DEFAULT_EP0_SIZE ? DEFAULT_EP0_SIZE : SetupLen; // The length of this transmission
|
|
memcpy(Ep0Buffer, pDescr, len); // Load upload data
|
|
SetupLen -= len;
|
|
pDescr += len;
|
|
UEP0_T_LEN = len;
|
|
UEP0_CTRL ^= bUEP_T_TOG; // Sync flag flip
|
|
break;
|
|
case USB_SET_ADDRESS:
|
|
USB_DEV_AD = (USB_DEV_AD & bUDA_GP_BIT) | SetupLen;
|
|
UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
|
|
break;
|
|
default:
|
|
UEP0_T_LEN = 0; // The status phase is completed and interrupted or the 0-length data packet is forced to be uploaded to end the control transmission.
|
|
UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case UIS_TOKEN_IN | 1: // Endpoint 1 IN (TX), Endpoint interrupts upload
|
|
UEP1_T_LEN = 0; // Transmit length must be cleared (Endpoint 1)
|
|
UEP1_CTRL = (UEP1_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK; // Default answer NAK
|
|
break;
|
|
|
|
case UIS_TOKEN_IN | 2: // Endpoint 2 IN (TX), Endpoint bulk upload
|
|
UEP2_T_LEN = 0; // Transmit length must be cleared (Endpoint 2)
|
|
UEP2_CTRL = (UEP2_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK; // Default answer NAK
|
|
Endpoint2UploadBusy = 0; // Clear busy flag
|
|
break;
|
|
|
|
case UIS_TOKEN_IN | 3: // Endpoint 3 IN (TX), Endpoint bulk upload
|
|
UEP3_T_LEN = 0; // Transmit length must be cleared (Endpoint 3)
|
|
UEP3_CTRL = (UEP3_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK; // Default answer NAK
|
|
Endpoint3UploadBusy = 0; // Clear busy flag
|
|
break;
|
|
|
|
case UIS_TOKEN_IN | 4: // Endpoint 4 IN (TX), Endpoint bulk upload
|
|
UEP4_T_LEN = 0; // Transmit length must be cleared (Endpoint 4)
|
|
UEP4_CTRL = (UEP4_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK; // Default answer NAK
|
|
UEP4_CTRL ^= bUEP_T_TOG; // Sync flag flip
|
|
Endpoint4UploadBusy = 0; // Clear busy flag
|
|
break;
|
|
|
|
case UIS_TOKEN_OUT | 0: // Endpoint 0 OUT (RX)
|
|
switch (SetupReq) {
|
|
case USB_CDC_REQ_TYPE_SET_LINE_CODING: // We ignore line coding here because baudrate to the FPGA should not change
|
|
if (U_TOG_OK) {
|
|
UEP0_T_LEN = 0;
|
|
UEP0_CTRL |= UEP_R_RES_ACK | UEP_T_RES_ACK; // Prepare to upload 0 packages
|
|
}
|
|
break;
|
|
default:
|
|
UEP0_T_LEN = 0;
|
|
UEP0_CTRL |= UEP_R_RES_ACK | UEP_T_RES_NAK; // Status phase, responds to IN with NAK
|
|
}
|
|
break;
|
|
|
|
case UIS_TOKEN_OUT | 1: // Endpoint 1 OUT (RX), Disabled for now.
|
|
// Out-of-sync packets will be dropped
|
|
if (U_TOG_OK) {
|
|
//UsbEpXByteCount = USB_RX_LEN; // Length of received data
|
|
//UEP1_CTRL = (UEP1_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_NAK; // NAK after receiving a packet of data, the main function finishes processing, and the main function modifies the response mode
|
|
}
|
|
break;
|
|
|
|
case UIS_TOKEN_OUT | 2: // Endpoint 2 OUT (RX), Endpoint batch download
|
|
// Out-of-sync packets will be dropped
|
|
if (U_TOG_OK) {
|
|
UsbEp2ByteCount = USB_RX_LEN; // Length of received data
|
|
UEP2_CTRL = (UEP2_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_NAK; // NAK after receiving a packet of data, the main function finishes processing, and the main function modifies the response mode
|
|
}
|
|
break;
|
|
|
|
case UIS_TOKEN_OUT | 3: // Endpoint 3 OUT (RX), Endpoint batch download
|
|
// Out-of-sync packets will be dropped
|
|
if (U_TOG_OK) {
|
|
UsbEp3ByteCount = USB_RX_LEN; // Length of received data
|
|
UEP3_CTRL = (UEP3_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_NAK; // NAK after receiving a packet of data, the main function finishes processing, and the main function modifies the response mode
|
|
}
|
|
break;
|
|
|
|
case UIS_TOKEN_OUT | 4: // Endpoint 4 OUT (RX), Endpoint batch download
|
|
// Out-of-sync packets will be dropped
|
|
if (U_TOG_OK) {
|
|
UsbEp4ByteCount = USB_RX_LEN; // Length of received data
|
|
UEP4_CTRL = (UEP4_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_NAK; // NAK after receiving a packet of data, the main function finishes processing, and the main function modifies the response mode
|
|
UEP4_CTRL ^= bUEP_R_TOG; // Sync flag flip
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
UIF_TRANSFER = 0; // Writing 0 clears the interrupt
|
|
|
|
} else if (UIF_BUS_RST) { // Check device mode USB bus reset interrupt
|
|
|
|
printStr("Reset\n");
|
|
|
|
UEP0_CTRL = UEP_T_RES_NAK | UEP_R_RES_ACK;
|
|
UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK;
|
|
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;
|
|
USB_DEV_AD = 0x00;
|
|
UIF_SUSPEND = 0;
|
|
UIF_TRANSFER = 0; // Writing 0 clears the interrupt
|
|
UIF_BUS_RST = 0; // Clear interrupt flag
|
|
|
|
UartRxBufInputPointer = 0; // Circular buffer input pointer
|
|
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
|
|
Endpoint2UploadBusy = 0; // Clear busy flag
|
|
Endpoint3UploadBusy = 0; // Clear busy flag
|
|
|
|
FrameMode = 0;
|
|
|
|
UsbConfig = 0; // Clear configuration values
|
|
|
|
} else if (UIF_SUSPEND) { // Check USB bus suspend/wake completed
|
|
|
|
UIF_SUSPEND = 0;
|
|
|
|
if (USB_MIS_ST & bUMS_SUSPEND) { // Hang
|
|
|
|
printStr("Suspend\n");
|
|
|
|
while (XBUS_AUX & bUART0_TX) {
|
|
; // Wait for sending to complete
|
|
}
|
|
|
|
SAFE_MOD = 0x55;
|
|
SAFE_MOD = 0xAA;
|
|
WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO | bWAK_RXD1_LO; // Can be woken up when there is a signal from USB or RXD0/1
|
|
PCON |= PD; // Sleep
|
|
SAFE_MOD = 0x55;
|
|
SAFE_MOD = 0xAA;
|
|
WAKE_CTRL = 0x00;
|
|
|
|
}
|
|
} else { // Unexpected IRQ, should not happen
|
|
printStr("Unexpected IRQ\n");
|
|
USB_INT_FG = 0xFF; // Clear interrupt flag
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Function Name : Uart0_ISR()
|
|
* Description : Serial debug port receiving interrupt function to realize circular buffer receiving
|
|
*******************************************************************************/
|
|
#if 1
|
|
#ifdef BUILD_CODE
|
|
#define IRQ_UART0 __interrupt(INT_NO_UART0)
|
|
#else
|
|
#define IRQ_UART0
|
|
#endif
|
|
|
|
void Uart0_ISR(void)IRQ_UART0
|
|
{
|
|
// Check if data has been received
|
|
if (RI) {
|
|
DebugUartRxBuf[DebugUartRxBufInputPointer++] = SBUF;
|
|
if (DebugUartRxBufInputPointer >= DEBUG_UART_RX_BUF_SIZE) {
|
|
DebugUartRxBufInputPointer = 0; // Reset write pointer
|
|
}
|
|
RI = 0;
|
|
}
|
|
}
|
|
|
|
uint8_t debug_uart_byte_count()
|
|
{
|
|
uint8_t in = DebugUartRxBufInputPointer;
|
|
uint8_t out = DebugUartRxBufOutputPointer;
|
|
|
|
if (in < out) {
|
|
in = in + DEBUG_UART_RX_BUF_SIZE;
|
|
}
|
|
return in - out;
|
|
}
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* Function Name : Uart1_ISR()
|
|
* Description : Serial port receiving interrupt function to realize circular buffer receiving
|
|
*******************************************************************************/
|
|
#ifdef BUILD_CODE
|
|
#define IRQ_UART1 __interrupt(INT_NO_UART1)
|
|
#else
|
|
#define IRQ_UART1
|
|
#endif
|
|
|
|
void Uart1_ISR(void)IRQ_UART1
|
|
{
|
|
// Check if data has been received
|
|
if (U1RI) {
|
|
UartRxBuf[UartRxBufInputPointer++] = SBUF1;
|
|
if (UartRxBufInputPointer == UartRxBufOutputPointer) {
|
|
UartRxBufOverflow = 1;
|
|
}
|
|
if (UartRxBufInputPointer >= UART_RX_BUF_SIZE) {
|
|
UartRxBufInputPointer = 0; // Reset write pointer
|
|
}
|
|
|
|
check_cts_stop();
|
|
|
|
U1RI = 0;
|
|
}
|
|
}
|
|
|
|
uint8_t uart_byte_count()
|
|
{
|
|
uint8_t in = UartRxBufInputPointer;
|
|
uint8_t out = UartRxBufOutputPointer;
|
|
|
|
if (in < out) {
|
|
in = in + UART_RX_BUF_SIZE;
|
|
}
|
|
return in - out;
|
|
}
|
|
|
|
// Copy data from a circular buffer
|
|
void circular_copy(uint8_t *dest, uint8_t *src, uint32_t src_size, uint32_t start_pos, uint32_t length) {
|
|
|
|
// Calculate the remaining space from start_pos to end of buffer
|
|
uint32_t remaining_space = src_size - start_pos;
|
|
|
|
if (length <= remaining_space) {
|
|
// If the length to copy doesn't exceed the remaining space, do a single memcpy
|
|
memcpy(dest, src + start_pos, length);
|
|
} else {
|
|
// If the length to copy exceeds the remaining space, split the copy
|
|
memcpy(dest, src + start_pos, remaining_space); // Copy from start_pos to end of buffer
|
|
memcpy(dest + remaining_space, src, length - remaining_space); // Copy the rest from the beginning of buffer
|
|
}
|
|
}
|
|
|
|
|
|
// Function to increment a pointer and wrap around the buffer
|
|
uint32_t increment_pointer(uint32_t pointer, uint32_t increment, uint32_t buffer_size)
|
|
{
|
|
return (pointer + increment) % buffer_size;
|
|
}
|
|
|
|
// Function to decrement a pointer and wrap around the buffer
|
|
uint32_t decrement_pointer(uint32_t pointer, uint32_t decrement, uint32_t buffer_size)
|
|
{
|
|
return (pointer + buffer_size - (decrement % buffer_size)) % buffer_size;
|
|
}
|
|
|
|
void cts_start(void)
|
|
{
|
|
gpio_p1_5_set(); // Signal to FPGA to send more data
|
|
}
|
|
|
|
void cts_stop(void)
|
|
{
|
|
gpio_p1_5_unset(); // Signal to FPGA to not send more data
|
|
}
|
|
|
|
void check_cts_stop(void)
|
|
{
|
|
if (uart_byte_count() >= 133) // UartRxBuf is filled to 95% or more
|
|
{
|
|
cts_stop();
|
|
}
|
|
}
|
|
|
|
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
|
|
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");
|
|
|
|
USBDeviceCfg();
|
|
USBDeviceEndPointCfg(); // Endpoint configuration
|
|
USBDeviceIntCfg(); // Interrupt initialization
|
|
|
|
UEP0_T_LEN = 0; // Transmit length must be cleared (Endpoint 0)
|
|
UEP1_T_LEN = 0; // Transmit length must be cleared (Endpoint 1)
|
|
UEP2_T_LEN = 0; // Transmit length must be cleared (Endpoint 2)
|
|
UEP3_T_LEN = 0; // Transmit length must be cleared (Endpoint 3)
|
|
UEP4_T_LEN = 0; // Transmit length must be cleared (Endpoint 4)
|
|
|
|
while (1) {
|
|
if (UsbConfig) {
|
|
|
|
// Check if Endpoint 2 (CDC) has received data
|
|
if (UsbEp2ByteCount) {
|
|
Ep2ByteLen = UsbEp2ByteCount; // UsbEp2ByteCount can be maximum 64 bytes
|
|
memcpy(UartTxBuf, Ep2Buffer, Ep2ByteLen);
|
|
|
|
UsbEp2ByteCount = 0;
|
|
CH554UART1SendByte(MODE_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
|
|
if (UsbEp3ByteCount) {
|
|
Ep3ByteLen = UsbEp3ByteCount; // UsbEp3ByteCount can be maximum 64 bytes
|
|
memcpy(UartTxBuf, Ep3Buffer, Ep3ByteLen);
|
|
|
|
UsbEp3ByteCount = 0;
|
|
CH554UART1SendByte(MODE_HID); // Send HID 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
|
|
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(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
|
|
}
|
|
|
|
UartRxBufByteCount = uart_byte_count(); // Check amount of data in buffer
|
|
|
|
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)) {
|
|
FrameLength = UartRxBuf[increment_pointer(UartRxBufOutputPointer,
|
|
1,
|
|
UART_RX_BUF_SIZE)]; // Extract frame length
|
|
FrameRemainingBytes = FrameLength;
|
|
UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer,
|
|
2,
|
|
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");
|
|
printNumHex(FrameMode);
|
|
printStr(", len = ");
|
|
printNumU32(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<UART_RX_BUF_SIZE; i++) {
|
|
printNumHex(UartRxBuf[increment_pointer(UartRxBufOutputPointer,
|
|
i,
|
|
UART_RX_BUF_SIZE)]);
|
|
print_char_count_out++;
|
|
if (print_char_count_out >= 16) {
|
|
printStr("\n");
|
|
print_char_count_out = 0;
|
|
}
|
|
}
|
|
if (print_char_count_out != 0) {
|
|
printStr("\n");
|
|
}
|
|
printStr("Halting!\n");
|
|
Halted = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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,
|
|
UartRxBuf,
|
|
UART_RX_BUF_SIZE,
|
|
UartRxBufOutputPointer,
|
|
MAX_PACKET_SIZE);
|
|
TkeyCtrlRxBufLength = MAX_PACKET_SIZE;
|
|
// Update output pointer
|
|
UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer,
|
|
MAX_PACKET_SIZE,
|
|
UART_RX_BUF_SIZE);
|
|
FrameRemainingBytes -= MAX_PACKET_SIZE;
|
|
TkeyCtrlDataAvailable = 1;
|
|
cts_start();
|
|
}
|
|
else if ((FrameRemainingBytes < MAX_PACKET_SIZE) &&
|
|
(UartRxBufByteCount >= FrameRemainingBytes)) {
|
|
circular_copy(TkeyCtrlRxBuf,
|
|
UartRxBuf,
|
|
UART_RX_BUF_SIZE,
|
|
UartRxBufOutputPointer,
|
|
FrameRemainingBytes);
|
|
TkeyCtrlRxBufLength = FrameRemainingBytes;
|
|
// Update output pointer
|
|
UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer,
|
|
FrameRemainingBytes,
|
|
UART_RX_BUF_SIZE);
|
|
FrameRemainingBytes -= FrameRemainingBytes;
|
|
TkeyCtrlDataAvailable = 1;
|
|
cts_start();
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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,
|
|
UartRxBuf,
|
|
UART_RX_BUF_SIZE,
|
|
UartRxBufOutputPointer,
|
|
MAX_PACKET_SIZE);
|
|
CdcRxBufLength = MAX_PACKET_SIZE;
|
|
// Update output pointer
|
|
UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer,
|
|
MAX_PACKET_SIZE,
|
|
UART_RX_BUF_SIZE);
|
|
FrameRemainingBytes -= MAX_PACKET_SIZE;
|
|
CdcDataAvailable = 1;
|
|
cts_start();
|
|
}
|
|
else if ((FrameRemainingBytes < MAX_PACKET_SIZE) &&
|
|
(UartRxBufByteCount >= FrameRemainingBytes)) {
|
|
circular_copy(CdcRxBuf,
|
|
UartRxBuf,
|
|
UART_RX_BUF_SIZE,
|
|
UartRxBufOutputPointer,
|
|
FrameRemainingBytes);
|
|
CdcRxBufLength = FrameRemainingBytes;
|
|
// Update output pointer
|
|
UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer,
|
|
FrameRemainingBytes,
|
|
UART_RX_BUF_SIZE);
|
|
FrameRemainingBytes -= FrameRemainingBytes;
|
|
CdcDataAvailable = 1;
|
|
cts_start();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Copy HID data from UartRxBuf to HidRxBuf
|
|
if (FrameStarted && !HidDataAvailable) {
|
|
if (FrameMode == MODE_HID) {
|
|
// Check if a complete frame has been received
|
|
if (UartRxBufByteCount >= FrameRemainingBytes) {
|
|
circular_copy(HidRxBuf,
|
|
UartRxBuf,
|
|
UART_RX_BUF_SIZE,
|
|
UartRxBufOutputPointer,
|
|
FrameRemainingBytes);
|
|
HidRxBufLength = MAX_PACKET_SIZE;
|
|
// Update output pointer
|
|
UartRxBufOutputPointer = increment_pointer(UartRxBufOutputPointer,
|
|
FrameRemainingBytes,
|
|
UART_RX_BUF_SIZE);
|
|
HidDataAvailable = 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);
|
|
|
|
UEP2_T_LEN = CdcRxBufLength; // 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
|
|
Endpoint2UploadBusy = 1; // Set busy flag
|
|
|
|
CdcDataAvailable = 0;
|
|
CdcRxBufLength = 0;
|
|
|
|
if (FrameRemainingBytes == 0) {
|
|
// Complete frame sent, get next header and data
|
|
FrameStarted = 0;
|
|
}
|
|
}
|
|
|
|
// Check if we should upload data to Endpoint 3 (HID)
|
|
if (HidDataAvailable && !Endpoint3UploadBusy) {
|
|
|
|
// Write upload endpoint
|
|
memcpy(Ep3Buffer + MAX_PACKET_SIZE, /* Copy to IN buffer of Endpoint 3 */
|
|
HidRxBuf,
|
|
HidRxBufLength);
|
|
|
|
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
|
|
Endpoint3UploadBusy = 1; // Set busy flag
|
|
|
|
HidDataAvailable = 0;
|
|
|
|
// Get next header and data
|
|
FrameStarted = 0;
|
|
}
|
|
|
|
// Check if we should upload data to Endpoint 4 (TKEYCTRL)
|
|
if (TkeyCtrlDataAvailable && !Endpoint4UploadBusy) {
|
|
|
|
if (TkeyCtrlRxBufLength == MAX_PACKET_SIZE) {
|
|
// Write upload endpoint
|
|
memcpy(Ep0Buffer+128, /* Copy to IN (TX) buffer of Endpoint 4 */
|
|
TkeyCtrlRxBuf,
|
|
TkeyCtrlRxBufLength);
|
|
} else {
|
|
memset(Ep0Buffer+128, 0, MAX_PACKET_SIZE);
|
|
// Write upload endpoint
|
|
memcpy(Ep0Buffer+128, /* Copy to IN (TX) buffer of Endpoint 4 */
|
|
TkeyCtrlRxBuf,
|
|
TkeyCtrlRxBufLength);
|
|
}
|
|
|
|
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
|
|
Endpoint4UploadBusy = 1; // Set busy flag
|
|
|
|
TkeyCtrlDataAvailable = 0;
|
|
TkeyCtrlRxBufLength = 0;
|
|
|
|
if (FrameRemainingBytes == 0) {
|
|
// Complete frame sent, get next header and data
|
|
FrameStarted = 0;
|
|
}
|
|
}
|
|
|
|
#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");
|
|
break;
|
|
|
|
case 'r':
|
|
/** UART */
|
|
UartRxBufInputPointer = 0;
|
|
UartRxBufOutputPointer = 0;
|
|
UartRxBufOverflow = 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");
|
|
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("UartRxBufOverflow = "); printNumU32(UartRxBufOverflow); 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);
|
|
}
|
|
#endif
|
|
} /* END if (UsbConfig) */
|
|
} /* END while (1) */
|
|
}
|