ChibiOS 21.11.5
hal_usb.c
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/**
18 * @file hal_usb.c
19 * @brief USB Driver code.
20 *
21 * @addtogroup USB
22 * @{
23 */
24
25#include <string.h>
26
27#include "hal.h"
28
29#if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__)
30
31/*===========================================================================*/
32/* Driver local definitions. */
33/*===========================================================================*/
34
35/*===========================================================================*/
36/* Driver exported variables. */
37/*===========================================================================*/
38
39/*===========================================================================*/
40/* Driver local variables and types. */
41/*===========================================================================*/
42
43static const uint8_t zero_status[] = {0x00, 0x00};
44static const uint8_t active_status[] = {0x00, 0x00};
45static const uint8_t halted_status[] = {0x01, 0x00};
46
47/*===========================================================================*/
48/* Driver local functions. */
49/*===========================================================================*/
50
51static uint16_t get_hword(uint8_t *p) {
52 uint16_t hw;
53
54 hw = (uint16_t)*p++;
55 hw |= (uint16_t)*p << 8U;
56 return hw;
57}
58
59/**
60 * @brief SET ADDRESS transaction callback.
61 *
62 * @param[in] usbp pointer to the @p USBDriver object
63 */
64static void set_address(USBDriver *usbp) {
65
66 usbp->address = usbp->setup[2];
69 usbp->state = USB_SELECTED;
70}
71
72/**
73 * @brief Standard requests handler.
74 * @details This is the standard requests default handler, most standard
75 * requests are handled here, the user can override the standard
76 * handling using the @p requests_hook_cb hook in the
77 * @p USBConfig structure.
78 *
79 * @param[in] usbp pointer to the @p USBDriver object
80 * @return The request handling exit code.
81 * @retval false Request not recognized by the handler or error.
82 * @retval true Request handled.
83 */
84static bool default_handler(USBDriver *usbp) {
85 const USBDescriptor *dp;
86
87 /* Decoding the request.*/
88 switch ((((uint32_t)usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK |
90 ((uint32_t)usbp->setup[1] << 8U))) {
91 case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_STATUS << 8):
92 /* Just returns the current status word.*/
93 usbSetupTransfer(usbp, (uint8_t *)&usbp->status, 2, NULL);
94 return true;
95 case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8):
96 /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature
97 number is handled as an error.*/
99 usbp->status &= ~2U;
100 usbSetupTransfer(usbp, NULL, 0, NULL);
101 return true;
102 }
103 return false;
104 case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_FEATURE << 8):
105 /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature
106 number is handled as an error.*/
107 if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) {
108 usbp->status |= 2U;
109 usbSetupTransfer(usbp, NULL, 0, NULL);
110 return true;
111 }
112 return false;
113 case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_ADDRESS << 8):
114 /* The SET_ADDRESS handling can be performed here or postponed after
115 the status packed depending on the USB_SET_ADDRESS_MODE low
116 driver setting.*/
117#if USB_SET_ADDRESS_MODE == USB_EARLY_SET_ADDRESS
118 if ((usbp->setup[0] == USB_RTYPE_RECIPIENT_DEVICE) &&
119 (usbp->setup[1] == USB_REQ_SET_ADDRESS)) {
120 set_address(usbp);
121 }
122 usbSetupTransfer(usbp, NULL, 0, NULL);
123#else
124 usbSetupTransfer(usbp, NULL, 0, set_address);
125#endif
126 return true;
127 case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_DESCRIPTOR << 8):
128 case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_DESCRIPTOR << 8):
129 /* Handling descriptor requests from the host.*/
130 dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3],
131 usbp->setup[2],
132 get_hword(&usbp->setup[4]));
133 if (dp == NULL) {
134 return false;
135 }
136 /*lint -save -e9005 [11.8] Removing const is fine.*/
137 usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
138 /*lint -restore*/
139 return true;
140 case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_GET_CONFIGURATION << 8):
141 /* Returning the last selected configuration.*/
142 usbSetupTransfer(usbp, &usbp->configuration, 1, NULL);
143 return true;
144 case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_CONFIGURATION << 8):
145#if defined(USB_SET_CONFIGURATION_OLD_BEHAVIOR)
146 /* Handling configuration selection from the host only if it is different
147 from the current configuration.*/
148 if (usbp->configuration != usbp->setup[2])
149#endif
150 {
151 /* If the USB device is already active then we have to perform the clear
152 procedure on the current configuration.*/
153 if (usbp->state == USB_ACTIVE) {
154 /* Current configuration cleared.*/
158 usbp->configuration = 0U;
159 usbp->state = USB_SELECTED;
161 }
162 if (usbp->setup[2] != 0U) {
163 /* New configuration.*/
164 usbp->configuration = usbp->setup[2];
165 usbp->state = USB_ACTIVE;
167 }
168 }
169 usbSetupTransfer(usbp, NULL, 0, NULL);
170 return true;
171 case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_STATUS << 8):
172 case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_SYNCH_FRAME << 8):
173 /* Just sending two zero bytes, the application can change the behavior
174 using a hook.*/
175 /*lint -save -e9005 [11.8] Removing const is fine.*/
176 usbSetupTransfer(usbp, (uint8_t *)zero_status, 2, NULL);
177 /*lint -restore*/
178 return true;
179 case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_GET_STATUS << 8):
180 /* Sending the EP status.*/
181 if ((usbp->setup[4] & 0x80U) != 0U) {
182 switch (usb_lld_get_status_in(usbp, usbp->setup[4] & 0x0FU)) {
184 /*lint -save -e9005 [11.8] Removing const is fine.*/
185 usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL);
186 /*lint -restore*/
187 return true;
188 case EP_STATUS_ACTIVE:
189 /*lint -save -e9005 [11.8] Removing const is fine.*/
190 usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL);
191 /*lint -restore*/
192 return true;
194 default:
195 return false;
196 }
197 }
198 else {
199 switch (usb_lld_get_status_out(usbp, usbp->setup[4] & 0x0FU)) {
201 /*lint -save -e9005 [11.8] Removing const is fine.*/
202 usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL);
203 /*lint -restore*/
204 return true;
205 case EP_STATUS_ACTIVE:
206 /*lint -save -e9005 [11.8] Removing const is fine.*/
207 usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL);
208 /*lint -restore*/
209 return true;
211 default:
212 return false;
213 }
214 }
215 case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8):
216 /* Only ENDPOINT_HALT is handled as feature.*/
217 if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) {
218 return false;
219 }
220 /* Clearing the EP status, not valid for EP0, it is ignored in that case.*/
221 if ((usbp->setup[4] & 0x0FU) != 0U) {
222 if ((usbp->setup[4] & 0x80U) != 0U) {
223 usb_lld_clear_in(usbp, usbp->setup[4] & 0x0FU);
224 }
225 else {
226 usb_lld_clear_out(usbp, usbp->setup[4] & 0x0FU);
227 }
228 }
229 usbSetupTransfer(usbp, NULL, 0, NULL);
230 return true;
231 case (uint32_t)USB_RTYPE_RECIPIENT_ENDPOINT | ((uint32_t)USB_REQ_SET_FEATURE << 8):
232 /* Only ENDPOINT_HALT is handled as feature.*/
233 if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) {
234 return false;
235 }
236 /* Stalling the EP, not valid for EP0, it is ignored in that case.*/
237 if ((usbp->setup[4] & 0x0FU) != 0U) {
238 if ((usbp->setup[4] & 0x80U) != 0U) {
239 usb_lld_stall_in(usbp, usbp->setup[4] & 0x0FU);
240 }
241 else {
242 usb_lld_stall_out(usbp, usbp->setup[4] & 0x0FU);
243 }
244 }
245 usbSetupTransfer(usbp, NULL, 0, NULL);
246 return true;
247 case (uint32_t)USB_RTYPE_RECIPIENT_DEVICE | ((uint32_t)USB_REQ_SET_DESCRIPTOR << 8):
248 case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_CLEAR_FEATURE << 8):
249 case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_SET_FEATURE << 8):
250 case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_INTERFACE << 8):
251 case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_SET_INTERFACE << 8):
252 /* All the above requests are not handled here, if you need them then
253 use the hook mechanism and provide handling.*/
254 default:
255 return false;
256 }
257}
258
259/**
260 * @brief Reset setup state machine.
261 *
262 * @param[in] usbp pointer to the @p USBDriver object
263 */
264static void setup_reset(USBDriver *usbp) {
265
266 usbp->receiving &= ~1U;
267 usbp->transmitting &= ~1U;
268 usbp->ep0n = 0;
270}
271
272/**
273 * @brief Set error in setup state machine.
274 *
275 * @param[in] usbp pointer to the @p USBDriver object
276 */
277static void setup_error(USBDriver *usbp) {
278
279 usb_lld_stall_in(usbp, 0);
280 usb_lld_stall_out(usbp, 0);
282 usbp->receiving &= ~1U;
283 usbp->transmitting &= ~1U;
284 usbp->ep0n = 0;
285 usbp->ep0state = USB_EP0_ERROR;
286}
287
288/*===========================================================================*/
289/* Driver exported functions. */
290/*===========================================================================*/
291
292/**
293 * @brief USB Driver initialization.
294 * @note This function is implicitly invoked by @p halInit(), there is
295 * no need to explicitly initialize the driver.
296 *
297 * @init
298 */
299void usbInit(void) {
300
301 usb_lld_init();
302}
303
304/**
305 * @brief Initializes the standard part of a @p USBDriver structure.
306 *
307 * @param[out] usbp pointer to the @p USBDriver object
308 *
309 * @init
310 */
312 unsigned i;
313
314 usbp->state = USB_STOP;
315 usbp->config = NULL;
316 for (i = 0; i < (unsigned)USB_MAX_ENDPOINTS; i++) {
317 usbp->in_params[i] = NULL;
318 usbp->out_params[i] = NULL;
319 }
320 usbp->transmitting = 0;
321 usbp->receiving = 0;
322}
323
324/**
325 * @brief Configures and activates the USB peripheral.
326 *
327 * @param[in] usbp pointer to the @p USBDriver object
328 * @param[in] config pointer to the @p USBConfig object
329 * @return The operation status.
330 *
331 * @api
332 */
333msg_t usbStart(USBDriver *usbp, const USBConfig *config) {
334 msg_t msg;
335 unsigned i;
336
337 osalDbgCheck((usbp != NULL) && (config != NULL));
338
339 osalSysLock();
340 osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY),
341 "invalid state");
342
343 usbp->config = config;
344 for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
345 usbp->epc[i] = NULL;
346 }
347
348#if defined(USB_LLD_ENHANCED_API)
349 msg = usb_lld_start(usbp);
350 if (msg == HAL_RET_SUCCESS) {
351 usbp->state = USB_READY;
352 }
353 else {
354 usbp->state = USB_STOP;
355 }
356#else
357 usb_lld_start(usbp);
358 usbp->state = USB_READY;
359 msg = HAL_RET_SUCCESS;
360#endif
361
363
364 return msg;
365}
366
367/**
368 * @brief Deactivates the USB peripheral.
369 *
370 * @param[in] usbp pointer to the @p USBDriver object
371 *
372 * @api
373 */
374void usbStop(USBDriver *usbp) {
375 unsigned i;
376
377 osalDbgCheck(usbp != NULL);
378
379 osalSysLock();
380
381 osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY) ||
382 (usbp->state == USB_SELECTED) || (usbp->state == USB_ACTIVE) ||
383 (usbp->state == USB_SUSPENDED),
384 "invalid state");
385
386 usb_lld_stop(usbp);
387 usbp->config = NULL;
388 usbp->state = USB_STOP;
389
390 /* Resetting all ongoing synchronous operations.*/
391 for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
392#if USB_USE_WAIT == TRUE
393 if (usbp->epc[i] != NULL) {
394 if (usbp->epc[i]->in_state != NULL) {
396 }
397 if (usbp->epc[i]->out_state != NULL) {
399 }
400 }
401#endif
402 usbp->epc[i] = NULL;
403 }
405
407}
408
409/**
410 * @brief Enables an endpoint.
411 * @details This function enables an endpoint, both IN and/or OUT directions
412 * depending on the configuration structure.
413 * @note This function must be invoked in response of a SET_CONFIGURATION
414 * or SET_INTERFACE message.
415 *
416 * @param[in] usbp pointer to the @p USBDriver object
417 * @param[in] ep endpoint number
418 * @param[in] epcp the endpoint configuration
419 *
420 * @iclass
421 */
423 const USBEndpointConfig *epcp) {
424
426 osalDbgCheck((usbp != NULL) && (epcp != NULL) &&
427 (ep <= (usbep_t)USB_MAX_ENDPOINTS));
429 "invalid state");
430 osalDbgAssert(usbp->epc[ep] == NULL, "already initialized");
431
432 /* Logically enabling the endpoint in the USBDriver structure.*/
433 usbp->epc[ep] = epcp;
434
435 /* Clearing the state structures, custom fields as well.*/
436 if (epcp->in_state != NULL) {
437 memset(epcp->in_state, 0, sizeof(USBInEndpointState));
438 }
439 if (epcp->out_state != NULL) {
440 memset(epcp->out_state, 0, sizeof(USBOutEndpointState));
441 }
442
443 /* Low level endpoint activation.*/
444 usb_lld_init_endpoint(usbp, ep);
445}
446
447/**
448 * @brief Disables all the active endpoints.
449 * @details This function disables all the active endpoints except the
450 * endpoint zero.
451 * @note This function must be invoked in response of a SET_CONFIGURATION
452 * message with configuration number zero.
453 *
454 * @param[in] usbp pointer to the @p USBDriver object
455 *
456 * @iclass
457 */
459 unsigned i;
460
462 osalDbgCheck(usbp != NULL);
463 osalDbgAssert(usbp->state == USB_ACTIVE, "invalid state");
464
465 usbp->transmitting &= 1U;
466 usbp->receiving &= 1U;
467
468 for (i = 1; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
469#if USB_USE_WAIT == TRUE
470 /* Signaling the event to threads waiting on endpoints.*/
471 if (usbp->epc[i] != NULL) {
472 if (usbp->epc[i]->in_state != NULL) {
474 }
475 if (usbp->epc[i]->out_state != NULL) {
477 }
478 }
479#endif
480 usbp->epc[i] = NULL;
481 }
482
483 /* Low level endpoints deactivation.*/
485}
486
487/**
488 * @brief Reads a setup packet from the dedicated packet buffer.
489 * @details This function must be invoked in the context of the @p setup_cb
490 * callback in order to read the received setup packet.
491 * @pre In order to use this function the endpoint must have been
492 * initialized as a control endpoint.
493 * @note This function can be invoked from ISR context.
494 *
495 * @param[in] usbp pointer to the @p USBDriver object
496 * @param[in] ep endpoint number
497 * @param[out] buf buffer where to copy the packet data
498 *
499 * @iclass
500 */
501void usbReadSetupI(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
502
504 osalDbgCheck((usbp != NULL) && (buf != NULL) &&
505 (ep <= (usbep_t)USB_MAX_ENDPOINTS));
506
507 usb_lld_read_setup(usbp, ep, buf);
508}
509
510/**
511 * @brief Starts a receive transaction on an OUT endpoint.
512 * @note This function is meant to be called from ISR context outside
513 * critical zones because there is a potentially slow operation
514 * inside.
515 * @note The transaction terminates when one of the following conditions
516 * has been met:
517 * - The specified amount of data has been received.
518 * - A short packet has been received.
519 * - A zero-length packet has been received.
520 * - The USB has been reset by host or the driver went into
521 * @p USB_SUSPENDED state.
522 * .
523 *
524 * @param[in] usbp pointer to the @p USBDriver object
525 * @param[in] ep endpoint number
526 * @param[out] buf buffer where to copy the received data
527 * @param[in] n transaction size. It is recommended a multiple of
528 * the packet size because the excess is discarded.
529 *
530 * @iclass
531 */
533 uint8_t *buf, size_t n) {
535
537 osalDbgCheck((usbp != NULL) && (ep <= (usbep_t)USB_MAX_ENDPOINTS));
538 osalDbgAssert(!usbGetReceiveStatusI(usbp, ep), "already receiving");
539
540 /* Marking the endpoint as active.*/
541 usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep);
542
543 /* Setting up the transfer.*/
544 /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/
545 osp = usbp->epc[ep]->out_state;
546 /*lint -restore*/
547 osp->rxbuf = buf;
548 osp->rxsize = n;
549 osp->rxcnt = 0;
550#if USB_USE_WAIT == TRUE
551 osp->thread = NULL;
552#endif
553
554 /* Starting transfer.*/
555 usb_lld_start_out(usbp, ep);
556}
557
558/**
559 * @brief Starts a transmit transaction on an IN endpoint.
560 * @note This function is meant to be called from ISR context outside
561 * critical zones because there is a potentially slow operation
562 * inside.
563 *
564 * @param[in] usbp pointer to the @p USBDriver object
565 * @param[in] ep endpoint number
566 * @param[in] buf buffer where to fetch the data to be transmitted
567 * @param[in] n transaction size
568 *
569 * @iclass
570 */
572 const uint8_t *buf, size_t n) {
574
576 osalDbgCheck((usbp != NULL) && (ep <= (usbep_t)USB_MAX_ENDPOINTS));
577 osalDbgAssert(!usbGetTransmitStatusI(usbp, ep), "already transmitting");
578
579 /* Marking the endpoint as active.*/
580 usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep);
581
582 /* Setting up the transfer.*/
583 /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/
584 isp = usbp->epc[ep]->in_state;
585 /*lint -restore*/
586 isp->txbuf = buf;
587 isp->txsize = n;
588 isp->txcnt = 0;
589#if USB_USE_WAIT == TRUE
590 isp->thread = NULL;
591#endif
592
593 /* Starting transfer.*/
594 usb_lld_start_in(usbp, ep);
595}
596
597#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
598/**
599 * @brief Performs a receive transaction on an OUT endpoint.
600 * @note The transaction terminates when one of the following conditions
601 * has been met:
602 * - The specified amount of data has been received.
603 * - A short packet has been received.
604 * - A zero-lenght packet has been received.
605 * - The USB has been reset by host or the driver went into
606 * @p USB_SUSPENDED state.
607 *
608 * @param[in] usbp pointer to the @p USBDriver object
609 * @param[in] ep endpoint number
610 * @param[out] buf buffer where to copy the received data
611 * @param[in] n transaction size. It is recommended a multiple of
612 * the packet size because the excess is discarded.
613 *
614 * @return The received effective data size, it can be less than
615 * the amount specified.
616 * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation
617 * has been aborted by an USB reset or a transition to
618 * the @p USB_SUSPENDED state.
619 *
620 * @api
621 */
622msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
623 msg_t msg;
624
625 osalSysLock();
626
627 if (usbGetDriverStateI(usbp) != USB_ACTIVE) {
629 return MSG_RESET;
630 }
631
632 usbStartReceiveI(usbp, ep, buf, n);
633 msg = osalThreadSuspendS(&usbp->epc[ep]->out_state->thread);
635
636 return msg;
637}
638
639/**
640 * @brief Performs a transmit transaction on an IN endpoint.
641 *
642 * @param[in] usbp pointer to the @p USBDriver object
643 * @param[in] ep endpoint number
644 * @param[in] buf buffer where to fetch the data to be transmitted
645 * @param[in] n transaction size
646 *
647 * @return The operation status.
648 * @retval MSG_OK operation performed successfully.
649 * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation
650 * has been aborted by an USB reset or a transition to
651 * the @p USB_SUSPENDED state.
652 *
653 * @api
654 */
655msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n) {
656 msg_t msg;
657
658 osalSysLock();
659
660 if (usbGetDriverStateI(usbp) != USB_ACTIVE) {
662 return MSG_RESET;
663 }
664
665 usbStartTransmitI(usbp, ep, buf, n);
666 msg = osalThreadSuspendS(&usbp->epc[ep]->in_state->thread);
668
669 return msg;
670}
671#endif /* USB_USE_WAIT == TRUE */
672
673/**
674 * @brief Stalls an OUT endpoint.
675 *
676 * @param[in] usbp pointer to the @p USBDriver object
677 * @param[in] ep endpoint number
678 *
679 * @return The operation status.
680 * @retval false Endpoint stalled.
681 * @retval true Endpoint busy, not stalled.
682 *
683 * @iclass
684 */
686
688 osalDbgCheck(usbp != NULL);
689
690 if (usbGetReceiveStatusI(usbp, ep)) {
691 return true;
692 }
693
694 usb_lld_stall_out(usbp, ep);
695 return false;
696}
697
698/**
699 * @brief Stalls an IN endpoint.
700 *
701 * @param[in] usbp pointer to the @p USBDriver object
702 * @param[in] ep endpoint number
703 *
704 * @return The operation status.
705 * @retval false Endpoint stalled.
706 * @retval true Endpoint busy, not stalled.
707 *
708 * @iclass
709 */
711
713 osalDbgCheck(usbp != NULL);
714
715 if (usbGetTransmitStatusI(usbp, ep)) {
716 return true;
717 }
718
719 usb_lld_stall_in(usbp, ep);
720 return false;
721}
722
723/**
724 * @brief Host wake-up procedure.
725 * @note It is silently ignored if the USB device is not in the
726 * @p USB_SUSPENDED state.
727 *
728 * @param[in] usbp pointer to the @p USBDriver object
729 *
730 * @api
731 */
733
734 if (usbp->state == USB_SUSPENDED) {
735 /* Starting host wakeup procedure.*/
737 }
738}
739
740/**
741 * @brief USB reset routine.
742 * @details This function must be invoked when an USB bus reset condition is
743 * detected.
744 *
745 * @param[in] usbp pointer to the @p USBDriver object
746 *
747 * @notapi
748 */
750 unsigned i;
751
752 /* State transition.*/
753 usbp->state = USB_READY;
754
755 /* Resetting internal state.*/
756 usbp->status = 0;
757 usbp->address = 0;
758 usbp->configuration = 0;
759 usbp->ep0n = 0;
760 usbp->transmitting = 0;
761 usbp->receiving = 0;
762
763 /* Invalidates all endpoints into the USBDriver structure.*/
764 for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
765#if USB_USE_WAIT == TRUE
766 /* Signaling the event to threads waiting on endpoints.*/
767 if (usbp->epc[i] != NULL) {
769 if (usbp->epc[i]->in_state != NULL) {
771 }
772 if (usbp->epc[i]->out_state != NULL) {
774 }
776 }
777#endif
778 usbp->epc[i] = NULL;
779 }
780
781 /* EP0 state machine initialization.*/
783
784 /* Low level reset.*/
785 usb_lld_reset(usbp);
786
787 /* Notification of reset event.*/
789}
790
791/**
792 * @brief USB suspend routine.
793 * @details This function must be invoked when an USB bus suspend condition is
794 * detected.
795 *
796 * @param[in] usbp pointer to the @p USBDriver object
797 *
798 * @notapi
799 */
801
802 /* It could happen that multiple suspend events are triggered.*/
803 if (usbp->state != USB_SUSPENDED) {
804
805 /* State transition, saving the current state.*/
806 usbp->saved_state = usbp->state;
807 usbp->state = USB_SUSPENDED;
808
809 /* Notification of suspend event.*/
811
812 /* Terminating all pending transactions.*/
813 usbp->transmitting = 0;
814 usbp->receiving = 0;
815
816 /* Signaling the event to threads waiting on endpoints.*/
817 #if USB_USE_WAIT == TRUE
818 {
819 unsigned i;
820
821 for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
822 if (usbp->epc[i] != NULL) {
824 if (usbp->epc[i]->in_state != NULL) {
826 }
827 if (usbp->epc[i]->out_state != NULL) {
829 }
831 }
832 }
833 }
834 #endif
835 }
836}
837
838/**
839 * @brief USB wake-up routine.
840 * @details This function must be invoked when an USB bus wake-up condition is
841 * detected.
842 *
843 * @param[in] usbp pointer to the @p USBDriver object
844 *
845 * @notapi
846 */
848
849 /* It could happen that multiple wakeup events are triggered.*/
850 if (usbp->state == USB_SUSPENDED) {
851
852 /* State transition, returning to the previous state.*/
853 usbp->state = usbp->saved_state;
854
855 /* Notification of suspend event.*/
857 }
858}
859
860/**
861 * @brief Default EP0 SETUP callback.
862 * @details This function is used by the low level driver as default handler
863 * for EP0 SETUP events.
864 *
865 * @param[in] usbp pointer to the @p USBDriver object
866 * @param[in] ep endpoint number, always zero
867 *
868 * @notapi
869 */
871
872 osalDbgAssert(ep == 0, "EP not zero");
873 size_t max;
874
875 /* Is the EP0 state machine in the correct state for handling setup
876 packets?*/
877 if (usbp->ep0state != USB_EP0_STP_WAITING) {
878 /* If a new SETUP packet arrives from the host while the device is still
879 in a previous control transfer (for example, an OUT data transfer), the
880 ongoing transfer is aborted. The EP0 state machine and transmitting and
881 receiving bits, must be reset. The count is also reset.*/
882 /* EP0 is driven by the control-transfer state machine; no waiters
883 are expected on EP0 transfers.*/
884 setup_reset(usbp);
885 }
886
887 /* Reading the setup data into the driver buffer.*/
888 usbReadSetup(usbp, 0, usbp->setup);
889
890 /* First verify if the application has an handler installed for this
891 request.*/
892 /*lint -save -e9007 [13.5] No side effects, it is intentional.*/
893 if ((usbp->config->requests_hook_cb == NULL) ||
894 !(usbp->config->requests_hook_cb(usbp))) {
895 /*lint -restore*/
896 /* Invoking the default handler, if this fails then stalls the
897 endpoint zero as error.*/
898 /*lint -save -e9007 [13.5] No side effects, it is intentional.*/
899 if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) != USB_RTYPE_TYPE_STD) ||
900 !default_handler(usbp)) {
901 /*lint -restore*/
902 /* Error response, the state machine goes into an error state, the low
903 level layer restores setup state based on low level events.*/
904 setup_error(usbp);
905 return;
906 }
907 }
908#if (USB_SET_ADDRESS_ACK_HANDLING == USB_SET_ADDRESS_ACK_HW)
909 if (usbp->setup[1] == USB_REQ_SET_ADDRESS) {
910 /* Zero-length packet sent by hardware */
911 return;
912 }
913#endif
914 /* Transfer preparation. The request handler must have populated
915 correctly the fields ep0next, ep0n and ep0endcb using the macro
916 usbSetupTransfer().*/
917 max = (size_t)get_hword(&usbp->setup[6]);
918 /* The transfer size cannot exceed the specified amount.*/
919 if (usbp->ep0n > max) {
920 usbp->ep0n = max;
921 }
922 if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_DEV2HOST) {
923 /* IN phase.*/
924 if (usbp->ep0n != 0U) {
925 /* Starts the transmit phase.*/
926 usbp->ep0state = USB_EP0_IN_TX;
928 usbStartTransmitI(usbp, 0, usbp->ep0next, usbp->ep0n);
930 }
931 else {
932 /* No transmission phase, directly receiving the zero sized status
933 packet.*/
935#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
937 usbStartReceiveI(usbp, 0, NULL, 0);
939#else
940 usb_lld_end_setup(usbp, 0);
941#endif
942 }
943 }
944 else {
945 /* OUT phase.*/
946 if (usbp->ep0n != 0U) {
947 /* Starts the receive phase.*/
948 usbp->ep0state = USB_EP0_OUT_RX;
950 usbStartReceiveI(usbp, 0, (uint8_t *)usbp->ep0next, usbp->ep0n);
952 }
953 else {
954 /* No receive phase, directly sending the zero sized status
955 packet.*/
957#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
959 usbStartTransmitI(usbp, 0, NULL, 0);
961#else
962 usb_lld_end_setup(usbp, 0);
963#endif
964 }
965 }
966}
967
968/**
969 * @brief Default EP0 IN callback.
970 * @details This function is used by the low level driver as default handler
971 * for EP0 IN events.
972 *
973 * @param[in] usbp pointer to the @p USBDriver object
974 * @param[in] ep endpoint number, always zero
975 *
976 * @notapi
977 */
978void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
979
980 osalDbgAssert(ep == 0, "EP not zero");
981
982 size_t max;
983 switch (usbp->ep0state) {
984 case USB_EP0_IN_TX:
985 max = (size_t)get_hword(&usbp->setup[6]);
986 /* If the transmitted size is less than the requested size and it is a
987 multiple of the maximum packet size then a zero size packet must be
988 transmitted.*/
989 if ((usbp->ep0n < max) &&
990 ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0U)) {
992 usbStartTransmitI(usbp, 0, NULL, 0);
995 return;
996 }
997 /* Falls through.*/
999 /* Transmit phase over, receiving the zero sized status packet.*/
1001#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
1003 usbStartReceiveI(usbp, 0, NULL, 0);
1005#else
1006 usb_lld_end_setup(usbp, 0);
1007#endif
1008 return;
1010 /* Status packet sent, invoking the callback if defined.*/
1011 if (usbp->ep0endcb != NULL) {
1012 usbp->ep0endcb(usbp);
1013 }
1014
1015 /* Put setup back in ready state.*/
1016 setup_reset(usbp);
1017 return;
1018
1020 /* Tolerate out of order setup.*/
1021 return;
1023 case USB_EP0_OUT_RX:
1024 /* All the above are invalid states in the IN phase.*/
1025 osalDbgAssert(false, "EP0 state machine error");
1026 /* Falls through.*/
1027 case USB_EP0_ERROR:
1028 /* Error response, the state machine goes into an error state, the low
1029 level layer restores setup state based on low level events.*/
1030 setup_error(usbp);
1031 return;
1032 default:
1033 osalDbgAssert(false, "EP0 state machine invalid state");
1034 }
1035}
1036
1037/**
1038 * @brief Default EP0 OUT callback.
1039 * @details This function is used by the low level driver as default handler
1040 * for EP0 OUT events.
1041 *
1042 * @param[in] usbp pointer to the @p USBDriver object
1043 * @param[in] ep endpoint number, always zero
1044 *
1045 * @notapi
1046 */
1048
1049 osalDbgAssert(ep == 0, "EP not zero");
1050
1051 switch (usbp->ep0state) {
1052 case USB_EP0_OUT_RX:
1053 /* Receive phase over, sending the zero sized status packet.*/
1055#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
1057 usbStartTransmitI(usbp, 0, NULL, 0);
1059#else
1060 usb_lld_end_setup(usbp, 0);
1061#endif
1062 return;
1064 /* Status packet received, it must be zero sized, invoking the callback
1065 if defined.*/
1066#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
1067 if (usbGetReceiveTransactionSizeX(usbp, 0) != 0U) {
1068 break;
1069 }
1070#endif
1071 if (usbp->ep0endcb != NULL) {
1072 usbp->ep0endcb(usbp);
1073 }
1074
1075 /* Put setup back in ready state.*/
1076 setup_reset(usbp);
1077 return;
1078
1079 case USB_EP0_IN_TX:
1080 /* Tolerate out of order setup.*/
1081 return;
1085 /* All the above are invalid states in the IN phase.*/
1086 osalDbgAssert(false, "EP0 state machine error");
1087 /* Falls through.*/
1088 case USB_EP0_ERROR:
1089 /* Error response, the state machine goes into an error state, the low
1090 level layer restores setup state based on low level events.*/
1091 setup_error(usbp);
1092 return;
1093 default:
1094 osalDbgAssert(false, "EP0 state machine invalid state");
1095 }
1096}
1097
1098#endif /* HAL_USE_USB == TRUE */
1099
1100/** @} */
#define HAL_RET_SUCCESS
Definition hal.h:93
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition osal.h:601
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition osal.h:611
static void osalSysLockFromISR(void)
Enters a critical zone from ISR context.
Definition osal.h:621
msg_t osalThreadSuspendS(thread_reference_t *trp)
Sends the current thread sleeping and sets a reference variable.
Definition osal.c:183
void osalOsRescheduleS(void)
Checks if a reschedule is required and performs it.
Definition osal.c:119
void osalThreadResumeI(thread_reference_t *trp, msg_t msg)
Wakes up a thread waiting on a thread reference object.
Definition osal.c:227
static void osalSysUnlockFromISR(void)
Leaves a critical zone from ISR context.
Definition osal.h:631
#define osalDbgAssert(c, remark)
Condition assertion.
Definition osal.h:264
#define osalDbgCheck(c)
Function parameters check.
Definition osal.h:284
#define osalDbgCheckClassI()
I-Class state check.
Definition osal.h:298
#define USB_RTYPE_RECIPIENT_MASK
Definition hal_usb.h:45
static void set_address(USBDriver *usbp)
SET ADDRESS transaction callback.
Definition hal_usb.c:64
#define usbGetDriverStateI(usbp)
Returns the driver state.
Definition hal_usb.h:391
static bool default_handler(USBDriver *usbp)
Standard requests handler.
Definition hal_usb.c:84
void usb_lld_stop(USBDriver *usbp)
Deactivates the USB peripheral.
void usb_lld_set_address(USBDriver *usbp)
Sets the USB address.
#define USB_FEATURE_ENDPOINT_HALT
Definition hal_usb.h:73
#define USB_REQ_GET_INTERFACE
Definition hal_usb.h:59
uint8_t usbep_t
Type of an endpoint identifier.
Definition hal_usb.h:264
void usb_lld_clear_in(USBDriver *usbp, usbep_t ep)
Brings an IN endpoint in the active state.
void _usb_suspend(USBDriver *usbp)
USB suspend routine.
Definition hal_usb.c:800
static const uint8_t zero_status[]
Definition hal_usb.c:43
void usbDisableEndpointsI(USBDriver *usbp)
Disables all the active endpoints.
Definition hal_usb.c:458
void usb_lld_init(void)
Low level USB driver initialization.
Definition hal_usb_lld.c:99
#define USB_REQ_SET_INTERFACE
Definition hal_usb.h:60
msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n)
Performs a transmit transaction on an IN endpoint.
Definition hal_usb.c:655
void usbStartReceiveI(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n)
Starts a receive transaction on an OUT endpoint.
Definition hal_usb.c:532
#define USB_REQ_SET_FEATURE
Definition hal_usb.h:53
void _usb_wakeup(USBDriver *usbp)
USB wake-up routine.
Definition hal_usb.c:847
#define usbGetReceiveTransactionSizeX(usbp, ep)
Returns the exact size of a receive transaction.
Definition hal_usb.h:461
#define USB_REQ_CLEAR_FEATURE
Definition hal_usb.h:52
static void setup_error(USBDriver *usbp)
Set error in setup state machine.
Definition hal_usb.c:277
void usbInit(void)
USB Driver initialization.
Definition hal_usb.c:299
#define USB_RTYPE_TYPE_STD
Definition hal_usb.h:41
bool usbStallTransmitI(USBDriver *usbp, usbep_t ep)
Stalls an IN endpoint.
Definition hal_usb.c:710
msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n)
Performs a receive transaction on an OUT endpoint.
Definition hal_usb.c:622
void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep)
Enables an endpoint.
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep)
Returns the status of an OUT endpoint.
static void setup_reset(USBDriver *usbp)
Reset setup state machine.
Definition hal_usb.c:264
void _usb_ep0setup(USBDriver *usbp, usbep_t ep)
Default EP0 SETUP callback.
Definition hal_usb.c:870
void usbStartTransmitI(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n)
Starts a transmit transaction on an IN endpoint.
Definition hal_usb.c:571
msg_t usbStart(USBDriver *usbp, const USBConfig *config)
Configures and activates the USB peripheral.
Definition hal_usb.c:333
#define USB_RTYPE_DIR_DEV2HOST
Definition hal_usb.h:39
#define USB_REQ_SET_CONFIGURATION
Definition hal_usb.h:58
static uint16_t get_hword(uint8_t *p)
Definition hal_usb.c:51
#define USB_RTYPE_RECIPIENT_ENDPOINT
Definition hal_usb.h:48
void usbInitEndpointI(USBDriver *usbp, usbep_t ep, const USBEndpointConfig *epcp)
Enables an endpoint.
Definition hal_usb.c:422
#define USB_REQ_SYNCH_FRAME
Definition hal_usb.h:61
#define usbGetReceiveStatusI(usbp, ep)
Returns the status of an OUT endpoint.
Definition hal_usb.h:446
#define usbSetupTransfer(usbp, buf, n, endcb)
Request transfer setup.
Definition hal_usb.h:479
#define USB_MAX_ENDPOINTS
Maximum endpoint address.
Definition hal_usb_lld.h:37
void usb_lld_reset(USBDriver *usbp)
USB low level reset routine.
#define usbGetTransmitStatusI(usbp, ep)
Returns the status of an IN endpoint.
Definition hal_usb.h:432
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep)
Returns the status of an IN endpoint.
void usb_lld_disable_endpoints(USBDriver *usbp)
Disables all the active endpoints except the endpoint zero.
#define USB_REQ_GET_STATUS
Definition hal_usb.h:51
static const uint8_t active_status[]
Definition hal_usb.c:44
void usb_lld_start_out(USBDriver *usbp, usbep_t ep)
Starts a receive operation on an OUT endpoint.
#define usbReadSetup(usbp, ep, buf)
Reads a setup packet from the dedicated packet buffer.
Definition hal_usb.h:499
#define usb_lld_wakeup_host(usbp)
Start of host wake-up procedure.
void usb_lld_start(USBDriver *usbp)
Configures and activates the USB peripheral.
#define USB_REQ_SET_ADDRESS
Definition hal_usb.h:54
void usb_lld_start_in(USBDriver *usbp, usbep_t ep)
Starts a transmit operation on an IN endpoint.
void usbStop(USBDriver *usbp)
Deactivates the USB peripheral.
Definition hal_usb.c:374
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP
Definition hal_usb.h:74
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf)
Reads a setup packet from the dedicated packet buffer.
static const uint8_t halted_status[]
Definition hal_usb.c:45
void _usb_ep0in(USBDriver *usbp, usbep_t ep)
Default EP0 IN callback.
Definition hal_usb.c:978
#define _usb_isr_invoke_event_cb(usbp, evt)
Common ISR code, usb event callback.
Definition hal_usb.h:535
void _usb_reset(USBDriver *usbp)
USB reset routine.
Definition hal_usb.c:749
#define USB_RTYPE_DIR_MASK
Definition hal_usb.h:37
void usb_lld_clear_out(USBDriver *usbp, usbep_t ep)
Brings an OUT endpoint in the active state.
void usbWakeupHost(USBDriver *usbp)
Host wake-up procedure.
Definition hal_usb.c:732
#define USB_RTYPE_RECIPIENT_INTERFACE
Definition hal_usb.h:47
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep)
Brings an OUT endpoint in the stalled state.
void usb_lld_stall_in(USBDriver *usbp, usbep_t ep)
Brings an IN endpoint in the stalled state.
#define USB_REQ_GET_DESCRIPTOR
Definition hal_usb.h:55
void usbObjectInit(USBDriver *usbp)
Initializes the standard part of a USBDriver structure.
Definition hal_usb.c:311
#define USB_REQ_GET_CONFIGURATION
Definition hal_usb.h:57
void usbReadSetupI(USBDriver *usbp, usbep_t ep, uint8_t *buf)
Reads a setup packet from the dedicated packet buffer.
Definition hal_usb.c:501
#define USB_REQ_SET_DESCRIPTOR
Definition hal_usb.h:56
bool usbStallReceiveI(USBDriver *usbp, usbep_t ep)
Stalls an OUT endpoint.
Definition hal_usb.c:685
#define USB_RTYPE_TYPE_MASK
Definition hal_usb.h:40
void _usb_ep0out(USBDriver *usbp, usbep_t ep)
Default EP0 OUT callback.
Definition hal_usb.c:1047
#define USB_RTYPE_RECIPIENT_DEVICE
Definition hal_usb.h:46
@ EP_STATUS_ACTIVE
Definition hal_usb.h:284
@ EP_STATUS_DISABLED
Definition hal_usb.h:282
@ EP_STATUS_STALLED
Definition hal_usb.h:283
@ USB_EP0_IN_WAITING_TX0
Definition hal_usb.h:293
@ USB_EP0_IN_SENDING_STS
Definition hal_usb.h:294
@ USB_EP0_OUT_WAITING_STS
Definition hal_usb.h:295
@ USB_EP0_ERROR
Definition hal_usb.h:297
@ USB_EP0_OUT_RX
Definition hal_usb.h:296
@ USB_EP0_STP_WAITING
Definition hal_usb.h:291
@ USB_EP0_IN_TX
Definition hal_usb.h:292
@ USB_EVENT_ADDRESS
Definition hal_usb.h:305
@ USB_EVENT_STALLED
Definition hal_usb.h:310
@ USB_EVENT_CONFIGURED
Definition hal_usb.h:306
@ USB_EVENT_SUSPEND
Definition hal_usb.h:308
@ USB_EVENT_RESET
Definition hal_usb.h:304
@ USB_EVENT_UNCONFIGURED
Definition hal_usb.h:307
@ USB_EVENT_WAKEUP
Definition hal_usb.h:309
@ USB_SUSPENDED
Definition hal_usb.h:275
@ USB_SELECTED
Definition hal_usb.h:273
@ USB_STOP
Definition hal_usb.h:271
@ USB_ACTIVE
Definition hal_usb.h:274
@ USB_READY
Definition hal_usb.h:272
int32_t msg_t
Definition chearly.h:87
#define MSG_RESET
Wakeup caused by a reset condition.
Definition chschd.h:41
HAL subsystem header.
Type of an USB driver configuration structure.
usbgetdescriptor_t get_descriptor_cb
Device GET_DESCRIPTOR request callback.
usbreqhandler_t requests_hook_cb
Requests hook callback.
Type of an USB descriptor.
Definition hal_usb.h:316
const uint8_t * ud_string
Pointer to the descriptor.
Definition hal_usb.h:324
size_t ud_size
Descriptor size in unicode characters.
Definition hal_usb.h:320
Structure representing an USB driver.
uint8_t setup[8]
Setup packet buffer.
size_t ep0n
Number of bytes yet to be transferred through endpoint 0.
uint16_t status
Current USB device status.
void * out_params[USB_MAX_ENDPOINTS]
Fields available to user, it can be used to associate an application-defined handler to an OUT endpoi...
void * in_params[USB_MAX_ENDPOINTS]
Fields available to user, it can be used to associate an application-defined handler to an IN endpoin...
uint8_t configuration
Current USB device configuration.
usbstate_t saved_state
State of the driver when a suspend happened.
usbep0state_t ep0state
Endpoint 0 state.
const USBEndpointConfig * epc[USB_MAX_ENDPOINTS+1]
Active endpoints configurations.
usbstate_t state
Driver state.
uint16_t receiving
Bit map of the receiving OUT endpoints.
usbcallback_t ep0endcb
Endpoint 0 end transaction callback.
const USBConfig * config
Current configuration data.
uint8_t address
Assigned USB address.
uint16_t transmitting
Bit map of the transmitting IN endpoints.
uint8_t * ep0next
Next position in the buffer to be transferred through endpoint 0.
Type of an USB endpoint configuration structure.
USBOutEndpointState * out_state
USBEndpointState associated to the OUT endpoint.
uint16_t in_maxsize
IN endpoint maximum packet size.
USBInEndpointState * in_state
USBEndpointState associated to the IN endpoint.
Type of an IN endpoint state structure.
Definition hal_usb_lld.h:83
const uint8_t * txbuf
Pointer to the transmission linear buffer.
Definition hal_usb_lld.h:95
thread_reference_t thread
Waiting thread.
size_t txsize
Requested transmit transfer size.
Definition hal_usb_lld.h:87
size_t txcnt
Transmitted bytes so far.
Definition hal_usb_lld.h:91
Type of an OUT endpoint state structure.
size_t rxsize
Requested receive transfer size.
uint8_t * rxbuf
Pointer to the receive linear buffer.
thread_reference_t thread
Waiting thread.
size_t rxcnt
Received bytes so far.