////TODO: refactoring into structure /** * @file USBd_config.c * @brief Standard USB Descriptor Definitions fix bugs 2020-1-23 * @version 0.2 * @date 2020-1-23 * * */ #include #include #include "USBd_config.h" #include "usb_defs.h" #define USBShort(ui16Value) ((ui16Value) & 0xff), ((ui16Value) >> 8) //((ui16Value) & 0xFF),(((ui16Value) >> 8) & 0xFF) /** * @brief step 1. Build Standard Device Descriptor * */ // Standard Device Descriptor const uint8_t kUSBd0DeviceDescriptor[0x12] = { 0x12, // bLength USB_DT_DEVICE, // bDescriptorType #if (USE_WINUSB == 1) USBShort(0x0210), // bcdUSB #else USBShort(0x0200), // bcdUSB #endif ////TODO: Is it also available elsewhere? // We need to use a device other than the USB-IF standard, set to 0x00 0x00, // bDeviceClass 0x00, // bDeviceSubClass 0x00, // bDeviceProtocol USBD0_MAX_PACKET0, // bMaxPacketSize0 Maximum packet size for default pipe. USBShort(USBD0_DEV_DESC_IDVENDOR), // idVendor Vendor ID (VID). USBShort(USBD0_DEV_DESC_IDPRODUCT), // idProduct Product ID (PID). USBShort(USBD0_DEV_DESC_BCDDEVICE), // bcdDevice Device Version BCD. 0x01, // iManufacturer Index of Manufacturer string identifier. 0x02, // iProduct Index of Product string identifier. 0x03 * USBD0_STR_DESC_SER_EN, // iSerialNumber Index of Product serial number. 0x01 // bNumConfigurations Number of configurations. }; /** * @brief step 2. Buid Standard Configuration Descriptor * */ // Standard Interface Descriptor #if (USE_WINUSB ==1) const uint8_t kUSBd0InterfaceDescriptor[0x1E]= { 0x09, // bLength USB_DT_INTERFACE, // bDescriptorType USBD_CUSTOM_CLASS0_IF0_NUM, // bInterfaceNumber USBD_CUSTOM_CLASS0_IF0_ALT, // bAlternateSetting 0x03, // bNumEndpoints(we will use 3 endpoints) // USBD_CUSTOM_CLASS0_IF0_CLASS, // bInterfaceClass USBD_CUSTOM_CLASS0_IF0_SUBCLASS, // bInterfaceSubClass USBD_CUSTOM_CLASS0_IF0_PROTOCOL, // bInterfaceProtocol 0x00, // iInterface // Index of string descriptor describing this interface ////TODO: fix this 0x04 ? // Standard Endpoint Descriptor // Endpoint 1: Bulk Out – used for commands received from host PC. // Endpoint 2: Bulk In – used for responses send to host PC. // Endpoint 3: Bulk In (optional) – used for streaming SWO trace // ATTENTION: // physical endpoint 1 indeed included two "endpoints": Bulk OUT and Bulk IN // physical endpoint 1 -> Endpoint 1 & Endpoint 2 // physical endpoint 2 -> Endpoint 3 // See also : // http://www.keil.com/pack/doc/CMSIS/DAP/html/group__DAP__ConfigUSB__gr.html /* Pysical endpoint 1 */ // "Endpoint 1: Bulk Out – used for commands received from host PC." PC -> Device 0x07, // bLength USB_DT_ENDPOINT, // bDescriptorType 0x01, // bEndpointAddress USB_ENDPOINT_ATTR_BULK, // bmAttributes USBShort(512), // wMaxPacketSize // We assume that it always runs in High Speed. 0x00, // bInterval /* Pysical endpoint 1 */ // "Endpoint 2: Bulk In – used for responses send to host PC." Device -> PC 0x07, // bLength USB_DT_ENDPOINT, // bDescriptorType 0x81, // bEndpointAddress USB_ENDPOINT_ATTR_BULK, // bmAttributes USBShort(512), // wMaxPacketSize 0x00, // bInterval /* Pysical endpoint 2 */ // "Endpoint 3: Bulk In (optional) – used for streaming SWO trace" Device -> PC 0x07, // bLength USB_DT_ENDPOINT, // bDescriptorType 0x82, // bEndpointAddress USB_ENDPOINT_ATTR_BULK, // bmAttributes USBShort(512), // wMaxPacketSize 0x00, // bInterval }; #else const uint8_t kUSBd0InterfaceDescriptor[0x20]= { 0x09, // bLength USB_DT_INTERFACE, // bDescriptorType USBD_CUSTOM_CLASS0_IF0_NUM, // bInterfaceNumber USBD_CUSTOM_CLASS0_IF0_ALT, // bAlternateSetting 0x02, // bNumEndpoints ----> 2 endpoint for USB HID // USBD_CUSTOM_CLASS0_IF0_CLASS, // bInterfaceClass USBD_CUSTOM_CLASS0_IF0_SUBCLASS, // bInterfaceSubClass USBD_CUSTOM_CLASS0_IF0_PROTOCOL, // bInterfaceProtocol 0x00, // iInterface // Index of string descriptor describing this interface // HID Descriptor 0x09, // bLength 0x21, // bDescriptorType 0x11, 0x01, // bcdHID 0x00, // bCountryCode 0x01, // bNumDescriptors 0x22, // bDescriptorType1 0x21, 0x00, // wDescriptorLength1 // Standard Endpoint Descriptor // We perform all transfer operations on Pysical endpoint 1. /* Pysical endpoint 1 */ 0x07, // bLength USB_DT_ENDPOINT, // bDescriptorType 0x81, // bEndpointAddress USB_ENDPOINT_ATTR_INTERRUPT, // bmAttributes USBShort(64), // wMaxPacketSize 0x01, // bInterval /* Pysical endpoint 1 */ 0x07, // bLength USB_DT_ENDPOINT, // bDescriptorType 0x01, // bEndpointAddress USB_ENDPOINT_ATTR_INTERRUPT, // bmAttributes USBShort(64), // wMaxPacketSize 0x01, // bInterval }; #endif // Standard Configuration Descriptor #define LENGTHOFCONFIGDESCRIPTOR 9 #if (USE_WINUSB == 1) const uint8_t kUSBd0ConfigDescriptor[LENGTHOFCONFIGDESCRIPTOR] = { // Configuration descriptor header. 0x09, // bLength USB_DT_CONFIGURATION, // bDescriptorType USBShort((sizeof(kUSBd0InterfaceDescriptor)) + (LENGTHOFCONFIGDESCRIPTOR)), // wTotalLength 0x01, // bNumInterfaces // There is only one interface in the CMSIS-DAP project 0x01, // bConfigurationValue: 0x01 is used to select this configuration */ 0x00, // iConfiguration: no string to describe this configuration */ USBD0_CFG_DESC_BMATTRIBUTES, // bmAttributes USBD0_CFG_DESC_BMAXPOWER, // bMaxPower }; #else const uint8_t kUSBd0ConfigDescriptor[LENGTHOFCONFIGDESCRIPTOR] = { // Configuration descriptor header. 0x09, // bLength USB_DT_CONFIGURATION, // bDescriptorType USBShort((sizeof(kUSBd0InterfaceDescriptor)) + (LENGTHOFCONFIGDESCRIPTOR)), // wTotalLength 0x01, // bNumInterfaces // There is only one interface in the CMSIS-DAP project 0x01, // bConfigurationValue: 0x01 is used to select this configuration */ 0x00, // iConfiguration: no string to describe this configuration */ USBD0_CFG_DESC_BMATTRIBUTES, // bmAttributes USBD0_CFG_DESC_BMAXPOWER, // bMaxPower }; #endif // USB HID Report Descriptor const uint8_t kHidReportDescriptor[0x21] = { 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) 0x09, 0x01, // Usage (0x01) 0xA1, 0x01, // Collection (Application) 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x00, // Logical Maximum (255) 0x75, 0x08, // Report Size (8) 0x95, 0xFF, // Report Count (64) 0x09, 0x01, // Usage (0x01) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x95, 0xFF, // Report Count (64) 0x09, 0x01, // Usage (0x01) 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0x95, 0x01, // Report Count (1) 0x09, 0x01, // Usage (0x01) 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xC0, // End Collection // 33 bytes }; /** * @brief step 3. Build String Descriptor * */ const uint8_t kLangDescriptor[0x04] = { 4, USB_DT_STRING, USBShort(USB_LANGID_ENGLISH_US) }; /** * @brief We will use these string descriptor: * 1. Manufacturer string -> "KEIL - Tools By ARM" * 2. Product string -> "LPC-Link-II" * 3. Serial number string -> "0001A0000000" * 4. Interface string -> "LPC-Link-II CMSIS-DAP" * * */ const uint8_t kManufacturerString[0x28] = { 0x28, // bLength 0x03, // bDescriptorType // "KEIL - Tools By ARM" 'K', 0, 'E', 0, 'I', 0, 'L', 0, ' ', 0, '-', 0, ' ', 0, 'T', 0, 'o', 0, 'o', 0, 'l', 0, 's', 0, ' ', 0, 'B', 0, 'y', 0, ' ', 0, 'A', 0, 'R', 0, 'M', 0 }; const uint8_t kProductString[0x18] = { 0x18, // bLength 0x03, // bDescriptorType // "LPC-Link-II" 'L', 0, 'P', 0, 'C', 0, '-', 0, 'L', 0, 'i', 0, 'n', 0, 'k', 0, '-', 0, 'I', 0, 'I', 0 }; const uint8_t kSerialNumberString[0x1A] = { 0x1A, // bLength 0x03, // bDescriptorType // "0001A0000000" '0', 0, '0', 0, '0', 0, '1', 0, 'A', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0 }; const uint8_t kInterfaceString[0x2C] = { 0x2C, // bLength 0x03, // bDescriptorType // "LPC-Link-II CMSIS-DAP" 'L', 0, 'P', 0, 'C', 0, '-', 0, 'L', 0, 'i', 0, 'n', 0, 'k', 0, '-', 0, 'I', 0, 'I', 0, ' ', 0, 'C', 0, 'M', 0, 'S', 0, 'I', 0, 'S', 0, '-', 0, 'D', 0, 'A', 0, 'P', 0 }; const uint8_t * const kUSBd0StringDescriptorsSet[0x05] = { kLangDescriptor, kManufacturerString, kProductString, kSerialNumberString, kInterfaceString };