diff options
Diffstat (limited to 'usb_common.c')
-rw-r--r-- | usb_common.c | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/usb_common.c b/usb_common.c index 0427122..9d59afe 100644 --- a/usb_common.c +++ b/usb_common.c @@ -1,11 +1,11 @@ #include <stdint.h> /* for uint{n}_t types */ #include <string.h> /* memcpy(newlib) */ #include <assert.h> /* for assert(newlib) */ -#include <stdlib.h> /* for malloc(pico_malloc) and realloc(pico_malloc) */ +#include <stdlib.h> /* for malloc(pico_malloc), realloc(pico_malloc), reallocarray(pico_malloc) */ #include "bsp/board_api.h" /* for board_usb_get_serial(TinyUSB) */ #include "tusb.h" /* for various tusb_*_t types */ -#include "tusb_helpers.h" /* for LANGID_*, UTF16(), utf16_strncpy */ +#include "tusb_helpers.h" /* for LANGID_*, TU_UTF16() */ #include "usb_common.h" /* Strings ********************************************************************/ @@ -14,37 +14,51 @@ * Return a pointer to the USB "String Descriptor" (see USB 2.0 ยง9.6.7 * "String"). */ -uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - static uint16_t desc[0xFF/2]; - static const size_t max_u16len = (sizeof desc / sizeof desc[0]) - 1; +uint16_t const *tud_descriptor_string_cb(uint8_t strid, uint16_t langid) { + static struct TU_ATTR_PACKED { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bString[(0xFF-2)/2]; + } desc; + TU_VERIFY_STATIC(sizeof desc == (0xFF/2)*2, "incorrect size"); static uint16_t const langids[] = { LANGID_EN_US, }; size_t bytelen = 0; - if (index == 0) { - memcpy(&desc[1], langids, sizeof langids); + if (strid == 0) { + memcpy(desc.bString, langids, sizeof langids); bytelen = sizeof langids; } else { +#define CONST_STR(str) bytelen = ((sizeof (str))-1); memcpy(desc.bString, (str), ((sizeof (str))-1)); switch (langid) { case LANGID_EN_US: - switch (index) { - case STRID_MANUF: bytelen = 2 * utf16_strncpy(&desc[1], UTF16("Umorpha Systems"), max_u16len); break; - case STRID_PRODUCT: bytelen = 2 * utf16_strncpy(&desc[1], UTF16("SBC-Harness Keyboard"), max_u16len); break; - case STRID_SERIAL: bytelen = 2 * board_usb_get_serial(&desc[1], max_u16len); break; - case STRID_CFG: bytelen = 2 * utf16_strncpy(&desc[1], UTF16("Standard Configuration"), max_u16len); break; - case STRID_KBD_IFC: bytelen = 2 * utf16_strncpy(&desc[1], UTF16("Keyboard Interface"), max_u16len); break; + switch (strid) { + case STRID_MANUF: CONST_STR(TU_UTF16("Umorpha Systems")); break; + case STRID_PRODUCT: CONST_STR(TU_UTF16("SBC-Harness Keyboard")); break; + case STRID_CFG: CONST_STR(TU_UTF16("Standard Configuration")); break; + case STRID_KBD_IFC: CONST_STR(TU_UTF16("Keyboard Interface")); break; + case STRID_SERIAL: +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" + bytelen = 2 * board_usb_get_serial(desc.bString, TU_ARRAY_SIZE(desc.bString)); +#pragma GCC diagnostic pop + break; default: + printf("GET STRING: unknown string id=%"PRIu8, strid); return NULL; - }; + } + break; default: + printf("GET STRING: unknown LANGID=%"PRIx16, langid); return NULL; } } - assert(bytelen <= 0xFF-2); - desc[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2+bytelen)); - return desc; + assert(bytelen <= sizeof desc.bString); + desc.bLength = bytelen + 2; + desc.bDescriptorType = TUSB_DESC_STRING; + return (uint16_t *)&desc; } /* Globals ********************************************************************/ @@ -68,7 +82,7 @@ static uint8_t **configv = NULL; uint8_t usb_add_config(uint8_t iConfiguration, uint8_t bmAttributes, uint8_t bMaxPower_mA) { uint8_t *desc; - configv = realloc(configv, (sizeof configv[0]) * ++configc); + configv = reallocarray(configv, ++configc, sizeof configv[0]); desc = configv[configc-1] = malloc(TUD_CONFIG_DESC_LEN); memcpy(desc, (uint8_t[]){ |