summaryrefslogtreecommitdiff
path: root/tusb_callbacks.c
diff options
context:
space:
mode:
Diffstat (limited to 'tusb_callbacks.c')
-rw-r--r--tusb_callbacks.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/tusb_callbacks.c b/tusb_callbacks.c
new file mode 100644
index 0000000..84214c9
--- /dev/null
+++ b/tusb_callbacks.c
@@ -0,0 +1,141 @@
+/* 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];
+}