blob: 701f301208a759d693f84fb1f152796c535e63ca [file] [log] [blame]
Patrick Delaunay759d36c2020-09-04 18:20:51 +02001/*
Yann Gautierbbfc8a62022-02-14 15:22:14 +01002 * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved
Patrick Delaunay759d36c2020-09-04 18:20:51 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <stdint.h>
9
10#include <common/debug.h>
11#include <drivers/usb_device.h>
12
13/* Define for EP address */
14#define EP_DIR_MASK BIT(7)
15#define EP_DIR_IN BIT(7)
16#define EP_NUM_MASK GENMASK(3, 0)
17
18#define EP0_IN (0U | EP_DIR_IN)
19#define EP0_OUT 0U
20
21/* USB address between 1 through 127 = 0x7F mask */
22#define ADDRESS_MASK GENMASK(6, 0)
23
24/*
25 * Set a STALL condition over an endpoint
26 * pdev: USB handle
27 * ep_addr: endpoint address
28 * return : status
29 */
30static enum usb_status usb_core_set_stall(struct usb_handle *pdev, uint8_t ep_addr)
31{
32 struct usbd_ep *ep;
33 struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data;
34 uint8_t num;
35
36 num = ep_addr & EP_NUM_MASK;
37 if (num >= USBD_EP_NB) {
38 return USBD_FAIL;
39 }
40 if ((EP_DIR_MASK & ep_addr) == EP_DIR_IN) {
41 ep = &hpcd->in_ep[num];
42 ep->is_in = true;
43 } else {
44 ep = &hpcd->out_ep[num];
45 ep->is_in = false;
46 }
47 ep->num = num;
48
49 pdev->driver->ep_set_stall(hpcd->instance, ep);
50 if (num == 0U) {
51 pdev->driver->ep0_out_start(hpcd->instance);
52 }
53
54 return USBD_OK;
55}
56
57/*
58 * usb_core_get_desc
59 * Handle Get Descriptor requests
60 * pdev : device instance
61 * req : usb request
62 */
63static void usb_core_get_desc(struct usb_handle *pdev, struct usb_setup_req *req)
64{
65 uint16_t len;
66 uint8_t *pbuf;
67 uint8_t desc_type = HIBYTE(req->value);
68 uint8_t desc_idx = LOBYTE(req->value);
69
70 switch (desc_type) {
71 case USB_DESC_TYPE_DEVICE:
72 pbuf = pdev->desc->get_device_desc(&len);
73 break;
74
75 case USB_DESC_TYPE_CONFIGURATION:
Patrick Delaunayc7f971b2021-11-04 14:39:28 +010076 pbuf = pdev->desc->get_config_desc(&len);
Patrick Delaunay759d36c2020-09-04 18:20:51 +020077 break;
78
79 case USB_DESC_TYPE_STRING:
80 switch (desc_idx) {
81 case USBD_IDX_LANGID_STR:
82 pbuf = pdev->desc->get_lang_id_desc(&len);
83 break;
84
85 case USBD_IDX_MFC_STR:
86 pbuf = pdev->desc->get_manufacturer_desc(&len);
87 break;
88
89 case USBD_IDX_PRODUCT_STR:
90 pbuf = pdev->desc->get_product_desc(&len);
91 break;
92
93 case USBD_IDX_SERIAL_STR:
94 pbuf = pdev->desc->get_serial_desc(&len);
95 break;
96
97 case USBD_IDX_CONFIG_STR:
98 pbuf = pdev->desc->get_configuration_desc(&len);
99 break;
100
101 case USBD_IDX_INTERFACE_STR:
102 pbuf = pdev->desc->get_interface_desc(&len);
103 break;
104
105 /* For all USER string */
106 case USBD_IDX_USER0_STR:
107 default:
108 pbuf = pdev->desc->get_usr_desc(desc_idx - USBD_IDX_USER0_STR, &len);
109 break;
110 }
111 break;
112
113 case USB_DESC_TYPE_DEVICE_QUALIFIER:
Patrick Delaunayc7f971b2021-11-04 14:39:28 +0100114 pbuf = pdev->desc->get_device_qualifier_desc(&len);
Patrick Delaunay759d36c2020-09-04 18:20:51 +0200115 break;
116
117 case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION:
Patrick Delaunayb43d85a2021-11-04 15:13:33 +0100118 if (pdev->desc->get_other_speed_config_desc == NULL) {
119 usb_core_ctl_error(pdev);
120 return;
121 }
122 pbuf = pdev->desc->get_other_speed_config_desc(&len);
Patrick Delaunay759d36c2020-09-04 18:20:51 +0200123 break;
124
125 default:
126 ERROR("Unknown request %i\n", desc_type);
127 usb_core_ctl_error(pdev);
128 return;
129 }
130
131 if ((len != 0U) && (req->length != 0U)) {
132 len = MIN(len, req->length);
133
134 /* Start the transfer */
135 usb_core_transmit_ep0(pdev, pbuf, len);
136 }
137}
138
139/*
140 * usb_core_set_config
141 * Handle Set device configuration request
142 * pdev : device instance
143 * req : usb request
144 */
145static void usb_core_set_config(struct usb_handle *pdev, struct usb_setup_req *req)
146{
147 static uint8_t cfgidx;
148
149 cfgidx = LOBYTE(req->value);
150
151 if (cfgidx > USBD_MAX_NUM_CONFIGURATION) {
152 usb_core_ctl_error(pdev);
153 return;
154 }
155
156 switch (pdev->dev_state) {
157 case USBD_STATE_ADDRESSED:
158 if (cfgidx != 0U) {
159 pdev->dev_config = cfgidx;
160 pdev->dev_state = USBD_STATE_CONFIGURED;
161 if (!pdev->class) {
162 usb_core_ctl_error(pdev);
163 return;
164 }
165 /* Set configuration and Start the Class */
166 if (pdev->class->init(pdev, cfgidx) != 0U) {
167 usb_core_ctl_error(pdev);
168 return;
169 }
170 }
171 break;
172
173 case USBD_STATE_CONFIGURED:
174 if (cfgidx == 0U) {
175 pdev->dev_state = USBD_STATE_ADDRESSED;
176 pdev->dev_config = cfgidx;
177 pdev->class->de_init(pdev, cfgidx);
178 } else if (cfgidx != pdev->dev_config) {
Patrick Delaunaye8b6c762021-11-02 11:09:12 +0100179 if (pdev->class == NULL) {
Patrick Delaunay759d36c2020-09-04 18:20:51 +0200180 usb_core_ctl_error(pdev);
181 return;
182 }
183 /* Clear old configuration */
184 pdev->class->de_init(pdev, pdev->dev_config);
185 /* Set new configuration */
186 pdev->dev_config = cfgidx;
187 /* Set configuration and start the USB class */
188 if (pdev->class->init(pdev, cfgidx) != 0U) {
189 usb_core_ctl_error(pdev);
190 return;
191 }
192 }
193 break;
194
195 default:
196 usb_core_ctl_error(pdev);
197 return;
198 }
199
200 /* Send status */
201 usb_core_transmit_ep0(pdev, NULL, 0U);
202}
203
204/*
205 * usb_core_get_status
206 * Handle Get Status request
207 * pdev : device instance
208 * req : usb request
209 */
210static void usb_core_get_status(struct usb_handle *pdev,
211 struct usb_setup_req *req)
212{
213 if ((pdev->dev_state != USBD_STATE_ADDRESSED) &&
214 (pdev->dev_state != USBD_STATE_CONFIGURED)) {
215 usb_core_ctl_error(pdev);
216 return;
217 }
218
219 pdev->dev_config_status = USB_CONFIG_SELF_POWERED;
220
221 if (pdev->dev_remote_wakeup != 0U) {
222 pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP;
223 }
224
225 /* Start the transfer */
226 usb_core_transmit_ep0(pdev, (uint8_t *)&pdev->dev_config_status, 2U);
227}
228
229/*
230 * usb_core_set_address
231 * Set device address
232 * pdev : device instance
233 * req : usb request
234 */
235static void usb_core_set_address(struct usb_handle *pdev,
236 struct usb_setup_req *req)
237{
238 uint8_t dev_addr;
239
240 if ((req->index != 0U) || (req->length != 0U)) {
241 usb_core_ctl_error(pdev);
242 return;
243 }
244
245 dev_addr = req->value & ADDRESS_MASK;
246 if (pdev->dev_state != USBD_STATE_DEFAULT) {
247 usb_core_ctl_error(pdev);
248 return;
249 }
250
251 pdev->dev_address = dev_addr;
252 pdev->driver->set_address(((struct pcd_handle *)(pdev->data))->instance, dev_addr);
253
254 /* Send status */
255 usb_core_transmit_ep0(pdev, NULL, 0U);
256
257 if (dev_addr != 0U) {
258 pdev->dev_state = USBD_STATE_ADDRESSED;
259 } else {
260 pdev->dev_state = USBD_STATE_DEFAULT;
261 }
262}
263
264/*
265 * usb_core_dev_req
266 * Handle standard usb device requests
267 * pdev : device instance
268 * req : usb request
269 * return : status
270 */
271static enum usb_status usb_core_dev_req(struct usb_handle *pdev,
272 struct usb_setup_req *req)
273{
274 VERBOSE("receive request %i\n", req->b_request);
275 switch (req->b_request) {
276 case USB_REQ_GET_DESCRIPTOR:
277 usb_core_get_desc(pdev, req);
278 break;
279
280 case USB_REQ_SET_CONFIGURATION:
281 usb_core_set_config(pdev, req);
282 break;
283
284 case USB_REQ_GET_STATUS:
285 usb_core_get_status(pdev, req);
286 break;
287
288 case USB_REQ_SET_ADDRESS:
289 usb_core_set_address(pdev, req);
290 break;
291
292 case USB_REQ_GET_CONFIGURATION:
293 case USB_REQ_SET_FEATURE:
294 case USB_REQ_CLEAR_FEATURE:
295 default:
296 ERROR("NOT SUPPORTED %i\n", req->b_request);
297 usb_core_ctl_error(pdev);
298 break;
299 }
300
301 return USBD_OK;
302}
303
304/*
305 * usb_core_itf_req
306 * Handle standard usb interface requests
307 * pdev : device instance
308 * req : usb request
309 * return : status
310 */
311static enum usb_status usb_core_itf_req(struct usb_handle *pdev,
312 struct usb_setup_req *req)
313{
314 if (pdev->dev_state != USBD_STATE_CONFIGURED) {
315 usb_core_ctl_error(pdev);
316 return USBD_OK;
317 }
318
319 if (LOBYTE(req->index) <= USBD_MAX_NUM_INTERFACES) {
320 pdev->class->setup(pdev, req);
321
322 if (req->length == 0U) {
323 usb_core_transmit_ep0(pdev, NULL, 0U);
324 }
325 } else {
326 usb_core_ctl_error(pdev);
327 }
328
329 return USBD_OK;
330}
331
332/*
333 * usb_core_setup_stage
334 * Handle the setup stage
335 * pdev: device instance
336 * psetup : setup buffer
337 * return : status
338 */
339static enum usb_status usb_core_setup_stage(struct usb_handle *pdev,
340 uint8_t *psetup)
341{
342 struct usb_setup_req *req = &pdev->request;
343
344 /* Copy setup buffer into req structure */
345 req->bm_request = psetup[0];
346 req->b_request = psetup[1];
347 req->value = psetup[2] + (psetup[3] << 8);
348 req->index = psetup[4] + (psetup[5] << 8);
349 req->length = psetup[6] + (psetup[7] << 8);
350
351 pdev->ep0_state = USBD_EP0_SETUP;
352 pdev->ep0_data_len = pdev->request.length;
353
354 switch (pdev->request.bm_request & USB_REQ_RECIPIENT_MASK) {
355 case USB_REQ_RECIPIENT_DEVICE:
356 usb_core_dev_req(pdev, &pdev->request);
357 break;
358
359 case USB_REQ_RECIPIENT_INTERFACE:
360 usb_core_itf_req(pdev, &pdev->request);
361 break;
362
363 case USB_REQ_RECIPIENT_ENDPOINT:
364 default:
Yann Gautierbbfc8a62022-02-14 15:22:14 +0100365 ERROR("receive unsupported request %u",
Patrick Delaunay759d36c2020-09-04 18:20:51 +0200366 pdev->request.bm_request & USB_REQ_RECIPIENT_MASK);
367 usb_core_set_stall(pdev, pdev->request.bm_request & USB_REQ_DIRECTION);
368 return USBD_FAIL;
369 }
370
371 return USBD_OK;
372}
373
374/*
375 * usb_core_data_out
376 * Handle data OUT stage
377 * pdev: device instance
378 * epnum: endpoint index
379 * pdata: buffer to sent
380 * return : status
381 */
382static enum usb_status usb_core_data_out(struct usb_handle *pdev, uint8_t epnum,
383 uint8_t *pdata)
384{
385 struct usb_endpoint *pep;
386
387 if (epnum == 0U) {
388 pep = &pdev->ep_out[0];
389 if (pdev->ep0_state == USBD_EP0_DATA_OUT) {
390 if (pep->rem_length > pep->maxpacket) {
391 pep->rem_length -= pep->maxpacket;
392
393 usb_core_receive(pdev, 0U, pdata,
394 MIN(pep->rem_length,
395 pep->maxpacket));
396 } else {
397 if (pdev->class->ep0_rx_ready &&
398 (pdev->dev_state == USBD_STATE_CONFIGURED)) {
399 pdev->class->ep0_rx_ready(pdev);
400 }
401
402 usb_core_transmit_ep0(pdev, NULL, 0U);
403 }
404 }
405 } else if (pdev->class->data_out != NULL &&
406 (pdev->dev_state == USBD_STATE_CONFIGURED)) {
407 pdev->class->data_out(pdev, epnum);
408 }
409
410 return USBD_OK;
411}
412
413/*
414 * usb_core_data_in
415 * Handle data in stage
416 * pdev: device instance
417 * epnum: endpoint index
418 * pdata: buffer to fill
419 * return : status
420 */
421static enum usb_status usb_core_data_in(struct usb_handle *pdev, uint8_t epnum,
422 uint8_t *pdata)
423{
424 if (epnum == 0U) {
425 struct usb_endpoint *pep = &pdev->ep_in[0];
426
427 if (pdev->ep0_state == USBD_EP0_DATA_IN) {
428 if (pep->rem_length > pep->maxpacket) {
429 pep->rem_length -= pep->maxpacket;
430
431 usb_core_transmit(pdev, 0U, pdata,
432 pep->rem_length);
433
434 /* Prepare EP for premature end of transfer */
435 usb_core_receive(pdev, 0U, NULL, 0U);
436 } else {
437 /* Last packet is MPS multiple, send ZLP packet */
438 if ((pep->total_length % pep->maxpacket == 0U) &&
439 (pep->total_length >= pep->maxpacket) &&
440 (pep->total_length < pdev->ep0_data_len)) {
441 usb_core_transmit(pdev, 0U, NULL, 0U);
442
443 pdev->ep0_data_len = 0U;
444
445 /* Prepare endpoint for premature end of transfer */
446 usb_core_receive(pdev, 0U, NULL, 0U);
447 } else {
448 if (pdev->class->ep0_tx_sent != NULL &&
449 (pdev->dev_state ==
450 USBD_STATE_CONFIGURED)) {
451 pdev->class->ep0_tx_sent(pdev);
452 }
453 /* Start the transfer */
454 usb_core_receive_ep0(pdev, NULL, 0U);
455 }
456 }
457 }
458 } else if ((pdev->class->data_in != NULL) &&
459 (pdev->dev_state == USBD_STATE_CONFIGURED)) {
460 pdev->class->data_in(pdev, epnum);
461 }
462
463 return USBD_OK;
464}
465
466/*
467 * usb_core_suspend
468 * Handle suspend event
469 * pdev : device instance
470 * return : status
471 */
472static enum usb_status usb_core_suspend(struct usb_handle *pdev)
473{
474 INFO("USB Suspend mode\n");
475 pdev->dev_old_state = pdev->dev_state;
476 pdev->dev_state = USBD_STATE_SUSPENDED;
477
478 return USBD_OK;
479}
480
481/*
482 * usb_core_resume
483 * Handle resume event
484 * pdev : device instance
485 * return : status
486 */
487static enum usb_status usb_core_resume(struct usb_handle *pdev)
488{
489 INFO("USB Resume\n");
490 pdev->dev_state = pdev->dev_old_state;
491
492 return USBD_OK;
493}
494
495/*
496 * usb_core_sof
497 * Handle SOF event
498 * pdev : device instance
499 * return : status
500 */
501static enum usb_status usb_core_sof(struct usb_handle *pdev)
502{
503 if (pdev->dev_state == USBD_STATE_CONFIGURED) {
504 if (pdev->class->sof != NULL) {
505 pdev->class->sof(pdev);
506 }
507 }
508
509 return USBD_OK;
510}
511
512/*
513 * usb_core_disconnect
514 * Handle device disconnection event
515 * pdev : device instance
516 * return : status
517 */
518static enum usb_status usb_core_disconnect(struct usb_handle *pdev)
519{
520 /* Free class resources */
521 pdev->dev_state = USBD_STATE_DEFAULT;
522 pdev->class->de_init(pdev, pdev->dev_config);
523
524 return USBD_OK;
525}
526
527enum usb_status usb_core_handle_it(struct usb_handle *pdev)
528{
529 uint32_t param = 0U;
530 uint32_t len = 0U;
531 struct usbd_ep *ep;
532
533 switch (pdev->driver->it_handler(pdev->data->instance, &param)) {
534 case USB_DATA_OUT:
535 usb_core_data_out(pdev, param,
536 pdev->data->out_ep[param].xfer_buff);
537 break;
538
539 case USB_DATA_IN:
540 usb_core_data_in(pdev, param,
541 pdev->data->in_ep[param].xfer_buff);
542 break;
543
544 case USB_SETUP:
545 usb_core_setup_stage(pdev, (uint8_t *)pdev->data->setup);
546 break;
547
548 case USB_ENUM_DONE:
549 break;
550
551 case USB_READ_DATA_PACKET:
552 ep = &pdev->data->out_ep[param & USBD_OUT_EPNUM_MASK];
553 len = (param & USBD_OUT_COUNT_MASK) >> USBD_OUT_COUNT_SHIFT;
554 pdev->driver->read_packet(pdev->data->instance,
555 ep->xfer_buff, len);
556 ep->xfer_buff += len;
557 ep->xfer_count += len;
558 break;
559
560 case USB_READ_SETUP_PACKET:
561 ep = &pdev->data->out_ep[param & USBD_OUT_EPNUM_MASK];
562 len = (param & USBD_OUT_COUNT_MASK) >> 0x10;
563 pdev->driver->read_packet(pdev->data->instance,
564 (uint8_t *)pdev->data->setup, 8);
565 ep->xfer_count += len;
566 break;
567
568 case USB_RESET:
569 pdev->dev_state = USBD_STATE_DEFAULT;
570 break;
571
572 case USB_RESUME:
573 if (pdev->data->lpm_state == LPM_L1) {
574 pdev->data->lpm_state = LPM_L0;
575 } else {
576 usb_core_resume(pdev);
577 }
578 break;
579
580 case USB_SUSPEND:
581 usb_core_suspend(pdev);
582 break;
583
584 case USB_LPM:
585 if (pdev->data->lpm_state == LPM_L0) {
586 pdev->data->lpm_state = LPM_L1;
587 } else {
588 usb_core_suspend(pdev);
589 }
590 break;
591
592 case USB_SOF:
593 usb_core_sof(pdev);
594 break;
595
596 case USB_DISCONNECT:
597 usb_core_disconnect(pdev);
598 break;
599
600 case USB_WRITE_EMPTY:
601 pdev->driver->write_empty_tx_fifo(pdev->data->instance, param,
602 pdev->data->in_ep[param].xfer_len,
603 (uint32_t *)&pdev->data->in_ep[param].xfer_count,
604 pdev->data->in_ep[param].maxpacket,
605 &pdev->data->in_ep[param].xfer_buff);
606 break;
607
608 case USB_NOTHING:
609 default:
610 break;
611 }
612
613 return USBD_OK;
614}
615
Patrick Delaunay8507a5c2021-11-02 13:14:45 +0100616static void usb_core_start_xfer(struct usb_handle *pdev,
617 void *handle,
618 struct usbd_ep *ep)
619{
620 if (ep->num == 0U) {
621 pdev->driver->ep0_start_xfer(handle, ep);
622 } else {
623 pdev->driver->ep_start_xfer(handle, ep);
624 }
625}
626
Patrick Delaunay759d36c2020-09-04 18:20:51 +0200627/*
628 * usb_core_receive
629 * Receive an amount of data
630 * pdev: USB handle
631 * ep_addr: endpoint address
632 * buf: pointer to the reception buffer
633 * len: amount of data to be received
634 * return : status
635 */
636enum usb_status usb_core_receive(struct usb_handle *pdev, uint8_t ep_addr,
637 uint8_t *buf, uint32_t len)
638{
639 struct usbd_ep *ep;
640 struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data;
641 uint8_t num;
642
643 num = ep_addr & EP_NUM_MASK;
644 if (num >= USBD_EP_NB) {
645 return USBD_FAIL;
646 }
647 ep = &hpcd->out_ep[num];
648
649 /* Setup and start the Xfer */
650 ep->xfer_buff = buf;
651 ep->xfer_len = len;
652 ep->xfer_count = 0U;
653 ep->is_in = false;
654 ep->num = num;
655
Patrick Delaunay8507a5c2021-11-02 13:14:45 +0100656 usb_core_start_xfer(pdev, hpcd->instance, ep);
Patrick Delaunay759d36c2020-09-04 18:20:51 +0200657
658 return USBD_OK;
659}
660
661/*
662 * usb_core_transmit
663 * Send an amount of data
664 * pdev: USB handle
665 * ep_addr: endpoint address
666 * buf: pointer to the transmission buffer
667 * len: amount of data to be sent
668 * return : status
669 */
670enum usb_status usb_core_transmit(struct usb_handle *pdev, uint8_t ep_addr,
671 uint8_t *buf, uint32_t len)
672{
673 struct usbd_ep *ep;
674 struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data;
675 uint8_t num;
676
677 num = ep_addr & EP_NUM_MASK;
678 if (num >= USBD_EP_NB) {
679 return USBD_FAIL;
680 }
681 ep = &hpcd->in_ep[num];
682
683 /* Setup and start the Xfer */
684 ep->xfer_buff = buf;
685 ep->xfer_len = len;
686 ep->xfer_count = 0U;
687 ep->is_in = true;
688 ep->num = num;
689
Patrick Delaunay8507a5c2021-11-02 13:14:45 +0100690 usb_core_start_xfer(pdev, hpcd->instance, ep);
Patrick Delaunay759d36c2020-09-04 18:20:51 +0200691
692 return USBD_OK;
693}
694
695/*
696 * usb_core_receive_ep0
697 * Receive an amount of data on ep0
698 * pdev: USB handle
699 * buf: pointer to the reception buffer
700 * len: amount of data to be received
701 * return : status
702 */
703enum usb_status usb_core_receive_ep0(struct usb_handle *pdev, uint8_t *buf,
704 uint32_t len)
705{
706 /* Prepare the reception of the buffer over EP0 */
707 if (len != 0U) {
708 pdev->ep0_state = USBD_EP0_DATA_OUT;
709 } else {
710 pdev->ep0_state = USBD_EP0_STATUS_OUT;
711 }
712
713 pdev->ep_out[0].total_length = len;
714 pdev->ep_out[0].rem_length = len;
715
716 /* Start the transfer */
717 return usb_core_receive(pdev, 0U, buf, len);
718}
719
720/*
721 * usb_core_transmit_ep0
722 * Send an amount of data on ep0
723 * pdev: USB handle
724 * buf: pointer to the transmission buffer
725 * len: amount of data to be sent
726 * return : status
727 */
728enum usb_status usb_core_transmit_ep0(struct usb_handle *pdev, uint8_t *buf,
729 uint32_t len)
730{
731 /* Set EP0 State */
732 if (len != 0U) {
733 pdev->ep0_state = USBD_EP0_DATA_IN;
734 } else {
735 pdev->ep0_state = USBD_EP0_STATUS_IN;
736 }
737
738 pdev->ep_in[0].total_length = len;
739 pdev->ep_in[0].rem_length = len;
740
741 /* Start the transfer */
742 return usb_core_transmit(pdev, 0U, buf, len);
743}
744
745/*
746 * usb_core_ctl_error
747 * Handle USB low level error
748 * pdev: device instance
749 * req: usb request
750 * return : None
751 */
752
753void usb_core_ctl_error(struct usb_handle *pdev)
754{
755 ERROR("%s : Send an ERROR\n", __func__);
756 usb_core_set_stall(pdev, EP0_IN);
757 usb_core_set_stall(pdev, EP0_OUT);
758}
759
760/*
761 * usb_core_start
762 * Start the USB device core.
763 * pdev: Device Handle
764 * return : USBD Status
765 */
766enum usb_status usb_core_start(struct usb_handle *pdev)
767{
768 /* Start the low level driver */
769 pdev->driver->start_device(pdev->data->instance);
770
771 return USBD_OK;
772}
773
774/*
775 * usb_core_stop
776 * Stop the USB device core.
777 * pdev: Device Handle
778 * return : USBD Status
779 */
780enum usb_status usb_core_stop(struct usb_handle *pdev)
781{
782 /* Free class resources */
783 pdev->class->de_init(pdev, pdev->dev_config);
784
785 /* Stop the low level driver */
786 pdev->driver->stop_device(pdev->data->instance);
787
788 return USBD_OK;
789}
790
791/*
792 * register_usb_driver
793 * Stop the USB device core.
794 * pdev: Device Handle
795 * pcd_handle: PCD handle
796 * driver: USB driver
797 * driver_handle: USB driver handle
798 * return : USBD Status
799 */
800enum usb_status register_usb_driver(struct usb_handle *pdev,
801 struct pcd_handle *pcd_handle,
802 const struct usb_driver *driver,
803 void *driver_handle)
804{
805 uint8_t i;
806
807 assert(pdev != NULL);
808 assert(pcd_handle != NULL);
809 assert(driver != NULL);
810 assert(driver_handle != NULL);
811
812 /* Free class resources */
813 pdev->driver = driver;
814 pdev->data = pcd_handle;
815 pdev->data->instance = driver_handle;
816 pdev->dev_state = USBD_STATE_DEFAULT;
817 pdev->ep0_state = USBD_EP0_IDLE;
818
819 /* Copy endpoint information */
820 for (i = 0U; i < USBD_EP_NB; i++) {
821 pdev->ep_in[i].maxpacket = pdev->data->in_ep[i].maxpacket;
822 pdev->ep_out[i].maxpacket = pdev->data->out_ep[i].maxpacket;
823 }
824
825 return USBD_OK;
826}
827
828/*
829 * register_platform
830 * Register the USB device core.
831 * pdev: Device Handle
832 * plat_call_back: callback
833 * return : USBD Status
834 */
835enum usb_status register_platform(struct usb_handle *pdev,
836 const struct usb_desc *plat_call_back)
837{
838 assert(pdev != NULL);
839 assert(plat_call_back != NULL);
840
841 /* Save platform info in class resources */
842 pdev->desc = plat_call_back;
843
844 return USBD_OK;
845}