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