Open FFBoard
Open source force feedback firmware
hid_device.c
Go to the documentation of this file.
1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2019 Ha Thach (tinyusb.org)
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 * This file is part of the TinyUSB stack.
25 */
26
27#include "tusb_option.h"
28
29#if (CFG_TUD_ENABLED && CFG_TUD_HID)
30
31//--------------------------------------------------------------------+
32// INCLUDE
33//--------------------------------------------------------------------+
34#include "device/usbd.h"
35#include "device/usbd_pvt.h"
36
37#include "hid_device.h"
38
39//--------------------------------------------------------------------+
40// MACRO CONSTANT TYPEDEF
41//--------------------------------------------------------------------+
42typedef struct {
43 uint8_t itf_num;
44 uint8_t ep_in;
45 uint8_t ep_out; // optional Out endpoint
46 uint8_t itf_protocol; // Boot mouse or keyboard
47
49 uint8_t protocol_mode; // Boot (0) or Report protocol (1)
50 uint8_t idle_rate; // up to application to handle idle rate
51
52 // TODO save hid descriptor since host can specifically request this after enumeration
53 // Note: HID descriptor may be not available from application after enumeration
54 tusb_hid_descriptor_hid_t const *hid_descriptor;
55
56 uint8_t ctrl_buf[CFG_TUD_HID_EP_BUFSIZE];
57 CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE];
58 CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE];
60
61CFG_TUD_MEM_SECTION tu_static hidd_interface_t _hidd_itf[CFG_TUD_HID];
62
63/*------------- Helpers -------------*/
64TU_ATTR_ALWAYS_INLINE static inline uint8_t get_index_by_itfnum(uint8_t itf_num) {
65 for (uint8_t i = 0; i < CFG_TUD_HID; i++) {
66 if (itf_num == _hidd_itf[i].itf_num) {
67 return i;
68 }
69 }
70 return 0xFF;
71}
72
73//--------------------------------------------------------------------+
74// Weak stubs: invoked if no strong implementation is available
75//--------------------------------------------------------------------+
76TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol) {
77 (void) instance;
78 (void) protocol;
79}
80
81TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate) {
82 (void) instance;
83 (void) idle_rate;
84 return true;
85}
86
87TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len) {
88 (void) instance;
89 (void) report;
90 (void) len;
91}
92
93// Invoked when a transfer wasn't successful
94TU_ATTR_WEAK void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, uint8_t const* report, uint16_t xferred_bytes) {
95 (void) instance;
96 (void) report_type;
97 (void) report;
98 (void) xferred_bytes;
99}
100
101//--------------------------------------------------------------------+
102// APPLICATION API
103//--------------------------------------------------------------------+
104bool tud_hid_n_ready(uint8_t instance) {
105 uint8_t const rhport = 0;
106 uint8_t const ep_in = _hidd_itf[instance].ep_in;
107 return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(rhport, ep_in);
108}
109
110bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const *report, uint16_t len) {
111 uint8_t const rhport = 0;
113
114 // claim endpoint
115 TU_VERIFY(usbd_edpt_claim(rhport, p_hid->ep_in));
116
117 // prepare data
118 if (report_id) {
119 p_hid->epin_buf[0] = report_id;
120 TU_VERIFY(0 == tu_memcpy_s(p_hid->epin_buf + 1, CFG_TUD_HID_EP_BUFSIZE - 1, report, len));
121 len++;
122 } else {
123 TU_VERIFY(0 == tu_memcpy_s(p_hid->epin_buf, CFG_TUD_HID_EP_BUFSIZE, report, len));
124 }
125
126 return usbd_edpt_xfer(rhport, p_hid->ep_in, p_hid->epin_buf, len);
127}
128
129uint8_t tud_hid_n_interface_protocol(uint8_t instance) {
131}
132
133uint8_t tud_hid_n_get_protocol(uint8_t instance) {
135}
136
137bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, const uint8_t keycode[6]) {
139 report.modifier = modifier;
140 report.reserved = 0;
141
142 if (keycode) {
143 memcpy(report.keycode, keycode, sizeof(report.keycode));
144 } else {
145 tu_memclr(report.keycode, 6);
146 }
147
148 return tud_hid_n_report(instance, report_id, &report, sizeof(report));
149}
150
151bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id,
152 uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) {
153 hid_mouse_report_t report = {
154 .buttons = buttons,
155 .x = x,
156 .y = y,
157 .wheel = vertical,
158 .pan = horizontal
159 };
160
161 return tud_hid_n_report(instance, report_id, &report, sizeof(report));
162}
163
164bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id,
165 uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal) {
166 hid_abs_mouse_report_t report = {
167 .buttons = buttons,
168 .x = x,
169 .y = y,
170 .wheel = vertical,
171 .pan = horizontal
172 };
173 return tud_hid_n_report(instance, report_id, &report, sizeof(report));
174}
175
176bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id,
177 int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) {
178 hid_gamepad_report_t report = {
179 .x = x,
180 .y = y,
181 .z = z,
182 .rz = rz,
183 .rx = rx,
184 .ry = ry,
185 .hat = hat,
186 .buttons = buttons,
187 };
188
189 return tud_hid_n_report(instance, report_id, &report, sizeof(report));
190}
191
192//--------------------------------------------------------------------+
193// USBD-CLASS API
194//--------------------------------------------------------------------+
195void hidd_init(void) {
196 hidd_reset(0);
197}
198
199bool hidd_deinit(void) {
200 return true;
201}
202
203void hidd_reset(uint8_t rhport) {
204 (void)rhport;
205 tu_memclr(_hidd_itf, sizeof(_hidd_itf));
206}
207
208uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16_t max_len) {
209 TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0);
210
211 // len = interface + hid + n*endpoints
212 uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) +
213 desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
214 TU_ASSERT(max_len >= drv_len, 0);
215
216 // Find available interface
217 hidd_interface_t *p_hid = NULL;
218 uint8_t hid_id;
219 for (hid_id = 0; hid_id < CFG_TUD_HID; hid_id++) {
220 if (_hidd_itf[hid_id].ep_in == 0) {
221 p_hid = &_hidd_itf[hid_id];
222 break;
223 }
224 }
225 TU_ASSERT(p_hid, 0);
226
227 uint8_t const *p_desc = (uint8_t const *)desc_itf;
228
229 //------------- HID descriptor -------------//
230 p_desc = tu_desc_next(p_desc);
231 TU_ASSERT(HID_DESC_TYPE_HID == tu_desc_type(p_desc), 0);
232 p_hid->hid_descriptor = (tusb_hid_descriptor_hid_t const *)p_desc;
233
234 //------------- Endpoint Descriptor -------------//
235 p_desc = tu_desc_next(p_desc);
236 TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, desc_itf->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_hid->ep_out, &p_hid->ep_in), 0);
237
238 if (desc_itf->bInterfaceSubClass == HID_SUBCLASS_BOOT) {
239 p_hid->itf_protocol = desc_itf->bInterfaceProtocol;
240 }
241
242 p_hid->protocol_mode = HID_PROTOCOL_REPORT; // Per Specs: default is report mode
243 p_hid->itf_num = desc_itf->bInterfaceNumber;
244
245 // Use offsetof to avoid pointer to the odd/misaligned address
246 p_hid->report_desc_len = tu_unaligned_read16((uint8_t const *)p_hid->hid_descriptor + offsetof(tusb_hid_descriptor_hid_t, wReportLength));
247
248 // Prepare for output endpoint
249 if (p_hid->ep_out) {
250 if (!usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))) {
251 TU_LOG_FAILED();
252 TU_BREAKPOINT();
253 }
254 }
255
256 return drv_len;
257}
258
259// Invoked when a control transfer occurred on an interface of this class
260// Driver response accordingly to the request and the transfer stage (setup/data/ack)
261// return false to stall control endpoint (e.g unsupported request)
262bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) {
263 TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
264
265 uint8_t const hid_itf = get_index_by_itfnum((uint8_t)request->wIndex);
266 TU_VERIFY(hid_itf < CFG_TUD_HID);
267
268 hidd_interface_t *p_hid = &_hidd_itf[hid_itf];
269
271 //------------- STD Request -------------//
272 if (stage == CONTROL_STAGE_SETUP) {
273 uint8_t const desc_type = tu_u16_high(request->wValue);
274 // uint8_t const desc_index = tu_u16_low (request->wValue);
275
277 TU_VERIFY(p_hid->hid_descriptor);
278 TU_VERIFY(tud_control_xfer(rhport, request, (void *)(uintptr_t)p_hid->hid_descriptor, p_hid->hid_descriptor->bLength));
279 } else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESC_TYPE_REPORT) {
280 uint8_t const *desc_report = tud_hid_descriptor_report_cb(hid_itf);
281 tud_control_xfer(rhport, request, (void *)(uintptr_t)desc_report, p_hid->report_desc_len);
282 } else {
283 return false; // stall unsupported request
284 }
285 }
286 } else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) {
287 //------------- Class Specific Request -------------//
288 switch (request->bRequest) {
290 if (stage == CONTROL_STAGE_SETUP) {
291 uint8_t const report_type = tu_u16_high(request->wValue);
292 uint8_t const report_id = tu_u16_low(request->wValue);
293
294 uint8_t* report_buf = p_hid->ctrl_buf;
295 uint16_t req_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE);
296 uint16_t xferlen = 0;
297
298 // If host request a specific Report ID, add ID to as 1 byte of response
299 if ((report_id != HID_REPORT_TYPE_INVALID) && (req_len > 1)) {
300 *report_buf++ = report_id;
301 req_len--;
302 xferlen++;
303 }
304
305 xferlen += tud_hid_get_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, req_len);
306 TU_ASSERT(xferlen > 0);
307
308 tud_control_xfer(rhport, request, p_hid->ctrl_buf, xferlen);
309 }
310 break;
311
313 if (stage == CONTROL_STAGE_SETUP) {
314 TU_VERIFY(request->wLength <= sizeof(p_hid->ctrl_buf));
316 } else if (stage == CONTROL_STAGE_ACK) {
317 uint8_t const report_type = tu_u16_high(request->wValue);
318 uint8_t const report_id = tu_u16_low(request->wValue);
319
320 uint8_t const* report_buf = p_hid->ctrl_buf;
321 uint16_t report_len = tu_min16(request->wLength, CFG_TUD_HID_EP_BUFSIZE);
322
323 // If host request a specific Report ID, extract report ID in buffer before invoking callback
324 if ((report_id != HID_REPORT_TYPE_INVALID) && (report_len > 1) && (report_id == report_buf[0])) {
325 report_buf++;
326 report_len--;
327 }
328
329 tud_hid_set_report_cb(hid_itf, report_id, (hid_report_type_t) report_type, report_buf, report_len);
330 }
331 break;
332
334 if (stage == CONTROL_STAGE_SETUP) {
336 TU_VERIFY(tud_hid_set_idle_cb(hid_itf, p_hid->idle_rate)); // stall if false
338 }
339 break;
340
342 if (stage == CONTROL_STAGE_SETUP) {
343 // TODO idle rate of report
344 tud_control_xfer(rhport, request, &p_hid->idle_rate, 1);
345 }
346 break;
347
349 if (stage == CONTROL_STAGE_SETUP) {
350 tud_control_xfer(rhport, request, &p_hid->protocol_mode, 1);
351 }
352 break;
353
355 if (stage == CONTROL_STAGE_SETUP) {
357 } else if (stage == CONTROL_STAGE_ACK) {
358 p_hid->protocol_mode = (uint8_t) request->wValue;
359 tud_hid_set_protocol_cb(hid_itf, p_hid->protocol_mode);
360 }
361 break;
362
363 default:
364 return false; // stall unsupported request
365 }
366 } else {
367 return false; // stall unsupported request
368 }
369
370 return true;
371}
372
373bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
374 uint8_t instance = 0;
376
377 // Identify which interface to use
378 for (instance = 0; instance < CFG_TUD_HID; instance++) {
379 p_hid = &_hidd_itf[instance];
380 if ((ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in)) {
381 break;
382 }
383 }
384 TU_ASSERT(instance < CFG_TUD_HID);
385
386 if (ep_addr == p_hid->ep_in) {
387 // Input report
388 if (XFER_RESULT_SUCCESS == result) {
389 tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint16_t) xferred_bytes);
390 } else {
391 tud_hid_report_failed_cb(instance, HID_REPORT_TYPE_INPUT, p_hid->epin_buf, (uint16_t) xferred_bytes);
392 }
393 } else {
394 // Output report
395 if (XFER_RESULT_SUCCESS == result) {
396 tud_hid_set_report_cb(instance, 0, HID_REPORT_TYPE_OUTPUT, p_hid->epout_buf, (uint16_t)xferred_bytes);
397 } else {
398 tud_hid_report_failed_cb(instance, HID_REPORT_TYPE_OUTPUT, p_hid->epout_buf, (uint16_t) xferred_bytes);
399 }
400
401 // prepare for new transfer
402 TU_ASSERT(usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf)));
403 }
404
405 return true;
406}
407
408#endif
void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize)
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen)
hid_report_type_t
HID Request Report Type.
Definition: hid.h:85
@ HID_REQ_CONTROL_GET_PROTOCOL
Get Protocol.
Definition: hid.h:97
@ HID_REQ_CONTROL_SET_REPORT
Set Report.
Definition: hid.h:98
@ HID_REQ_CONTROL_GET_REPORT
Get Report.
Definition: hid.h:95
@ HID_REQ_CONTROL_SET_PROTOCOL
Set Protocol.
Definition: hid.h:100
@ HID_REQ_CONTROL_SET_IDLE
Set Idle.
Definition: hid.h:99
@ HID_REQ_CONTROL_GET_IDLE
Get Idle.
Definition: hid.h:96
@ HID_SUBCLASS_BOOT
Boot Interface Subclass.
Definition: hid.h:64
@ HID_DESC_TYPE_REPORT
Report Descriptor.
Definition: hid.h:79
@ HID_DESC_TYPE_HID
HID Descriptor.
Definition: hid.h:78
@ HID_PROTOCOL_REPORT
Definition: hid.h:148
@ HID_REPORT_TYPE_INPUT
Input.
Definition: hid.h:87
@ HID_REPORT_TYPE_INVALID
Definition: hid.h:86
@ HID_REPORT_TYPE_OUTPUT
Output.
Definition: hid.h:88
void hidd_reset(uint8_t rhport)
Definition: hid_device.c:203
void hidd_init(void)
Definition: hid_device.c:195
uint16_t hidd_open(uint8_t rhport, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
Definition: hid_device.c:208
bool tud_hid_n_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal)
Definition: hid_device.c:151
TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate)
Definition: hid_device.c:81
uint8_t tud_hid_n_get_protocol(uint8_t instance)
Definition: hid_device.c:133
CFG_TUD_MEM_SECTION tu_static hidd_interface_t _hidd_itf[CFG_TUD_HID]
Definition: hid_device.c:61
TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report, uint16_t len)
Definition: hid_device.c:87
uint8_t tud_hid_n_interface_protocol(uint8_t instance)
Definition: hid_device.c:129
TU_ATTR_WEAK void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol)
Definition: hid_device.c:76
bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
Definition: hid_device.c:373
bool hidd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request)
Definition: hid_device.c:262
bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t buttons, int16_t x, int16_t y, int8_t vertical, int8_t horizontal)
Definition: hid_device.c:164
static TU_ATTR_ALWAYS_INLINE uint8_t get_index_by_itfnum(uint8_t itf_num)
Definition: hid_device.c:64
bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons)
Definition: hid_device.c:176
TU_ATTR_WEAK void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, uint8_t const *report, uint16_t xferred_bytes)
Definition: hid_device.c:94
bool hidd_deinit(void)
Definition: hid_device.c:199
bool tud_hid_n_keyboard_report(uint8_t instance, uint8_t report_id, uint8_t modifier, const uint8_t keycode[6])
Definition: hid_device.c:137
bool tud_hid_n_report(uint8_t instance, uint8_t report_id, void const *report, uint16_t len)
Definition: hid_device.c:110
bool tud_hid_n_ready(uint8_t instance)
Definition: hid_device.c:104
static void * memcpy(void *dst, const void *src, size_t n)
Definition: ringbuffer.c:8
AUDIO Channel Cluster Descriptor (4.1)
Definition: audio.h:647
uint32_t buttons
Buttons mask for currently pressed buttons.
Definition: hid.h:204
uint16_t wValue
Definition: audio.h:934
struct TU_ATTR_PACKED::@16::TU_ATTR_PACKED bmRequestType_bit
uint8_t keycode[6]
Definition: hid.h:339
uint16_t wLength
Definition: audio.h:840
int8_t x
Delta x movement of left analog-stick.
Definition: hid.h:197
uint8_t modifier
Definition: hid.h:337
uint16_t wIndex
Definition: audio.h:943
uint8_t bInterfaceClass
Class code (assigned by the USB-IF).
Definition: tusb_types.h:349
uint8_t bInterfaceSubClass
Subclass code (assigned by the USB-IF). These codes are qualified by the value of the bInterfaceCla...
Definition: tusb_types.h:350
uint8_t bRequest
Request type audio_cs_req_t.
Definition: audio.h:831
uint8_t reserved
Definition: hid.h:338
uint8_t bNumEndpoints
Number of endpoints used by this interface (excluding endpoint zero). If this value is zero,...
Definition: tusb_types.h:348
uint8_t bInterfaceProtocol
Protocol code (assigned by the USB). These codes are qualified by the value of the bInterfaceClass ...
Definition: tusb_types.h:351
uint8_t bInterfaceNumber
Number of this interface. Zero-based value identifying the index in the array of concurrent interface...
Definition: tusb_types.h:346
uint8_t itf_num
Definition: hid_device.c:43
uint8_t protocol_mode
Definition: hid_device.c:49
uint8_t ep_out
Definition: hid_device.c:45
uint8_t idle_rate
Definition: hid_device.c:50
uint8_t ctrl_buf[CFG_TUD_HID_EP_BUFSIZE]
Definition: hid_device.c:56
uint8_t itf_protocol
Definition: hid_device.c:46
tusb_hid_descriptor_hid_t const * hid_descriptor
Definition: hid_device.c:54
uint16_t report_desc_len
Definition: hid_device.c:48
CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_HID_EP_BUFSIZE]
Definition: hid_device.c:57
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_HID_EP_BUFSIZE]
Definition: hid_device.c:58
static TU_ATTR_ALWAYS_INLINE uint8_t tu_u16_low(uint16_t ui16)
Definition: tusb_common.h:146
static TU_ATTR_ALWAYS_INLINE uint16_t tu_min16(uint16_t x, uint16_t y)
Definition: tusb_common.h:155
static TU_ATTR_ALWAYS_INLINE uint8_t tu_u16_high(uint16_t ui16)
Definition: tusb_common.h:145
static TU_ATTR_ALWAYS_INLINE uint16_t tu_unaligned_read16(const void *mem)
Definition: tusb_common.h:219
static TU_ATTR_ALWAYS_INLINE int tu_memcpy_s(void *dest, size_t destsz, const void *src, size_t count)
Definition: tusb_common.h:114
@ TUSB_REQ_GET_DESCRIPTOR
Definition: tusb_types.h:128
@ TUSB_CLASS_HID
Definition: tusb_types.h:162
xfer_result_t
Definition: tusb_types.h:236
@ XFER_RESULT_SUCCESS
Definition: tusb_types.h:237
@ TUSB_REQ_RCPT_INTERFACE
Definition: tusb_types.h:152
@ TUSB_XFER_INTERRUPT
Definition: tusb_types.h:62
@ CONTROL_STAGE_ACK
Definition: tusb_types.h:270
@ CONTROL_STAGE_SETUP
Definition: tusb_types.h:268
static TU_ATTR_ALWAYS_INLINE uint8_t tu_desc_type(void const *desc)
Definition: tusb_types.h:537
@ TUSB_REQ_TYPE_STANDARD
Definition: tusb_types.h:144
@ TUSB_REQ_TYPE_CLASS
Definition: tusb_types.h:145
static TU_ATTR_ALWAYS_INLINE uint8_t const * tu_desc_next(void const *desc)
Definition: tusb_types.h:531
bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t *buffer, uint16_t total_bytes)
Definition: usbd.c:1309
bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr)
Definition: usbd.c:1286
bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr)
Definition: usbd.c:1376
bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const *p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t *ep_out, uint8_t *ep_in)
Definition: usbd.c:1238
bool tud_control_xfer(uint8_t rhport, tusb_control_request_t const *request, void *buffer, uint16_t len)
Definition: usbd_control.c:111
static TU_ATTR_ALWAYS_INLINE bool tud_ready(void)
Definition: usbd.h:97
bool tud_control_status(uint8_t rhport, tusb_control_request_t const *request)
Definition: usbd_control.c:81
CFG_TUH_MEM_ALIGN tusb_control_request_t request
Definition: usbh.c:259
volatile uint8_t stage
Definition: usbh.c:265