diff options
-rw-r--r-- | CMakeLists.txt | 9 | ||||
-rw-r--r-- | main.c | 14 | ||||
-rw-r--r-- | tusb_callbacks.c | 141 | ||||
-rw-r--r-- | tusb_config.h | 30 | ||||
-rw-r--r-- | tusb_helpers.h | 9 | ||||
-rwxr-xr-x | tusb_helpers.h.gen | 2 | ||||
-rw-r--r-- | usb_common.c | 150 | ||||
-rw-r--r-- | usb_common.h | 49 | ||||
-rw-r--r-- | usb_keyboard.c | 108 | ||||
-rw-r--r-- | usb_keyboard.h | 10 | ||||
-rw-r--r-- | usbkeyboard.c | 15 |
11 files changed, 363 insertions, 174 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f229d17..bb5abcf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,9 +10,16 @@ pico_sdk_init() add_executable(sbc_harness) target_sources(sbc_harness PUBLIC main.c + usb_common.c + usb_keyboard.c ) target_include_directories(sbc_harness PUBLIC ${CMAKE_CURRENT_LIST_DIR}) # So TinyUSB can find tusb_config.h -target_link_libraries(sbc_harness pico_stdlib) +target_link_libraries(sbc_harness + pico_stdlib + pico_unique_id + tinyusb_device + tinyusb_board +) pico_enable_stdio_usb(sbc_harness 0) pico_enable_stdio_uart(sbc_harness 1) pico_enable_stdio_semihosting(sbc_harness 0) @@ -6,12 +6,17 @@ #include "bsp/board_api.h" #include "tusb.h" +/* local */ +#include "usb_keyboard.h" + int main() { /* pico-sdk initialization */ stdio_uart_init(); gpio_init(PICO_DEFAULT_LED_PIN); gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); + usb_keyboard_init(); + /* TinyUSB initialization */ board_init(); tud_init(BOARD_TUD_RHPORT); @@ -20,7 +25,12 @@ int main() { /* Event loop. */ for (;;) { - tud_task(); /* run TinyUSB */ - usbkeyboard_task(); + tud_task(); + usb_keyboard_task(); + if (usb_keyboard_is_flushed()) { + char *msg = "Hello world!\n"; + for (size_t i = 0; i < strlen(msg); i++) + usb_keyboard_send_char(msg[i]); + } } } diff --git a/tusb_callbacks.c b/tusb_callbacks.c deleted file mode 100644 index 84214c9..0000000 --- a/tusb_callbacks.c +++ /dev/null @@ -1,141 +0,0 @@ -/* tinyusb */ -#include "bsp/board_api.h" -#include "tusb.h" - -/* local */ -#include "tusb_helpers.h" - -#define NUM_INTERFACES CFG_TUD_HID -#define NUM_CONFIGS 1 - -enum { - STRID_LANGID = 0, - STRID_MANUF, - STRID_PRODUCT, - STRID_SERIAL, - - STRID_NONE = 0, -}; - -/** - * 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 max_u16len = (sizeof desc / sizeof desc[0]) - 1; - - static uint16_t const langids[] = { - LANGID_EN_US, - }; - - size_t bytelen = 0; - if (index == 0) { - memcpy(&desc[1], langids, sizeof langids); - bytelen = sizeof langids; - } else { - 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; - default: - return NULL; - }; - default: - return NULL; - } - } - assert(bytelen <= 0xFF-2); - desc[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2+bytelen)); - return desc; -} - -/** - * Return a pointer to the USB "Device Descriptor" (see USB 2.0 §9.6.1 - * "Device") as a byte-array. - */ -uint8_t const *tud_decriptor_device_cb(void) { - /* Our device descriptor is static, so just declare it as a - * static const. */ - static tusb_desc_device_t const desc = { - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x200, /* USB 2.0 */ - - /* Use the "base device class", which means to use information - * form interface descriptors instead of a global device - * descriptor. */ - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - - .idVendor = 0xCAFE, /* Vendor ID (assigned by the USB-IF) */ - .idProduct = 0x4001, /* Product ID (assigned by the manufacturer) */ - .bcdDevice = 0x0100, /* Device release number */ - - .iManufacturer = STRID_MANUF /* Index of string descriptor describing manufacturer */ - .iProduct = STRID_PRODUCT, /* Index of string descriptor describing product */ - .iSerialNumber = STRID_SERIAL, /* Index of string descriptor describing the device's serial number */ - - .bNumConfigurations = NUM_CONFIGS, /* Number of possible configurations */ - }; - return (uint8_t const *) &desc; -} - -/** - * A USB-HID "Report Descriptor" (see USB-HID 1.11 §6.2.2 "Report - * Descriptor") describing a keyboard. - */ -static uint8_t const hid_report_descriptor_keyboard[] = { TUD_HID_REPORT_DESC_KEYBOARD() }; - -/** - * Return a pointer to the USB config "Configuration Descriptor" (see - * USB 2.0 §9.6.4 "Configuration") for the given index. - */ -uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { - static uint8_t const configs[NUM_CONFIGS][] = { - { - /* USB configuration descriptor header (USB 2.0 §9.6.4 "Configuration") */ - TUD_CONFIG_DESCRIPTOR( - 1, /* bConfigurationValue ; Value to use as an argument to the SetConfiguration() request to select this configuration */ - NUM_INTERFACES, /* bNumInterfaces ; Number of interfaces supported by this configuration */ - STRID_NONE, /* iConfiguration ; Index of string descriptor describing this configuration */ - TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN, /* wTotalLength ; Total lenggth of data returned for this configuration */ - TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, /* bmAttributes ; Bitmap of flags (self-powered and remote-wakeup are the only flags defined in USB 2.0) */ - 100), /* bMaxPower (in mA) ; Maximum power consumption of the device when in this configuration */ - /* USB-HID input-only descriptor; consisting of 3 parts: - * 1. an interface descriptor (USB 2.0 §9.6.5 "Interface"), - * 2. a class-specific (class=HID) descriptor of type HID (USB-HID 1.11 §6.2.1 "HID Descriptor"), - * 3. an endpoint descriptor for inputs (USB 2.0 §9.6.6 "Endpoint"). - * The TUD_HID_DESCRIPTOR() macro takes care of this for us. */ - TUD_HID_DESCRIPTOR( - 0, /* interface : bInterfaceNumber ; Number of this interface (0-indexed) */ - STRID_NONE, /* interface : iInterface ; Index of string descriptor describing this interface */ - HID_ITF_PROTOCOL_KEYBOARD, /* interface : bInterfaceProtocol ; see USB-HID 1.11 §4.3 "Protocols" */ - sizeof(hid_report_descriptor_keyboard), /* hid : wDescriptorLength ; Total size of report descriptor */ - TUD_ENDPOINT_IN | 1, /* endpoint : bEndpointAddress ; Direction | endpoint number (arbitrary?) */ - CFG_TUD_HID_EP_BUFSIZE, /* endpoint : wMaxPacketSize ; Maximum packet size this endpoint is capable of sending or receiving */ - 10), /* endpoint : bInterval ; poll interval (in milliseconds?) */ - }, - }; - if (index >= sizeof config / sizeof configs[0]) - return NULL; - return configs[index]; -} - -/** - * Return a pointer to the HID "Report Descriptor" (see USB-HID 1.11 - * §6.2.2 "Report Descriptor") for the given index. - */ -uint8_t const *tud_hid_descriptor_report_cb(uint8_t index) { - static uint8_t const *reports[NUM_INTERFACES] = { - hid_report_descriptor_keyboard, - }; - if (index >= sizeof reports / sizeof reports[0]) - return NULL; - return reports[index]; -} diff --git a/tusb_config.h b/tusb_config.h index 051c39c..37b14b3 100644 --- a/tusb_config.h +++ b/tusb_config.h @@ -52,7 +52,6 @@ extern "C" { #error CFG_TUSB_MCU must be defined #endif -#define CFG_TUSB_OS OPT_OS_NONE #define CFG_TUSB_DEBUG 0 // USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. @@ -75,19 +74,22 @@ extern "C" { #define CFG_TUD_ENDPOINT0_SIZE 64 // Which of TinyUSB's built-in class drivers to enable. -#define CFG_TUD_CDC 0 // Communications Device Class (e.g. ttyUSB) https://www.usb.org/sites/default/files/CDC1.2_WMC1.1_012011.zip -#define CFG_TUD_MSC 0 // Mass Storage Class https://www.usb.org/sites/default/files/Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf -#define CFG_TUD_HID 1 // Human Interface Device (num is how many interfaces) https://www.usb.org/sites/default/files/hid1_11.pdf -#define CFG_TUD_AUDIO 0 // Audio https://www.usb.org/sites/default/files/audio10.pdf -#define CFG_TUD_VIDEO 0 // Video https://www.usb.org/sites/default/files/USB_Video_Class_1_5.zip -#define CFG_TUD_MIDI 0 // Musical Instrument Digital Interface https://www.usb.org/sites/default/files/USB%20MIDI%20v2_0.pdf -#define CFG_TUD_VENDOR 0 // ??? -#define CFG_TUD_USBTMC 0 // Test & Measurement Class https://www.usb.org/sites/default/files/USBTMC_1_006a.zip -#define CFG_TUD_DFU_RUNTIME 0 // Device Firmware Upgrade https://www.usb.org/sites/default/files/DFU_1.1.pdf -#define CFG_TUD_DFU 0 // Device Firmware Upgrade https://www.usb.org/sites/default/files/DFU_1.1.pdf -#define CFG_TUD_ECM_RNDIS 0 // net -#define CFG_TUD_NCM 0 // net -#define CFG_TUD_BTH 0 // Bluetooth +// +// If a class takes an int, that's the maximum number of interfaces of +// that type that may be listed in the same configuration descriptor. +#define CFG_TUD_CDC 0 // int : Communications Device Class (e.g. ttyUSB) https://www.usb.org/sites/default/files/CDC1.2_WMC1.1_012011.zip +#define CFG_TUD_MSC 0 // bool: Mass Storage Class https://www.usb.org/sites/default/files/Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf +#define CFG_TUD_HID 1 // int : Human Interface Device https://www.usb.org/sites/default/files/hid1_11.pdf +#define CFG_TUD_AUDIO 0 // int : Audio https://www.usb.org/sites/default/files/audio10.pdf +#define CFG_TUD_VIDEO 0 // int : Video https://www.usb.org/sites/default/files/USB_Video_Class_1_5.zip +#define CFG_TUD_MIDI 0 // int : Musical Instrument Digital Interface https://www.usb.org/sites/default/files/USB%20MIDI%20v2_0.pdf +#define CFG_TUD_VENDOR 0 // int : ??? +#define CFG_TUD_USBTMC 0 // bool: Test & Measurement Class https://www.usb.org/sites/default/files/USBTMC_1_006a.zip +#define CFG_TUD_DFU_RUNTIME 0 // bool: Device Firmware Upgrade https://www.usb.org/sites/default/files/DFU_1.1.pdf +#define CFG_TUD_DFU 0 // bool: Device Firmware Upgrade https://www.usb.org/sites/default/files/DFU_1.1.pdf +#define CFG_TUD_ECM_RNDIS 0 // bool: net +#define CFG_TUD_NCM 0 // bool: net +#define CFG_TUD_BTH 0 // bool: Bluetooth // HID buffer size Should be sufficient to hold ID (if any) + Data #define CFG_TUD_HID_EP_BUFSIZE 8 diff --git a/tusb_helpers.h b/tusb_helpers.h index 452a32e..0e04988 100644 --- a/tusb_helpers.h +++ b/tusb_helpers.h @@ -966,4 +966,13 @@ #define TUD_ENDPOINT_OUT 0x00 #define TUD_ENDPOINT_IN 0x80 +#define UTF16(str) u ## str + +static inline size_t utf16_strncpy(uint16_t *dst, uint16_t *src, size_t dsize) { + size_t i; + for (i = 0; i < dsize && src && src[i]; i++) + dst[i] = src[i]; + return i; +} + #endif /* _USB_HELPERS_H_ */ diff --git a/tusb_helpers.h.gen b/tusb_helpers.h.gen index 4682166..8ef83c8 100755 --- a/tusb_helpers.h.gen +++ b/tusb_helpers.h.gen @@ -77,7 +77,7 @@ cat <<'EOT' #define UTF16(str) u ## str -static inline size_t utf16_strncpy(uint16_t *dst, uint16_t *src, dsize size_t) { +static inline size_t utf16_strncpy(uint16_t *dst, uint16_t *src, size_t dsize) { size_t i; for (i = 0; i < dsize && src && src[i]; i++) dst[i] = src[i]; diff --git a/usb_common.c b/usb_common.c new file mode 100644 index 0000000..0427122 --- /dev/null +++ b/usb_common.c @@ -0,0 +1,150 @@ +#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 "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 "usb_common.h" + +/* Strings ********************************************************************/ + +/** + * 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; + + static uint16_t const langids[] = { + LANGID_EN_US, + }; + + size_t bytelen = 0; + if (index == 0) { + memcpy(&desc[1], langids, sizeof langids); + bytelen = sizeof langids; + } else { + 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; + default: + return NULL; + }; + default: + return NULL; + } + } + assert(bytelen <= 0xFF-2); + desc[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2+bytelen)); + return desc; +} + +/* Globals ********************************************************************/ + +uint8_t cfgnum_std = 0; + +void usb_common_init(void) { + if (cfgnum_std) + return; + cfgnum_std = usb_add_config( + STRID_CFG, /* iConfiguration ; Index of string descriptor describing this configuration */ + TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, /* bmAttributes ; Bitmap of flags (self-powered and remote-wakeup are the only flags defined in USB 2.0) */ + 100); /* bMaxPower (in mA) ; Maximum power consumption of the device when in this configuration */ +} + +/* Main utilities *************************************************************/ + +static uint8_t configc = 0; +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); + desc = configv[configc-1] = malloc(TUD_CONFIG_DESC_LEN); + + memcpy(desc, (uint8_t[]){ + /* USB configuration descriptor header (USB 2.0 §9.6.4 "Configuration") */ + TUD_CONFIG_DESCRIPTOR( + configc, /* bConfigurationValue */ + 0, /* bNumInterfaces (will be incremented by usb_add_interface() */ + iConfiguration, /* iConfiguration */ + TUD_CONFIG_DESC_LEN, /* wTotalLength (will be incremented by usb_add_interface() */ + bmAttributes, /* bmAttributes */ + bMaxPower_mA+1), /* bMaxPower (+1 because tusb just does n/2 instead of (n+1)/2) */ + }, TUD_CONFIG_DESC_LEN); + + return configc; +} + +uint8_t usb_add_interface(uint8_t cfg_num, uint16_t ifc_len, uint8_t *ifc_dat) { + assert(cfg_num > 0 && cfg_num <= configc); + assert(ifc_len >= 3); + assert(ifc_dat); + + uint8_t *desc = configv[cfg_num-1]; + // wTotalLength + uint16_t total_len = TU_U16(desc[3], desc[2]) + ifc_len; + desc[3] = TU_U16_HIGH(total_len); + desc[2] = TU_U16_LOW(total_len); + // bNumInterfaces + ifc_dat[3] = desc[4]++; + + desc = configv[cfg_num-1] = realloc(desc, total_len); + memcpy(&desc[total_len-ifc_len], ifc_dat, ifc_len); + + return ifc_dat[3]; +} + +/** + * Return a pointer to the USB "Device Descriptor" (see USB 2.0 §9.6.1 + * "Device") as a byte-array. + */ +uint8_t const *tud_descriptor_device_cb(void) { + /* Our device descriptor is static, so just declare it as a + * static const. */ + static tusb_desc_device_t desc = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x200, /* USB 2.0 */ + + /* Use the "base device class", which means to use information + * from interface descriptors instead of a global device + * descriptor. */ + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = 0xCAFE, /* Vendor ID (assigned by the USB-IF) */ + .idProduct = 0x4001, /* Product ID (assigned by the manufacturer) */ + .bcdDevice = 0x0100, /* Device release number */ + + .iManufacturer = STRID_MANUF, /* Index of string descriptor describing manufacturer */ + .iProduct = STRID_PRODUCT, /* Index of string descriptor describing product */ + .iSerialNumber = STRID_SERIAL, /* Index of string descriptor describing the device's serial number */ + + .bNumConfigurations = 0, /* Number of possible configurations */ + }; + desc.bNumConfigurations = configc; + return (uint8_t const *) &desc; +} + +/** + * Return a pointer to the USB config "Configuration Descriptor" (see + * USB 2.0 §9.6.4 "Configuration") for the given index. + */ +uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { + if (index >= configc) + return NULL; + return configv[index]; +} diff --git a/usb_common.h b/usb_common.h new file mode 100644 index 0000000..f0ed844 --- /dev/null +++ b/usb_common.h @@ -0,0 +1,49 @@ +#ifndef _USB_COMMON_H_ +#define _USB_COMMON_H_ + +/* Strings ********************************************************************/ + +enum { + /* Be sure to keep this list in-sync with + * usb_common.c:tud_descriptor_string_cb() */ + STRID_LANGID = 0, + STRID_MANUF, + STRID_PRODUCT, + STRID_SERIAL, + STRID_CFG, + STRID_KBD_IFC, + + STRID_NONE = 0, +}; + +/* Globals ********************************************************************/ + +extern uint8_t cfgnum_std; +void usb_common_init(void); + +/* Main utilities *************************************************************/ + +/** + * Declare a new TUD configuration. + * + * @param iConfiguration : ID of the string descriptor describing this configuration + * @param bmAttributes : bitmap of flags; TUSB_DESC_CONFIG_ATT_{REMOTE_WAKUP,SELF_POWERED} + * @param bMaxPower_mA : maximum power consumption of the device when in this configuration, in mA + * @return the configuration number for the created config + */ +uint8_t usb_add_config(uint8_t iConfiguration, uint8_t bmAttributes, uint8_t bMaxPower_mA); + +/** + * Add an interface to a configuration that has been created with usb_add_config(). + * + * @param cfg_num : the value returned from usb_add_config() + * @param ifc_len : the length of ifc_Dat + * @param ifc_dat : the raw descriptor data for the interface (probably created by + * TUD_{CLASS}_DESCRIPTOR(); grep TinyUSB/src/device/usbd.h for '#define + * TUD_\S*_DESCRIPTOR(_itfnum'). The interface number in this data is overwritten with the + * appropriate number for this config. + * @return the interface number for the added interface + */ +uint8_t usb_add_interface(uint8_t cfg_num, uint16_t ifc_len, uint8_t *ifc_dat); + +#endif /* _USB_COMMON_H_ */ diff --git a/usb_keyboard.c b/usb_keyboard.c new file mode 100644 index 0000000..5647403 --- /dev/null +++ b/usb_keyboard.c @@ -0,0 +1,108 @@ +#include "tusb.h" + +#include "tusb_helpers.h" /* for TUD_ENDPOINT_IN */ +#include "usb_common.h" +#include "usb_keyboard.h" + +/** + * A USB-HID "Report Descriptor" (see USB-HID 1.11 §6.2.2 "Report + * Descriptor") describing a keyboard. + */ +static uint8_t const hid_report_descriptor_keyboard[] = { TUD_HID_REPORT_DESC_KEYBOARD() }; + +static uint8_t kbd_ifc = 0; + +void usb_keyboard_init() { + if (kbd_ifc) + return; + usb_common_init(); + + kbd_ifc = usb_add_interface(cfgnum_std, TUD_HID_DESC_LEN, (uint8_t[]){ + /* USB-HID input-only descriptor for inclusion in the config descriptor; consisting of 3 parts: + * 1. an interface descriptor (USB 2.0 §9.6.5 "Interface"), + * 2. a class-specific (class=HID) descriptor of type HID (USB-HID 1.11 §6.2.1 "HID Descriptor"), + * 3. an endpoint descriptor for inputs (USB 2.0 §9.6.6 "Endpoint"). + * The TUD_HID_DESCRIPTOR() macro takes care of this for us. */ + TUD_HID_DESCRIPTOR( + 0, /* interface : bInterfaceNumber ; Number of this interface (0-indexed) */ + STRID_KBD_IFC, /* interface : iInterface ; Index of string descriptor describing this interface */ + HID_ITF_PROTOCOL_KEYBOARD, /* interface : bInterfaceProtocol ; see USB-HID 1.11 §4.3 "Protocols" */ + sizeof(hid_report_descriptor_keyboard), /* hid : wDescriptorLength ; Total size of report descriptor */ + TUD_ENDPOINT_IN | 1, /* endpoint : bEndpointAddress ; Direction | endpoint number (arbitrary?) */ + CFG_TUD_HID_EP_BUFSIZE, /* endpoint : wMaxPacketSize ; Maximum packet size this endpoint is capable of sending or receiving */ + 10), /* endpoint : bInterval ; poll interval (in milliseconds?) */ + }); +} + +#define kbd_buf_cap 1024 +static uint32_t kbd_buf[kbd_buf_cap]; +static size_t kbd_buf_beg = 0; +static size_t kbd_buf_len = 0; + +static uint8_t ascii2keycode[128][2] = { HID_ASCII_TO_KEYCODE }; + +void usb_keyboard_task(void) { + if (tud_hid_n_ready(kbd_ifc)) { + uint8_t const report_id = 0; + uint8_t modifier = 0; + uint8_t keycodes[6] = {0}; + + if (kbd_buf_len) { + if (ascii2keycode[kbd_buf[kbd_buf_beg]][0]) + modifier = KEYBOARD_MODIFIER_LEFTSHIFT; + keycodes[0] = ascii2keycode[kbd_buf[kbd_buf_beg]][1]; + + kbd_buf_beg++; + if (kbd_buf_beg == kbd_buf_cap) + kbd_buf_beg = 0; + kbd_buf_len--; + } + + tud_hid_n_keyboard_report(kbd_ifc, report_id, modifier, keycodes); + } +} + +bool usb_keyboard_send_char(uint32_t ch) { + if (kbd_buf_len == kbd_buf_cap) /* buffer full */ + return false; + if (ch > 0x7F) /* not ASCII */ + return false; + kbd_buf[(kbd_buf_beg + kbd_buf_len++) % kbd_buf_cap] = ch; +} + +bool usb_keyboard_is_flushed(void) { + return kbd_buf_len == 0; +} + +/** + * Return a pointer to the HID "Report Descriptor" (see USB-HID 1.11 + * §6.2.2 "Report Descriptor") for the given index. + */ +uint8_t const *tud_hid_descriptor_report_cb(uint8_t index) { + static uint8_t const *reports[] = { + hid_report_descriptor_keyboard, + }; + if (index >= sizeof reports / sizeof reports[0]) + return NULL; + return reports[index]; +} + +uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) +{ + // TODO not Implemented + (void) instance; + (void) report_id; + (void) report_type; + (void) buffer; + (void) reqlen; + + return 0; +} + +// Invoked when received SET_REPORT control request or +// received data on OUT endpoint ( Report ID = 0, Type = 0 ) +void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) +{ + // TODO not implemented + (void) report_id; +} diff --git a/usb_keyboard.h b/usb_keyboard.h new file mode 100644 index 0000000..9460feb --- /dev/null +++ b/usb_keyboard.h @@ -0,0 +1,10 @@ +#ifndef _USB_KEYBOARD_H_ +#define _USB_KEYBOARD_H_ + +void usb_keyboard_init(void); +void usb_keyboard_task(void); + +bool usb_keyboard_send_char(uint32_t ch); +bool usb_keyboard_is_flushed(void); + +#endif /* _USB_KEYBOARD_H_ */ diff --git a/usbkeyboard.c b/usbkeyboard.c deleted file mode 100644 index 436610c..0000000 --- a/usbkeyboard.c +++ /dev/null @@ -1,15 +0,0 @@ -void usbkeyboard_send_char(uint32_t ch) { -} - -char - -enum { - IFACE_KEYBOARD = 0 -}; - -void usbkeyboard_task(void) { - if (tud_hid_n_ready(0)) { - uint8_t keycode[6] - } -} - |