1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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];
}
|