ChibiOS  21.6.0
hal_usb.c
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 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 
43 static const uint8_t zero_status[] = {0x00, 0x00};
44 static const uint8_t active_status[] = {0x00, 0x00};
45 static const uint8_t halted_status[] = {0x01, 0x00};
46 
47 /*===========================================================================*/
48 /* Driver local functions. */
49 /*===========================================================================*/
50 
51 static 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  */
64 static void set_address(USBDriver *usbp) {
65 
66  usbp->address = usbp->setup[2];
67  usb_lld_set_address(usbp);
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  */
84 static 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 |
89  USB_RTYPE_TYPE_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.*/
98  if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) {
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.*/
156  usbDisableEndpointsI(usbp);
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)) {
183  case EP_STATUS_STALLED:
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;
193  case EP_STATUS_DISABLED:
194  default:
195  return false;
196  }
197  }
198  else {
199  switch (usb_lld_get_status_out(usbp, usbp->setup[4] & 0x0FU)) {
200  case EP_STATUS_STALLED:
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;
210  case EP_STATUS_DISABLED:
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 /* Driver exported functions. */
261 /*===========================================================================*/
262 
263 /**
264  * @brief USB Driver initialization.
265  * @note This function is implicitly invoked by @p halInit(), there is
266  * no need to explicitly initialize the driver.
267  *
268  * @init
269  */
270 void usbInit(void) {
271 
272  usb_lld_init();
273 }
274 
275 /**
276  * @brief Initializes the standard part of a @p USBDriver structure.
277  *
278  * @param[out] usbp pointer to the @p USBDriver object
279  *
280  * @init
281  */
283  unsigned i;
284 
285  usbp->state = USB_STOP;
286  usbp->config = NULL;
287  for (i = 0; i < (unsigned)USB_MAX_ENDPOINTS; i++) {
288  usbp->in_params[i] = NULL;
289  usbp->out_params[i] = NULL;
290  }
291  usbp->transmitting = 0;
292  usbp->receiving = 0;
293 }
294 
295 /**
296  * @brief Configures and activates the USB peripheral.
297  *
298  * @param[in] usbp pointer to the @p USBDriver object
299  * @param[in] config pointer to the @p USBConfig object
300  *
301  * @api
302  */
303 void usbStart(USBDriver *usbp, const USBConfig *config) {
304  unsigned i;
305 
306  osalDbgCheck((usbp != NULL) && (config != NULL));
307 
308  osalSysLock();
309  osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY),
310  "invalid state");
311  usbp->config = config;
312  for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
313  usbp->epc[i] = NULL;
314  }
315  usb_lld_start(usbp);
316  usbp->state = USB_READY;
317  osalSysUnlock();
318 }
319 
320 /**
321  * @brief Deactivates the USB peripheral.
322  *
323  * @param[in] usbp pointer to the @p USBDriver object
324  *
325  * @api
326  */
327 void usbStop(USBDriver *usbp) {
328  unsigned i;
329 
330  osalDbgCheck(usbp != NULL);
331 
332  osalSysLock();
333 
334  osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY) ||
335  (usbp->state == USB_SELECTED) || (usbp->state == USB_ACTIVE) ||
336  (usbp->state == USB_SUSPENDED),
337  "invalid state");
338 
339  usb_lld_stop(usbp);
340  usbp->config = NULL;
341  usbp->state = USB_STOP;
342 
343  /* Resetting all ongoing synchronous operations.*/
344  for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
345 #if USB_USE_WAIT == TRUE
346  if (usbp->epc[i] != NULL) {
347  if (usbp->epc[i]->in_state != NULL) {
349  }
350  if (usbp->epc[i]->out_state != NULL) {
352  }
353  }
354 #endif
355  usbp->epc[i] = NULL;
356  }
358 
359  osalSysUnlock();
360 }
361 
362 /**
363  * @brief Enables an endpoint.
364  * @details This function enables an endpoint, both IN and/or OUT directions
365  * depending on the configuration structure.
366  * @note This function must be invoked in response of a SET_CONFIGURATION
367  * or SET_INTERFACE message.
368  *
369  * @param[in] usbp pointer to the @p USBDriver object
370  * @param[in] ep endpoint number
371  * @param[in] epcp the endpoint configuration
372  *
373  * @iclass
374  */
376  const USBEndpointConfig *epcp) {
377 
379  osalDbgCheck((usbp != NULL) && (epcp != NULL));
380  osalDbgAssert(usbp->state == USB_ACTIVE,
381  "invalid state");
382  osalDbgAssert(usbp->epc[ep] == NULL, "already initialized");
383 
384  /* Logically enabling the endpoint in the USBDriver structure.*/
385  usbp->epc[ep] = epcp;
386 
387  /* Clearing the state structures, custom fields as well.*/
388  if (epcp->in_state != NULL) {
389  memset(epcp->in_state, 0, sizeof(USBInEndpointState));
390  }
391  if (epcp->out_state != NULL) {
392  memset(epcp->out_state, 0, sizeof(USBOutEndpointState));
393  }
394 
395  /* Low level endpoint activation.*/
396  usb_lld_init_endpoint(usbp, ep);
397 }
398 
399 /**
400  * @brief Disables all the active endpoints.
401  * @details This function disables all the active endpoints except the
402  * endpoint zero.
403  * @note This function must be invoked in response of a SET_CONFIGURATION
404  * message with configuration number zero.
405  *
406  * @param[in] usbp pointer to the @p USBDriver object
407  *
408  * @iclass
409  */
411  unsigned i;
412 
414  osalDbgCheck(usbp != NULL);
415  osalDbgAssert(usbp->state == USB_ACTIVE, "invalid state");
416 
417  usbp->transmitting &= 1U;
418  usbp->receiving &= 1U;
419 
420  for (i = 1; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
421 #if USB_USE_WAIT == TRUE
422  /* Signaling the event to threads waiting on endpoints.*/
423  if (usbp->epc[i] != NULL) {
424  if (usbp->epc[i]->in_state != NULL) {
426  }
427  if (usbp->epc[i]->out_state != NULL) {
429  }
430  }
431 #endif
432  usbp->epc[i] = NULL;
433  }
434 
435  /* Low level endpoints deactivation.*/
437 }
438 
439 /**
440  * @brief Starts a receive transaction on an OUT endpoint.
441  * @note This function is meant to be called from ISR context outside
442  * critical zones because there is a potentially slow operation
443  * inside.
444  *
445  * @param[in] usbp pointer to the @p USBDriver object
446  * @param[in] ep endpoint number
447  * @param[out] buf buffer where to copy the received data
448  * @param[in] n transaction size. It is recommended a multiple of
449  * the packet size because the excess is discarded.
450  *
451  * @iclass
452  */
454  uint8_t *buf, size_t n) {
455  USBOutEndpointState *osp;
456 
458  osalDbgCheck((usbp != NULL) && (ep <= (usbep_t)USB_MAX_ENDPOINTS));
459  osalDbgAssert(!usbGetReceiveStatusI(usbp, ep), "already receiving");
460 
461  /* Marking the endpoint as active.*/
462  usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep);
463 
464  /* Setting up the transfer.*/
465  /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/
466  osp = usbp->epc[ep]->out_state;
467  /*lint -restore*/
468  osp->rxbuf = buf;
469  osp->rxsize = n;
470  osp->rxcnt = 0;
471 #if USB_USE_WAIT == TRUE
472  osp->thread = NULL;
473 #endif
474 
475  /* Starting transfer.*/
476  usb_lld_start_out(usbp, ep);
477 }
478 
479 /**
480  * @brief Starts a transmit transaction on an IN endpoint.
481  * @note This function is meant to be called from ISR context outside
482  * critical zones because there is a potentially slow operation
483  * inside.
484  *
485  * @param[in] usbp pointer to the @p USBDriver object
486  * @param[in] ep endpoint number
487  * @param[in] buf buffer where to fetch the data to be transmitted
488  * @param[in] n transaction size
489  *
490  * @iclass
491  */
493  const uint8_t *buf, size_t n) {
494  USBInEndpointState *isp;
495 
497  osalDbgCheck((usbp != NULL) && (ep <= (usbep_t)USB_MAX_ENDPOINTS));
498  osalDbgAssert(!usbGetTransmitStatusI(usbp, ep), "already transmitting");
499 
500  /* Marking the endpoint as active.*/
501  usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep);
502 
503  /* Setting up the transfer.*/
504  /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/
505  isp = usbp->epc[ep]->in_state;
506  /*lint -restore*/
507  isp->txbuf = buf;
508  isp->txsize = n;
509  isp->txcnt = 0;
510 #if USB_USE_WAIT == TRUE
511  isp->thread = NULL;
512 #endif
513 
514  /* Starting transfer.*/
515  usb_lld_start_in(usbp, ep);
516 }
517 
518 #if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
519 /**
520  * @brief Performs a receive transaction on an OUT endpoint.
521  *
522  * @param[in] usbp pointer to the @p USBDriver object
523  * @param[in] ep endpoint number
524  * @param[out] buf buffer where to copy the received data
525  * @param[in] n transaction size. It is recommended a multiple of
526  * the packet size because the excess is discarded.
527  *
528  * @return The received effective data size, it can be less than
529  * the amount specified.
530  * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation
531  * has been aborted by an USB reset or a transition to
532  * the @p USB_SUSPENDED state.
533  *
534  * @api
535  */
536 msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
537  msg_t msg;
538 
539  osalSysLock();
540 
541  if (usbGetDriverStateI(usbp) != USB_ACTIVE) {
542  osalSysUnlock();
543  return MSG_RESET;
544  }
545 
546  usbStartReceiveI(usbp, ep, buf, n);
547  msg = osalThreadSuspendS(&usbp->epc[ep]->out_state->thread);
548  osalSysUnlock();
549 
550  return msg;
551 }
552 
553 /**
554  * @brief Performs a transmit transaction on an IN endpoint.
555  *
556  * @param[in] usbp pointer to the @p USBDriver object
557  * @param[in] ep endpoint number
558  * @param[in] buf buffer where to fetch the data to be transmitted
559  * @param[in] n transaction size
560  *
561  * @return The operation status.
562  * @retval MSG_OK operation performed successfully.
563  * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation
564  * has been aborted by an USB reset or a transition to
565  * the @p USB_SUSPENDED state.
566  *
567  * @api
568  */
569 msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n) {
570  msg_t msg;
571 
572  osalSysLock();
573 
574  if (usbGetDriverStateI(usbp) != USB_ACTIVE) {
575  osalSysUnlock();
576  return MSG_RESET;
577  }
578 
579  usbStartTransmitI(usbp, ep, buf, n);
580  msg = osalThreadSuspendS(&usbp->epc[ep]->in_state->thread);
581  osalSysUnlock();
582 
583  return msg;
584 }
585 #endif /* USB_USE_WAIT == TRUE */
586 
587 /**
588  * @brief Stalls an OUT endpoint.
589  *
590  * @param[in] usbp pointer to the @p USBDriver object
591  * @param[in] ep endpoint number
592  *
593  * @return The operation status.
594  * @retval false Endpoint stalled.
595  * @retval true Endpoint busy, not stalled.
596  *
597  * @iclass
598  */
600 
602  osalDbgCheck(usbp != NULL);
603 
604  if (usbGetReceiveStatusI(usbp, ep)) {
605  return true;
606  }
607 
608  usb_lld_stall_out(usbp, ep);
609  return false;
610 }
611 
612 /**
613  * @brief Stalls an IN endpoint.
614  *
615  * @param[in] usbp pointer to the @p USBDriver object
616  * @param[in] ep endpoint number
617  *
618  * @return The operation status.
619  * @retval false Endpoint stalled.
620  * @retval true Endpoint busy, not stalled.
621  *
622  * @iclass
623  */
625 
627  osalDbgCheck(usbp != NULL);
628 
629  if (usbGetTransmitStatusI(usbp, ep)) {
630  return true;
631  }
632 
633  usb_lld_stall_in(usbp, ep);
634  return false;
635 }
636 
637 /**
638  * @brief Host wake-up procedure.
639  * @note It is silently ignored if the USB device is not in the
640  * @p USB_SUSPENDED state.
641  *
642  * @param[in] usbp pointer to the @p USBDriver object
643  *
644  * @api
645  */
647 
648  if (usbp->state == USB_SUSPENDED) {
649  /* Starting host wakeup procedure.*/
650  usb_lld_wakeup_host(usbp);
651  }
652 }
653 
654 /**
655  * @brief USB reset routine.
656  * @details This function must be invoked when an USB bus reset condition is
657  * detected.
658  *
659  * @param[in] usbp pointer to the @p USBDriver object
660  *
661  * @notapi
662  */
663 void _usb_reset(USBDriver *usbp) {
664  unsigned i;
665 
666  /* State transition.*/
667  usbp->state = USB_READY;
668 
669  /* Resetting internal state.*/
670  usbp->status = 0;
671  usbp->address = 0;
672  usbp->configuration = 0;
673  usbp->transmitting = 0;
674  usbp->receiving = 0;
675 
676  /* Invalidates all endpoints into the USBDriver structure.*/
677  for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
678 #if USB_USE_WAIT == TRUE
679  /* Signaling the event to threads waiting on endpoints.*/
680  if (usbp->epc[i] != NULL) {
682  if (usbp->epc[i]->in_state != NULL) {
684  }
685  if (usbp->epc[i]->out_state != NULL) {
687  }
689  }
690 #endif
691  usbp->epc[i] = NULL;
692  }
693 
694  /* EP0 state machine initialization.*/
696 
697  /* Low level reset.*/
698  usb_lld_reset(usbp);
699 
700  /* Notification of reset event.*/
702 }
703 
704 /**
705  * @brief USB suspend routine.
706  * @details This function must be invoked when an USB bus suspend condition is
707  * detected.
708  *
709  * @param[in] usbp pointer to the @p USBDriver object
710  *
711  * @notapi
712  */
713 void _usb_suspend(USBDriver *usbp) {
714  /* No state change, suspend always returns to previous state. */
715 
716  /* State transition.*/
717  usbp->saved_state = usbp->state;
718  usbp->state = USB_SUSPENDED;
719 
720  /* Notification of suspend event.*/
722 
723  /* Terminating all pending transactions.*/
724  usbp->transmitting = 0;
725  usbp->receiving = 0;
726 
727  /* Signaling the event to threads waiting on endpoints.*/
728 #if USB_USE_WAIT == TRUE
729  {
730  unsigned i;
731 
732  for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
733  if (usbp->epc[i] != NULL) {
735  if (usbp->epc[i]->in_state != NULL) {
737  }
738  if (usbp->epc[i]->out_state != NULL) {
740  }
742  }
743  }
744  }
745 #endif
746 }
747 
748 /**
749  * @brief USB wake-up routine.
750  * @details This function must be invoked when an USB bus wake-up condition is
751  * detected.
752  *
753  * @param[in] usbp pointer to the @p USBDriver object
754  *
755  * @notapi
756  */
757 void _usb_wakeup(USBDriver *usbp) {
758 
759  /* State transition, returning to the previous state.*/
760  usbp->state = usbp->saved_state;
761 
762  /* Notification of suspend event.*/
764 }
765 
766 /**
767  * @brief Default EP0 SETUP callback.
768  * @details This function is used by the low level driver as default handler
769  * for EP0 SETUP events.
770  *
771  * @param[in] usbp pointer to the @p USBDriver object
772  * @param[in] ep endpoint number, always zero
773  *
774  * @notapi
775  */
776 void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
777  size_t max;
778 
779  /* Is the EP0 state machine in the correct state for handling setup
780  packets?*/
781  if (usbp->ep0state != USB_EP0_STP_WAITING) {
782  /* This is unexpected could require handling with a warning event.*/
783  /* CHTODO: handling here.*/
784 
785  /* Resetting the EP0 state machine and going ahead.*/
787  }
788 
789  /* Reading the setup data into the driver buffer.*/
790  usbReadSetup(usbp, ep, usbp->setup);
791 
792  /* First verify if the application has an handler installed for this
793  request.*/
794  /*lint -save -e9007 [13.5] No side effects, it is intentional.*/
795  if ((usbp->config->requests_hook_cb == NULL) ||
796  !(usbp->config->requests_hook_cb(usbp))) {
797  /*lint -restore*/
798  /* Invoking the default handler, if this fails then stalls the
799  endpoint zero as error.*/
800  /*lint -save -e9007 [13.5] No side effects, it is intentional.*/
801  if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) != USB_RTYPE_TYPE_STD) ||
802  !default_handler(usbp)) {
803  /*lint -restore*/
804  /* Error response, the state machine goes into an error state, the low
805  level layer will have to reset it to USB_EP0_WAITING_SETUP after
806  receiving a SETUP packet.*/
807  usb_lld_stall_in(usbp, 0);
808  usb_lld_stall_out(usbp, 0);
810  usbp->ep0state = USB_EP0_ERROR;
811  return;
812  }
813  }
814 #if (USB_SET_ADDRESS_ACK_HANDLING == USB_SET_ADDRESS_ACK_HW)
815  if (usbp->setup[1] == USB_REQ_SET_ADDRESS) {
816  /* Zero-length packet sent by hardware */
817  return;
818  }
819 #endif
820  /* Transfer preparation. The request handler must have populated
821  correctly the fields ep0next, ep0n and ep0endcb using the macro
822  usbSetupTransfer().*/
823  max = (size_t)get_hword(&usbp->setup[6]);
824  /* The transfer size cannot exceed the specified amount.*/
825  if (usbp->ep0n > max) {
826  usbp->ep0n = max;
827  }
828  if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_DEV2HOST) {
829  /* IN phase.*/
830  if (usbp->ep0n != 0U) {
831  /* Starts the transmit phase.*/
832  usbp->ep0state = USB_EP0_IN_TX;
834  usbStartTransmitI(usbp, 0, usbp->ep0next, usbp->ep0n);
836  }
837  else {
838  /* No transmission phase, directly receiving the zero sized status
839  packet.*/
841 #if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
843  usbStartReceiveI(usbp, 0, NULL, 0);
845 #else
846  usb_lld_end_setup(usbp, ep);
847 #endif
848  }
849  }
850  else {
851  /* OUT phase.*/
852  if (usbp->ep0n != 0U) {
853  /* Starts the receive phase.*/
854  usbp->ep0state = USB_EP0_OUT_RX;
856  usbStartReceiveI(usbp, 0, (uint8_t *)usbp->ep0next, usbp->ep0n);
858  }
859  else {
860  /* No receive phase, directly sending the zero sized status
861  packet.*/
863 #if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
865  usbStartTransmitI(usbp, 0, NULL, 0);
867 #else
868  usb_lld_end_setup(usbp, ep);
869 #endif
870  }
871  }
872 }
873 
874 /**
875  * @brief Default EP0 IN callback.
876  * @details This function is used by the low level driver as default handler
877  * for EP0 IN events.
878  *
879  * @param[in] usbp pointer to the @p USBDriver object
880  * @param[in] ep endpoint number, always zero
881  *
882  * @notapi
883  */
884 void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
885  size_t max;
886 
887  (void)ep;
888  switch (usbp->ep0state) {
889  case USB_EP0_IN_TX:
890  max = (size_t)get_hword(&usbp->setup[6]);
891  /* If the transmitted size is less than the requested size and it is a
892  multiple of the maximum packet size then a zero size packet must be
893  transmitted.*/
894  if ((usbp->ep0n < max) &&
895  ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0U)) {
897  usbStartTransmitI(usbp, 0, NULL, 0);
900  return;
901  }
902  /* Falls through.*/
904  /* Transmit phase over, receiving the zero sized status packet.*/
906 #if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
908  usbStartReceiveI(usbp, 0, NULL, 0);
910 #else
911  usb_lld_end_setup(usbp, ep);
912 #endif
913  return;
915  /* Status packet sent, invoking the callback if defined.*/
916  if (usbp->ep0endcb != NULL) {
917  usbp->ep0endcb(usbp);
918  }
920  return;
921  case USB_EP0_STP_WAITING:
923  case USB_EP0_OUT_RX:
924  /* All the above are invalid states in the IN phase.*/
925  osalDbgAssert(false, "EP0 state machine error");
926  /* Falls through.*/
927  case USB_EP0_ERROR:
928  /* Error response, the state machine goes into an error state, the low
929  level layer will have to reset it to USB_EP0_WAITING_SETUP after
930  receiving a SETUP packet.*/
931  usb_lld_stall_in(usbp, 0);
932  usb_lld_stall_out(usbp, 0);
934  usbp->ep0state = USB_EP0_ERROR;
935  return;
936  default:
937  osalDbgAssert(false, "EP0 state machine invalid state");
938  }
939 }
940 
941 /**
942  * @brief Default EP0 OUT callback.
943  * @details This function is used by the low level driver as default handler
944  * for EP0 OUT events.
945  *
946  * @param[in] usbp pointer to the @p USBDriver object
947  * @param[in] ep endpoint number, always zero
948  *
949  * @notapi
950  */
951 void _usb_ep0out(USBDriver *usbp, usbep_t ep) {
952 
953  (void)ep;
954  switch (usbp->ep0state) {
955  case USB_EP0_OUT_RX:
956  /* Receive phase over, sending the zero sized status packet.*/
958 #if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
960  usbStartTransmitI(usbp, 0, NULL, 0);
962 #else
963  usb_lld_end_setup(usbp, ep);
964 #endif
965  return;
967  /* Status packet received, it must be zero sized, invoking the callback
968  if defined.*/
969 #if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
970  if (usbGetReceiveTransactionSizeX(usbp, 0) != 0U) {
971  break;
972  }
973 #endif
974  if (usbp->ep0endcb != NULL) {
975  usbp->ep0endcb(usbp);
976  }
978  return;
979  case USB_EP0_STP_WAITING:
980  case USB_EP0_IN_TX:
983  /* All the above are invalid states in the IN phase.*/
984  osalDbgAssert(false, "EP0 state machine error");
985  /* Falls through.*/
986  case USB_EP0_ERROR:
987  /* Error response, the state machine goes into an error state, the low
988  level layer will have to reset it to USB_EP0_WAITING_SETUP after
989  receiving a SETUP packet.*/
990  usb_lld_stall_in(usbp, 0);
991  usb_lld_stall_out(usbp, 0);
993  usbp->ep0state = USB_EP0_ERROR;
994  return;
995  default:
996  osalDbgAssert(false, "EP0 state machine invalid state");
997  }
998 }
999 
1000 #endif /* HAL_USE_USB == TRUE */
1001 
1002 /** @} */
usb_lld_reset
void usb_lld_reset(USBDriver *usbp)
USB low level reset routine.
Definition: hal_usb_lld.c:156
usb_lld_wakeup_host
#define usb_lld_wakeup_host(usbp)
Start of host wake-up procedure.
Definition: hal_usb_lld.h:344
USBDriver::out_params
void * out_params[USB_MAX_ENDPOINTS]
Fields available to user, it can be used to associate an application-defined handler to an OUT endpoi...
Definition: hal_usb_lld.h:251
usb_lld_clear_in
void usb_lld_clear_in(USBDriver *usbp, usbep_t ep)
Brings an IN endpoint in the active state.
Definition: hal_usb_lld.c:381
usb_lld_stall_out
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep)
Brings an OUT endpoint in the stalled state.
Definition: hal_usb_lld.c:336
USBOutEndpointState::rxbuf
uint8_t * rxbuf
Pointer to the receive linear buffer.
Definition: hal_usb_lld.h:120
usb_lld_set_address
void usb_lld_set_address(USBDriver *usbp)
Sets the USB address.
Definition: hal_usb_lld.c:172
usbGetDriverStateI
#define usbGetDriverStateI(usbp)
Returns the driver state.
Definition: hal_usb.h:391
USB_EP0_STP_WAITING
@ USB_EP0_STP_WAITING
Definition: hal_usb.h:291
USBDriver::ep0next
uint8_t * ep0next
Next position in the buffer to be transferred through endpoint 0.
Definition: hal_usb_lld.h:259
USBOutEndpointState
Type of an OUT endpoint state structure.
Definition: hal_usb_lld.h:108
USBDescriptor
Type of an USB descriptor.
Definition: hal_usb.h:316
USBOutEndpointState::rxcnt
size_t rxcnt
Received bytes so far.
Definition: hal_usb_lld.h:116
USBOutEndpointState::rxsize
size_t rxsize
Requested receive transfer size.
Definition: hal_usb_lld.h:112
usb_lld_init_endpoint
void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep)
Enables an endpoint.
Definition: hal_usb_lld.c:186
_usb_suspend
void _usb_suspend(USBDriver *usbp)
USB suspend routine.
Definition: hal_usb.c:713
USBDriver
Structure representing an USB driver.
Definition: hal_usb_lld.h:217
usbSetupTransfer
#define usbSetupTransfer(usbp, buf, n, endcb)
Request transfer setup.
Definition: hal_usb.h:476
usb_lld_start_out
void usb_lld_start_out(USBDriver *usbp, usbep_t ep)
Starts a receive operation on an OUT endpoint.
Definition: hal_usb_lld.c:306
usbReadSetup
#define usbReadSetup(usbp, ep, buf)
Reads a setup packet from the dedicated packet buffer.
Definition: hal_usb.h:496
_usb_reset
void _usb_reset(USBDriver *usbp)
USB reset routine.
Definition: hal_usb.c:663
USBEndpointConfig::in_maxsize
uint16_t in_maxsize
IN endpoint maximum packet size.
Definition: hal_usb_lld.h:167
usb_lld_get_status_out
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep)
Returns the status of an OUT endpoint.
Definition: hal_usb_lld.c:218
usbStartReceiveI
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:453
MSG_RESET
#define MSG_RESET
Wakeup caused by a reset condition.
Definition: chschd.h:42
osalThreadSuspendS
msg_t osalThreadSuspendS(thread_reference_t *trp)
Sends the current thread sleeping and sets a reference variable.
Definition: osal.c:185
USB_EVENT_ADDRESS
@ USB_EVENT_ADDRESS
Definition: hal_usb.h:305
_usb_ep0in
void _usb_ep0in(USBDriver *usbp, usbep_t ep)
Default EP0 IN callback.
Definition: hal_usb.c:884
hal.h
HAL subsystem header.
USB_EVENT_SUSPEND
@ USB_EVENT_SUSPEND
Definition: hal_usb.h:308
osalDbgCheckClassI
#define osalDbgCheckClassI()
I-Class state check.
Definition: osal.h:298
USBDriver::receiving
uint16_t receiving
Bit map of the receiving OUT endpoints.
Definition: hal_usb_lld.h:233
osalSysLockFromISR
static void osalSysLockFromISR(void)
Enters a critical zone from ISR context.
Definition: osal.h:621
usb_lld_disable_endpoints
void usb_lld_disable_endpoints(USBDriver *usbp)
Disables all the active endpoints except the endpoint zero.
Definition: hal_usb_lld.c:200
USBDescriptor::ud_string
const uint8_t * ud_string
Pointer to the descriptor.
Definition: hal_usb.h:324
USB_EP0_IN_TX
@ USB_EP0_IN_TX
Definition: hal_usb.h:292
usbStallReceiveI
bool usbStallReceiveI(USBDriver *usbp, usbep_t ep)
Stalls an OUT endpoint.
Definition: hal_usb.c:599
osalSysUnlock
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition: osal.h:611
_usb_ep0out
void _usb_ep0out(USBDriver *usbp, usbep_t ep)
Default EP0 OUT callback.
Definition: hal_usb.c:951
EP_STATUS_ACTIVE
@ EP_STATUS_ACTIVE
Definition: hal_usb.h:284
USBInEndpointState::txcnt
size_t txcnt
Transmitted bytes so far.
Definition: hal_usb_lld.h:91
USBEndpointConfig::in_state
USBInEndpointState * in_state
USBEndpointState associated to the IN endpoint.
Definition: hal_usb_lld.h:178
USBDescriptor::ud_size
size_t ud_size
Descriptor size in unicode characters.
Definition: hal_usb.h:320
msg_t
int32_t msg_t
Definition: chearly.h:88
USBEndpointConfig::out_state
USBOutEndpointState * out_state
USBEndpointState associated to the OUT endpoint.
Definition: hal_usb_lld.h:183
USBDriver::transmitting
uint16_t transmitting
Bit map of the transmitting IN endpoints.
Definition: hal_usb_lld.h:229
usbStallTransmitI
bool usbStallTransmitI(USBDriver *usbp, usbep_t ep)
Stalls an IN endpoint.
Definition: hal_usb.c:624
usbReceive
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:536
USB_EVENT_CONFIGURED
@ USB_EVENT_CONFIGURED
Definition: hal_usb.h:306
USBDriver::status
uint16_t status
Current USB device status.
Definition: hal_usb_lld.h:275
USBDriver::ep0state
usbep0state_t ep0state
Endpoint 0 state.
Definition: hal_usb_lld.h:255
USB_STOP
@ USB_STOP
Definition: hal_usb.h:271
osalOsRescheduleS
void osalOsRescheduleS(void)
Checks if a reschedule is required and performs it.
Definition: osal.c:119
default_handler
static bool default_handler(USBDriver *usbp)
Standard requests handler.
Definition: hal_usb.c:84
USB_EP0_OUT_RX
@ USB_EP0_OUT_RX
Definition: hal_usb.h:296
USB_EP0_ERROR
@ USB_EP0_ERROR
Definition: hal_usb.h:297
USBDriver::in_params
void * in_params[USB_MAX_ENDPOINTS]
Fields available to user, it can be used to associate an application-defined handler to an IN endpoin...
Definition: hal_usb_lld.h:244
_usb_isr_invoke_event_cb
#define _usb_isr_invoke_event_cb(usbp, evt)
Common ISR code, usb event callback.
Definition: hal_usb.h:511
USB_EVENT_RESET
@ USB_EVENT_RESET
Definition: hal_usb.h:304
USBInEndpointState::txbuf
const uint8_t * txbuf
Pointer to the transmission linear buffer.
Definition: hal_usb_lld.h:95
usbDisableEndpointsI
void usbDisableEndpointsI(USBDriver *usbp)
Disables all the active endpoints.
Definition: hal_usb.c:410
usbTransmit
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:569
usb_lld_stall_in
void usb_lld_stall_in(USBDriver *usbp, usbep_t ep)
Brings an IN endpoint in the stalled state.
Definition: hal_usb_lld.c:351
USB_EVENT_UNCONFIGURED
@ USB_EVENT_UNCONFIGURED
Definition: hal_usb.h:307
usb_lld_start_in
void usb_lld_start_in(USBDriver *usbp, usbep_t ep)
Starts a transmit operation on an IN endpoint.
Definition: hal_usb_lld.c:321
USBDriver::setup
uint8_t setup[8]
Setup packet buffer.
Definition: hal_usb_lld.h:271
usbStartTransmitI
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:492
USB_EVENT_STALLED
@ USB_EVENT_STALLED
Definition: hal_usb.h:310
_usb_ep0setup
void _usb_ep0setup(USBDriver *usbp, usbep_t ep)
Default EP0 SETUP callback.
Definition: hal_usb.c:776
USB_EVENT_WAKEUP
@ USB_EVENT_WAKEUP
Definition: hal_usb.h:309
USBConfig
Type of an USB driver configuration structure.
Definition: hal_usb_lld.h:190
USBOutEndpointState::thread
thread_reference_t thread
Waiting thread.
Definition: hal_usb_lld.h:125
usbInitEndpointI
void usbInitEndpointI(USBDriver *usbp, usbep_t ep, const USBEndpointConfig *epcp)
Enables an endpoint.
Definition: hal_usb.c:375
USBEndpointConfig
Type of an USB endpoint configuration structure.
Definition: hal_usb_lld.h:134
USBDriver::saved_state
usbstate_t saved_state
State of the driver when a suspend happened.
Definition: hal_usb_lld.h:287
usb_lld_clear_out
void usb_lld_clear_out(USBDriver *usbp, usbep_t ep)
Brings an OUT endpoint in the active state.
Definition: hal_usb_lld.c:366
usbGetReceiveStatusI
#define usbGetReceiveStatusI(usbp, ep)
Returns the status of an OUT endpoint.
Definition: hal_usb.h:446
USBDriver::ep0endcb
usbcallback_t ep0endcb
Endpoint 0 end transaction callback.
Definition: hal_usb_lld.h:267
EP_STATUS_STALLED
@ EP_STATUS_STALLED
Definition: hal_usb.h:283
USBDriver::state
usbstate_t state
Driver state.
Definition: hal_usb_lld.h:221
usb_lld_start
void usb_lld_start(USBDriver *usbp)
Configures and activates the USB peripheral.
Definition: hal_usb_lld.c:114
USBInEndpointState::thread
thread_reference_t thread
Waiting thread.
Definition: hal_usb_lld.h:100
osalDbgCheck
#define osalDbgCheck(c)
Function parameters check.
Definition: osal.h:284
USBConfig::requests_hook_cb
usbreqhandler_t requests_hook_cb
Requests hook callback.
Definition: hal_usb_lld.h:206
osalSysUnlockFromISR
static void osalSysUnlockFromISR(void)
Leaves a critical zone from ISR context.
Definition: osal.h:631
USB_READY
@ USB_READY
Definition: hal_usb.h:272
osalSysLock
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition: osal.h:601
USBConfig::get_descriptor_cb
usbgetdescriptor_t get_descriptor_cb
Device GET_DESCRIPTOR request callback.
Definition: hal_usb_lld.h:200
usb_lld_init
void usb_lld_init(void)
Low level USB driver initialization.
Definition: hal_usb_lld.c:99
USBDriver::config
const USBConfig * config
Current configuration data.
Definition: hal_usb_lld.h:225
USBDriver::configuration
uint8_t configuration
Current USB device configuration.
Definition: hal_usb_lld.h:283
USB_ACTIVE
@ USB_ACTIVE
Definition: hal_usb.h:274
USBDriver::address
uint8_t address
Assigned USB address.
Definition: hal_usb_lld.h:279
USB_EP0_OUT_WAITING_STS
@ USB_EP0_OUT_WAITING_STS
Definition: hal_usb.h:295
usb_lld_stop
void usb_lld_stop(USBDriver *usbp)
Deactivates the USB peripheral.
Definition: hal_usb_lld.c:135
USB_SELECTED
@ USB_SELECTED
Definition: hal_usb.h:273
usbStart
void usbStart(USBDriver *usbp, const USBConfig *config)
Configures and activates the USB peripheral.
Definition: hal_usb.c:303
USBInEndpointState
Type of an IN endpoint state structure.
Definition: hal_usb_lld.h:83
usb_lld_get_status_in
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep)
Returns the status of an IN endpoint.
Definition: hal_usb_lld.c:238
osalDbgAssert
#define osalDbgAssert(c, remark)
Condition assertion.
Definition: osal.h:264
USB_EP0_IN_SENDING_STS
@ USB_EP0_IN_SENDING_STS
Definition: hal_usb.h:294
osalThreadResumeI
void osalThreadResumeI(thread_reference_t *trp, msg_t msg)
Wakes up a thread waiting on a thread reference object.
Definition: osal.c:230
usbStop
void usbStop(USBDriver *usbp)
Deactivates the USB peripheral.
Definition: hal_usb.c:327
usbGetReceiveTransactionSizeX
#define usbGetReceiveTransactionSizeX(usbp, ep)
Returns the exact size of a receive transaction.
Definition: hal_usb.h:461
EP_STATUS_DISABLED
@ EP_STATUS_DISABLED
Definition: hal_usb.h:282
USBInEndpointState::txsize
size_t txsize
Requested transmit transfer size.
Definition: hal_usb_lld.h:87
USBDriver::epc
const USBEndpointConfig * epc[USB_MAX_ENDPOINTS+1]
Active endpoints configurations.
Definition: hal_usb_lld.h:237
usbep_t
uint8_t usbep_t
Type of an endpoint identifier.
Definition: hal_usb.h:264
usbObjectInit
void usbObjectInit(USBDriver *usbp)
Initializes the standard part of a USBDriver structure.
Definition: hal_usb.c:282
USB_EP0_IN_WAITING_TX0
@ USB_EP0_IN_WAITING_TX0
Definition: hal_usb.h:293
USBDriver::ep0n
size_t ep0n
Number of bytes yet to be transferred through endpoint 0.
Definition: hal_usb_lld.h:263
usbGetTransmitStatusI
#define usbGetTransmitStatusI(usbp, ep)
Returns the status of an IN endpoint.
Definition: hal_usb.h:432
USB_SUSPENDED
@ USB_SUSPENDED
Definition: hal_usb.h:275
usbInit
void usbInit(void)
USB Driver initialization.
Definition: hal_usb.c:270
usbWakeupHost
void usbWakeupHost(USBDriver *usbp)
Host wake-up procedure.
Definition: hal_usb.c:646
USB_MAX_ENDPOINTS
#define USB_MAX_ENDPOINTS
Maximum endpoint address.
Definition: hal_usb_lld.h:37
_usb_wakeup
void _usb_wakeup(USBDriver *usbp)
USB wake-up routine.
Definition: hal_usb.c:757
set_address
static void set_address(USBDriver *usbp)
SET ADDRESS transaction callback.
Definition: hal_usb.c:64