diff options
| author | Louis Burda <quent.burda@gmail.com> | 2022-11-20 16:35:30 +0100 |
|---|---|---|
| committer | Louis Burda <quent.burda@gmail.com> | 2022-11-20 16:35:44 +0100 |
| commit | 570c88be0e06de5a36c8af0de7b112e9509325df (patch) | |
| tree | 4c5d4a9f36db5cf6e920d06104f4be66fa2a1766 /src/usb_descriptors.c | |
| parent | 5c2cb697aa8d03eed27b45f8dc67957c45a3d722 (diff) | |
| download | sxkbd-570c88be0e06de5a36c8af0de7b112e9509325df.tar.gz sxkbd-570c88be0e06de5a36c8af0de7b112e9509325df.zip | |
Add CDC stdio driver and logging + panic handlers
Diffstat (limited to 'src/usb_descriptors.c')
| -rw-r--r-- | src/usb_descriptors.c | 307 |
1 files changed, 171 insertions, 136 deletions
diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index c2b4792..8372c2a 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -1,170 +1,205 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - #include "tusb.h" +#include "tusb_types.h" -/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. - * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. - * - * Auto ProductID layout's Bitmap: - * [MSB] HID | MSC | CDC [LSB] - */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ - _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) - -//--------------------------------------------------------------------+ -// Device Descriptors -//--------------------------------------------------------------------+ -tusb_desc_device_t const desc_device = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - - .idVendor = 0xCafe, - .idProduct = USB_PID, - .bcdDevice = 0x0100, - - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, - - .bNumConfigurations = 0x01 +#define ARRLEN(x) (sizeof(x) / sizeof((x)[0])) + +/* same VID/PID with difference interface can cause issues! */ + +#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) \ + | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4)) + +#define USB_VID 0xC0FE +#define USB_BCD 0x0200 + +#define CONFIG_TOTAL_LEN \ + (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN) + +#define EPNUM_HID 0x01 + +/* MCU-specific! */ +#define EPNUM_CDC_NOTIF 0x81 +#define EPNUM_CDC_OUT 0x02 +#define EPNUM_CDC_IN 0x82 +#define EPNUM_MSC_OUT 0x03 +#define EPNUM_MSC_IN 0x83 + +enum { + ITF_NUM_CDC, + ITF_NUM_CTC_DATA, + ITF_NUM_HID, + ITF_NUM_TOTAL }; -// Invoked when received GET DEVICE DESCRIPTOR -// Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ - return (uint8_t const *) &desc_device; -} +tusb_desc_device_t const desc_device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, -//--------------------------------------------------------------------+ -// HID Report Descriptor -//--------------------------------------------------------------------+ + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, -uint8_t const desc_hid_report[] = -{ - TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE) + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = USB_VID, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 }; -// Invoked when received GET HID REPORT DESCRIPTOR -// Application return pointer to descriptor -// Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) -{ - (void) itf; - return desc_hid_report; -} +uint8_t const desc_hid_report[] = { + TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE) +}; -//--------------------------------------------------------------------+ -// Configuration Descriptor -//--------------------------------------------------------------------+ +uint8_t const desc_fs_configuration[] = { + /* Config number, interface count, string index, + * total length, attribute, power in mA */ + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), -enum -{ - ITF_NUM_HID, - ITF_NUM_TOTAL + /* Interface number, string index, EP notification address and size, + * EP data address (out, in) and size */ + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, + EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), + + /* Interface number, string index, protocol, report descriptor len, + * EP In & Out address, size & polling interval */ + TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 5, HID_ITF_PROTOCOL_NONE, + sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, 64, 10) }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_INOUT_DESC_LEN) +#if TUD_OPT_HIGH_SPEED +uint8_t const desc_hs_configuration[] = { + /* Config number, interface count, string index, + * total length, attribute, power in mA */ + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + + /* Interface number, string index, EP notification address and size, + * EP data address (out, in) and size */ + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, + EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), + + /* Interface number, string index, protocol, report descriptor len, + * EP In & Out address, size & polling interval */ + TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 5, HID_ITF_PROTOCOL_NONE, + sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, 512, 10) +}; -#define EPNUM_HID 0x01 +uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; -uint8_t const desc_configuration[] = +tusb_desc_device_qualifier_t const desc_device_qualifier = { - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, + .bcdUSB = USB_BCD, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, - // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval - TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10) + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; +#endif + +char const *string_desc_arr[] = { + [0] = (const char[]) { 0x09, 0x04 }, /* supported language is English */ + [1] = "TinyUSB", /* Manufacturer */ + [2] = "TinyUSB Device", /* Product */ + [3] = "123456", /* Serials, should use chip ID */ + [4] = "SXKBD CDC", + [5] = "SXKBD HID" }; -// Invoked when received GET CONFIGURATION DESCRIPTOR -// Application return pointer to descriptor -// Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +static uint16_t _desc_str[32]; + +/* Invoked on GET DEVICE DESCRIPTOR */ +uint8_t const * +tud_descriptor_device_cb(void) { - (void) index; // for multiple configurations - return desc_configuration; + return (uint8_t const *) &desc_device; } -//--------------------------------------------------------------------+ -// String Descriptors -//--------------------------------------------------------------------+ - -// array of pointer to string descriptors -char const* string_desc_arr [] = +/* Invoked on GET HID REPORT DESCRIPTOR */ +uint8_t const * +tud_hid_descriptor_report_cb(uint8_t itf) { - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - "123456", // 3: Serials, should use chip ID -}; + (void) itf; + return desc_hid_report; +} -static uint16_t _desc_str[32]; +/* Invoked on GET CONFIGURATION DESCRIPTOR */ +uint8_t const * +tud_descriptor_configuration_cb(uint8_t index) +{ + (void) index; + +#if TUD_OPT_HIGH_SPEED + return (tud_speed_get() == TUSB_SPEED_HIGH) ? + desc_hs_configuration : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif +} -// Invoked when received GET STRING DESCRIPTOR request -// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete -uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +/* Invoked on GET STRING DESCRIPTOR */ +uint16_t const * +tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - (void) langid; + const char *str; + uint8_t i, chr_count; + + (void) langid; + + if (index == 0) { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + } else { + if (index >= ARRLEN(string_desc_arr)) + return NULL; - uint8_t chr_count; + str = string_desc_arr[index]; - if ( index == 0) - { - memcpy(&_desc_str[1], string_desc_arr[0], 2); - chr_count = 1; - }else - { - // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. - // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + chr_count = (uint8_t) strlen(str); + if (chr_count > 31) chr_count = 31; - if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; + /* Convert ASCII string into UTF-16 */ + for (i = 0; i < chr_count; i++) + _desc_str[i+1] = str[i]; + } - const char* str = string_desc_arr[index]; + /* first byte is length (including header), second byte is type */ + _desc_str[0] = (uint8_t) (2 * chr_count + 2); + _desc_str[0] |= (uint16_t) (TUSB_DESC_STRING << 8); + + return _desc_str; +} - // Cap at max char - chr_count = (uint8_t) strlen(str); - if ( chr_count > 31 ) chr_count = 31; +#if TUD_OPT_HIGH_SPEED +uint8_t const * +tud_descriptor_device_qualifier_cb(void) +{ + return (uint8_t const*) &desc_device_qualifier; +} + +/* Invoked on GET OTHER SEED CONFIGURATION DESCRIPTOR */ +uint8_t const * +tud_descriptor_other_speed_configuration_cb(uint8_t index) +{ + (void) index; - // Convert ASCII string into UTF-16 - for(uint8_t i=0; i<chr_count; i++) - { - _desc_str[1+i] = str[i]; - } - } + memcpy(desc_other_speed_config, (tud_speed_get() == TUSB_SPEED_HIGH) + ? desc_fs_configuration : desc_hs_configuration, + CONFIG_TOTAL_LEN); - // first byte is length (including header), second byte is string type - _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8 ) | (2*chr_count + 2)); + desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; - return _desc_str; + return desc_other_speed_config; } +#endif |
