1 /****************************************************************************
2 * drivers/usbdev/composite.c
3 *
4 * Copyright (C) 2012, 2016-2017 Gregory Nutt. All rights reserved.
5 * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
6 * Author: Gregory Nutt <gnutt@nuttx.org>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name NuttX nor the names of its contributors may be
19 * used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
29 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 ****************************************************************************/
36 /****************************************************************************
37 * Notice of Export Control Law
38 * ===============================================
39 * Huawei LiteOS may be subject to applicable export control laws and regulations,
40 * which might include those applicable to Huawei LiteOS of U.S. and the country in
41 * which you are located.
42 * Import, export and usage of Huawei LiteOS in any manner by you shall be in
43 * compliance with such applicable export control laws and regulations.
44 ****************************************************************************/
45
46 /****************************************************************************
47 * Included Files
48 ****************************************************************************/
49 #include "los_vm_iomap.h"
50 #include "gadget/composite.h"
51 #define FCOFNIG_FUN
52
53 #undef USB_DEBUG_VAR
54 #define USB_DEBUG_VAR g_composite_debug
55 #ifdef LOSCFG_USB_DEBUG
56 static int g_composite_debug = 0;
usb_composite_debug_func(int level)57 void usb_composite_debug_func(int level)
58 {
59 g_composite_debug = level;
60 PRINTK("The level of usb composite debug is %d\n", level);
61 }
62 DEBUG_MODULE(composite, usb_composite_debug_func);
63 #endif
64
65 int composite_device_init(struct composite_softc *cdev);
66
67 static const uint8_t g_bos_desc_buf[22] =
68 {
69 5, 0xf, 0x16, 0, 2, 7, 0x10, 2, 6, 0, 0, 0,
70 0xa, 0x10, 3, 0, 0xf, 0, 1, 1, 0xf4, 1
71 };
72
73 static device_probe_t composite_probe;
74 static device_attach_t composite_attach;
75 static device_detach_t composite_detach;
76 static devclass_t composite_devclass;
77
78 static device_method_t g_composite_methods[] =
79 {
80 /* Device interface */
81
82 DEVMETHOD(device_probe, composite_probe),
83 DEVMETHOD(device_attach, composite_attach),
84 DEVMETHOD(device_detach, composite_detach),
85 DEVMETHOD_END
86 };
87
88 static driver_t g_composite_driver =
89 {
90 .name = "composite",
91 .methods = g_composite_methods,
92 .size = sizeof(struct composite_softc)
93 };
94
95 DRIVER_MODULE(composite, hiudc3, g_composite_driver, composite_devclass, NULL, NULL);
96
usbd_configep_byspeed(struct usbdev_s * dev,struct usb_endpoint_descriptor * ep_desc)97 void usbd_configep_byspeed(struct usbdev_s *dev, struct usb_endpoint_descriptor *ep_desc)
98 {
99 if (ep_desc->bmAttributes == UE_BULK)
100 {
101 switch (dev->speed)
102 {
103 case USB_SPEED_SUPER:
104 USETW(ep_desc->wMaxPacketSize, USB_DWC_MAX_PACKET_SIZE);
105 break;
106
107 case USB_SPEED_HIGH:
108 USETW(ep_desc->wMaxPacketSize, USB_DWC_U2_MAX_PACKET_SIZE);
109 break;
110
111 default:
112 PRINT_ERR("%s invalid speed:%u\r\n", __FUNCTION__, dev->speed);
113 break;
114 }
115 }
116
117 return;
118 }
119
composite_request_complete(struct usbdev_ep_s * ep,struct usbdev_req_s * req)120 void composite_request_complete(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
121 {
122 (void)ep;
123 (void)req;
124 }
125
composite_allocreq(uint16_t len)126 static struct usbdev_req_s *composite_allocreq(uint16_t len)
127 {
128 DMA_ADDR_T paddr;
129 struct usbdev_req_s *req = zalloc(sizeof(struct usbdev_req_s));
130 if (req != NULL)
131 {
132 req->len = len;
133 req->buf = (uint8_t *)LOS_DmaMemAlloc(&paddr, len, USB_CACHE_ALIGN_SIZE, DMA_NOCACHE);
134 if (req->buf == NULL)
135 {
136 free(req);
137 return NULL;
138 }
139 req->dma = (DMA_ADDR_T)VMM_TO_UNCACHED_ADDR((unsigned long)req->buf);
140 }
141
142 return req;
143 }
144
composite_freereq(struct usbdev_req_s * req)145 static void composite_freereq(struct usbdev_req_s *req)
146 {
147 if (req != NULL)
148 {
149 if (req->buf != NULL)
150 {
151 (VOID)LOS_DmaMemFree(req->buf);
152 req->buf = NULL;
153 }
154 free(req);
155 }
156 }
157
usb_composite_unbind(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)158 static int usb_composite_unbind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
159 {
160 struct composite_dev_s *cdev;
161 int ret;
162
163 if (driver == NULL || dev == NULL)
164 {
165 PRINT_ERR("unbind fail, invalid gadget\n");
166 return -1;
167 }
168
169 cdev = ((struct composite_driver_s *)driver)->dev;
170
171 /* Make sure that we are not already unbound */
172
173 if (cdev != NULL)
174 {
175 int i;
176
177 /* Unbind the constituent class drivers */
178
179 for (i = 0; i < cdev->ndevices; i++)
180 {
181 ret = CLASS_UNBIND(cdev->device[i].dev, dev);
182 if (ret < 0)
183 {
184 PRINT_ERR("unbind gadget fail, busy!\n");
185 return -1;
186 }
187 }
188
189 /* Free the pre-allocated control request */
190
191 cdev->config = COMPOSITE_CONFIGIDNONE;
192 composite_freereq(cdev->ctrlreq);
193 cdev->ctrlreq = NULL;
194 cdev->usbdev = NULL;
195 }
196 dev->ep0->priv = NULL;
197
198 return 0;
199 }
200
usb_composite_bind(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)201 static int usb_composite_bind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
202 {
203 struct composite_dev_s *cdev;
204 int ret;
205 int i;
206
207 if (driver == NULL || dev == NULL)
208 {
209 return -1;
210 }
211 cdev = ((struct composite_driver_s *)driver)->dev;
212 if (cdev == NULL)
213 {
214 PRINT_ERR("cdev == NULL\n");
215 return -1;
216 }
217
218 /* Bind the structures */
219
220 cdev->usbdev = dev;
221
222 /* initialize ctrlreq and allocate memory for it's buf */
223
224 cdev->ctrlreq = composite_allocreq(USB_COMP_EP0_BUFSIZ);
225 if (cdev->ctrlreq == NULL)
226 {
227 PRINT_ERR("%s malloc control request buf failed!\n", __FUNCTION__);
228 goto failed;
229 }
230 dev->ep0->handle_req = cdev->ctrlreq;
231 cdev->ctrlreq->callback = composite_request_complete;
232
233 /* Save the reference to our private data structure in EP0 so that it
234 * can be recovered in ep0 completion events.
235 */
236 dev->ep0->priv = cdev;
237 for (i = 0; i < cdev->ndevices; i++)
238 {
239 ret = CLASS_BIND(cdev->device[i].dev, dev);
240 if (ret < 0)
241 {
242 PRINT_ERR(" composite device bind gadget failed!\n");
243 goto failed;
244 }
245 }
246
247 DPRINTF("composite bind device success!\n");
248 return 0;
249
250 failed:
251 (void)usb_composite_unbind(driver, dev);
252 return -1;
253 }
254
modify_config_descriptor_byspeed(struct usbdev_s * dev,struct usbdev_req_s * req)255 static int modify_config_descriptor_byspeed(struct usbdev_s *dev, struct usbdev_req_s *req)
256 {
257 struct usb_descriptor *descriptors;
258 uint32_t config_len = req->len;
259 uint32_t new_config_len;
260 uint8_t *config_tmp_buf;
261 struct usb_config_descriptor *config_des;
262 uint32_t i;
263 int ret;
264
265 if (dev->speed != USB_SPEED_SUPER && dev->speed != USB_SPEED_HIGH)
266 {
267 usb_err("Device controller speed can not support!\n");
268 return -EINVAL;
269 }
270
271 if (dev->speed == USB_SPEED_SUPER)
272 {
273 return 0; /* The configuration descriptor defaults to the superspeed form. */
274 }
275
276 config_tmp_buf = malloc(config_len);
277 if (config_tmp_buf == NULL)
278 {
279 usb_err("malloc failed\n");
280 return -ENOMEM;
281 }
282
283 ret = memset_s(config_tmp_buf, config_len, 0, config_len);
284 if (ret != EOK)
285 {
286 usb_err("memset_s failed, %d\n", ret);
287 goto err;
288 }
289
290 descriptors = (struct usb_descriptor *)req->buf;
291 i = 0;
292 new_config_len = 0;
293 while (i < config_len)
294 {
295 i += descriptors->bLength;
296 if (descriptors->bDescriptorType != UDESC_ENDPOINT_SS_COMP)
297 {
298 ret = memcpy_s(config_tmp_buf + new_config_len, config_len - new_config_len,
299 descriptors, descriptors->bLength);
300 if (ret != EOK)
301 {
302 usb_err("memcpy_s failed, %d\n", ret);
303 goto err;
304 }
305 new_config_len += descriptors->bLength;
306 }
307 descriptors = (struct usb_descriptor *)((char *)descriptors + descriptors->bLength);
308 }
309 ret = memset_s(req->buf, USB_COMP_EP0_BUFSIZ, 0, config_len);
310 if (ret != EOK)
311 {
312 usb_err("memset_s failed, %d\n", ret);
313 goto err;
314 }
315
316 ret = memcpy_s(req->buf, USB_COMP_EP0_BUFSIZ, config_tmp_buf, new_config_len);
317 if (ret != EOK)
318 {
319 usb_err("memcpy_s failed, %d\n", ret);
320 goto err;
321 }
322
323 config_des = (struct usb_config_descriptor *)req->buf;
324 USETW(config_des->wTotalLength, new_config_len);
325 req->len = new_config_len;
326 free(config_tmp_buf);
327
328 return 0;
329
330 err:
331 free(config_tmp_buf);
332 return -EINVAL;
333 }
334
composite_get_config_descriptor(struct usbdev_s * dev,struct usbdev_req_s * req,unsigned len)335 int composite_get_config_descriptor(struct usbdev_s *dev,
336 struct usbdev_req_s *req, unsigned len)
337 {
338 int retval;
339 struct usb_descriptor *descriptors;
340 struct usb_endpoint_descriptor *ep_des;
341 int ret;
342 int i = 0;
343
344 ret = modify_config_descriptor_byspeed(dev, req);
345 if (ret < 0)
346 {
347 return -1;
348 }
349
350 retval = min(len, req->len);
351 descriptors = (struct usb_descriptor *)req->buf;
352
353 while (i < retval)
354 {
355 i += descriptors->bLength;
356 if (descriptors->bDescriptorType != UDESC_ENDPOINT)
357 {
358 descriptors = (struct usb_descriptor *)((char *)descriptors + descriptors->bLength);
359 continue;
360 }
361
362 ep_des = (struct usb_endpoint_descriptor *)descriptors;
363 usbd_configep_byspeed(dev, ep_des);
364 descriptors = (struct usb_descriptor *)((char *)descriptors + descriptors->bLength);
365 }
366
367 req->len = retval;
368 return retval;
369 }
370
modify_device_descriptor_byspeed(struct usbdev_s * dev,uint8_t * buf)371 void modify_device_descriptor_byspeed(struct usbdev_s *dev, uint8_t *buf)
372 {
373 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)buf;
374 switch (dev->speed)
375 {
376 case USB_SPEED_SUPER:
377 USETW(desc->bcdUSB, 0x0300);
378 desc->bMaxPacketSize = 0x09;
379 break;
380
381 case USB_SPEED_HIGH:
382 USETW(desc->bcdUSB, 0x0200);
383 desc->bMaxPacketSize = 0x40;
384 break;
385
386 default:
387 usb_err("invalid speed:%u\n", dev->speed);
388 break;
389 }
390 }
391
composite_classsetup(struct composite_dev_s * priv,struct usbdev_s * dev,const struct usb_device_request * ctrl,uint8_t * dataout,size_t outlen)392 static int composite_classsetup(struct composite_dev_s *priv,
393 struct usbdev_s *dev,
394 const struct usb_device_request *ctrl,
395 uint8_t *dataout, size_t outlen)
396 {
397 struct composite_devobj_s *devobj;
398 struct usbdev_devinfo_s *devinfo;
399 uint16_t index;
400 uint8_t interface;
401 int ret = -EOPNOTSUPP;
402 int i;
403 int j;
404
405 (void)dataout;
406 (void)outlen;
407
408 index = UGETW(ctrl->wIndex);
409 interface = (uint8_t)(index & 0xff);
410
411 /* Usb standard protocol logic processing, such as set interface. */
412
413 for (i = 0; i < priv->ndevices; i++)
414 {
415 if (interface >= priv->device[i].compdesc.devinfo.ifnobase &&
416 interface < (priv->device[i].compdesc.devinfo.ifnobase +
417 priv->device[i].compdesc.devinfo.ninterfaces))
418 {
419 ret = CLASS_SETUP(priv->device[i].dev, dev, ctrl, dataout, outlen);
420 return ret;
421 }
422 }
423
424 /* Specific protocol logic processing, such as UAC class setup. */
425
426 for (i = 0; i < priv->ndevices; i++)
427 {
428 devobj = &priv->device[i];
429 devinfo = &devobj->compdesc.devinfo;
430 for (j = 0; j < USBDEV_MAX_EPNUM; j++)
431 {
432 if (devinfo->epno[j] == interface)
433 {
434 ret = CLASS_SETUP(devobj->dev, dev, ctrl, dataout, outlen);
435 break;
436 }
437 }
438 }
439
440 return ret;
441 }
442
composite_setup_complete(struct usbdev_ep_s * ep,struct usbdev_req_s * req)443 static void composite_setup_complete(struct usbdev_ep_s *ep,
444 struct usbdev_req_s *req)
445 {
446 (void)ep;
447 (void)req;
448 }
449
usb_composite_setup(struct usbdevclass_driver_s * driver,struct usbdev_s * dev,const struct usb_device_request * ctrl,uint8_t * dataout,size_t outlen)450 int usb_composite_setup(struct usbdevclass_driver_s *driver, struct usbdev_s *dev,
451 const struct usb_device_request *ctrl, uint8_t *dataout, size_t outlen)
452 {
453 int ret = -1;
454 int value = 0;
455 int new_req = 0;
456 uint16_t w_value, w_length, w_Index;
457 struct composite_driver_s *driv;
458 struct composite_dev_s *usb_cdev;
459 struct usbdev_req_s *usb_req;
460 int i;
461
462 if (driver == NULL || ctrl == NULL || dev == NULL)
463 {
464 return -1;
465 }
466
467 driv = (struct composite_driver_s *)driver;
468 usb_cdev = driv->dev;
469 if (usb_cdev == NULL)
470 {
471 return -1;
472 }
473
474 w_value = UGETW(ctrl->wValue);
475 w_length = UGETW(ctrl->wLength);
476 w_Index = UGETW(ctrl->wIndex);
477
478 usb_req = usb_cdev->ctrlreq;
479
480 /* Update in the 'setup' function of a specific protocol, or use the default */
481 usb_req->callback = composite_setup_complete;
482 usb_req->len = 0;
483
484 switch (ctrl->bRequest)
485 {
486 case USB_REQ_GET_DESCRIPTOR:
487 {
488 if (ctrl->bmRequestType != USB_DIR_IN)
489 {
490 goto unknowned;
491 }
492
493 switch (w_value >> 8)
494 {
495 case UDESC_DEVICE:
496 value = MIN(w_length, (UINT16)sizeof(struct usb_device_descriptor));
497 composite_mkdevdesc(usb_cdev, usb_req->buf);
498 modify_device_descriptor_byspeed(dev, usb_req->buf);
499 usb_req->len = value;
500 new_req = 1;
501 break;
502
503 case UDESC_CONFIG:
504 value = composite_mkcfgdesc(usb_cdev, usb_req->buf);
505 if (value < 0)
506 {
507 break;
508 }
509 usb_req->len = value;
510 (void)composite_get_config_descriptor(dev, usb_req, w_length);
511 new_req = 1;
512 break;
513
514 case UDESC_STRING:
515 value = composite_mkstrdesc(usb_cdev, (w_value & 0xff), w_Index, usb_req->buf);
516 if (value < 0)
517 {
518 break;
519 }
520 usb_req->len = MIN(w_length, value);
521 new_req = 1;
522 break;
523
524 case UDESC_BOS:
525 usb_req->len = w_length;
526 ret = memcpy_s(usb_req->buf, USB_COMP_EP0_BUFSIZ, (void *)g_bos_desc_buf, SKB_DATA_ALIGN(usb_req->len));
527 if (ret < 0)
528 {
529 return -1;
530 }
531 new_req = 1;
532 break;
533
534 default:
535 break;
536 }
537 }
538 break;
539
540 case USB_REQ_SET_CONFIGURATION:
541 {
542 if (ctrl->bmRequestType != USB_DIR_OUT)
543 {
544 goto unknowned;
545 }
546 dprintf("SET_CONFIGURATION\n");
547 /* Save the configuration and inform the constituent classes */
548 for (i = 0; i < usb_cdev->ndevices; i++)
549 {
550 ret = CLASS_SETUP(usb_cdev->device[i].dev, dev, ctrl, dataout, outlen);
551 if (ret < 0)
552 {
553 PRINT_ERR("set config fail!\n");
554 return -1;
555 }
556 }
557
558 /* the ret of usbclass_mass_set_alt is '1', the invoking of usbd_endpoint_request is fmass's protocal */
559 if (ret == 0)
560 {
561 new_req = 1;
562 }
563 usb_req->len = 0;
564 usb_cdev->config = w_value;
565 }
566 break;
567
568 case USB_REQ_GET_CONFIGURATION:
569 {
570 dprintf("%s, USB_REQ_GET_CONFIGURATION\n", __func__);
571 usb_req->len = 1;
572 usb_req->buf[0] = 1;
573 new_req = 1;
574 break;
575 }
576
577 case USB_REQ_SET_INTERFACE:
578 {
579 if (ctrl->bmRequestType == USB_RECIP_INTERFACE &&
580 usb_cdev->config == COMPOSITE_CONFIGID)
581 {
582 value = composite_classsetup(usb_cdev, dev, ctrl, dataout, outlen);
583 new_req = 1;
584 }
585 break;
586 }
587
588 case USB_REQ_GET_STATUS:
589 {
590 if (ctrl->bmRequestType != (USB_DIR_IN | USB_RECIP_INTERFACE))
591 {
592 goto unknowned;
593 }
594
595 break;
596 }
597
598 case USB_REQ_CLEAR_FEATURE:
599 case USB_REQ_SET_FEATURE:
600 {
601 if (ctrl->bmRequestType != (USB_DIR_OUT | USB_RECIP_INTERFACE))
602 {
603 goto unknowned;
604 }
605
606 break;
607 }
608
609 default:
610 unknowned:
611 switch (ctrl->bmRequestType & USB_RECIP_MASK)
612 {
613 case USB_RECIP_INTERFACE:
614 case USB_RECIP_ENDPOINT:
615 (void)composite_classsetup(usb_cdev, dev, ctrl, dataout, outlen);
616 break;
617
618 default:
619 break;
620 }
621 goto success;
622 }
623
624 if (new_req)
625 {
626 value = EP_SUBMIT(dev->ep0, usb_req);
627 if (value < 0)
628 {
629 PRINT_ERR("endpoint send fail!\n");
630 usb_req->result = 0;
631 return -1;
632 }
633 }
634
635 success:
636 return value;
637 }
638
usb_composite_disconnect(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)639 static void usb_composite_disconnect(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
640 {
641 struct composite_dev_s *priv;
642 int i;
643
644 /* Extract reference to private data */
645
646 priv = ((struct composite_driver_s *)driver)->dev;
647 if (priv == NULL)
648 {
649 return;
650 }
651
652 for (i = 0; i < priv->ndevices; i++)
653 {
654 CLASS_DISCONNECT(priv->device[i].dev, dev);
655 }
656 }
657
usb_composite_suspend(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)658 static void usb_composite_suspend(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
659 {
660 (void)driver;
661 (void)dev;
662 PRINT_WARN("%s is not support now!\n", __FUNCTION__);
663 }
664
usb_composite_resume(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)665 static void usb_composite_resume(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
666 {
667 (void)driver;
668 (void)dev;
669 PRINT_WARN("%s is not support now!\n", __FUNCTION__);
670 }
671
672 static struct usbdevclass_driverops_s g_composite_driverops =
673 {
674 .bind = usb_composite_bind, /* bind */
675 .unbind = usb_composite_unbind, /* unbind */
676 .setup = usb_composite_setup, /* setup */
677 .disconnect = usb_composite_disconnect, /* disconnect */
678 .suspend = usb_composite_suspend, /* suspend */
679 .resume = usb_composite_resume, /* resume */
680 };
681
682 /* probe composite device driver */
usbd_composite_probe(struct composite_softc * cdev)683 int usbd_composite_probe(struct composite_softc *cdev)
684 {
685 int ret;
686
687 if (cdev == NULL)
688 {
689 return -INVAL_ARGU;
690 }
691
692 /* probe and initiate device driver */
693 ret = composite_device_init(cdev);
694 if (ret < 0)
695 {
696 PRINT_ERR("composite device init failed!, ret:%d\n", ret);
697 return -1;
698 }
699
700 return 0;
701 }
702
composite_probe(device_t dev)703 static int composite_probe(device_t dev)
704 {
705 return 0;
706 }
707 extern struct driver_module_data fcdcacm_simple_driver_mod;
708 extern struct driver_module_data fconfig_simple_driver_mod;
composite_device_init(struct composite_softc * cdev)709 int composite_device_init(struct composite_softc *cdev)
710 {
711 int ret;
712 #ifndef FCOFNIG_FUN
713 struct driver_module_data *mod = &fcdcacm_simple_driver_mod;
714 #else
715 struct driver_module_data *mod = &fconfig_simple_driver_mod;
716 #endif
717 if (mod->dmd_chainevh)
718 ret = mod->dmd_chainevh(NULL, MOD_LOAD, cdev);
719 return 0;
720 }
721
composite_attach(device_t dev)722 static int composite_attach(device_t dev)
723 {
724 struct composite_softc *usb_cdev = device_get_softc(dev);
725 void *parnet_conext = (void *)usb_cdev;
726
727 int ret;
728
729 if (usb_cdev == NULL || parnet_conext == NULL)
730 {
731 PRINT_ERR("%s usb_cdev or parnet_conext is null!\n", __FUNCTION__);
732 return -1;
733 }
734
735 /* probe gadget drivers */
736 ret = usbd_composite_probe(usb_cdev);
737 if (ret < 0)
738 {
739 return -1;
740 }
741
742 usb_cdev->drvr.dev = &usb_cdev->dev;
743 usb_cdev->parnet_conext = parnet_conext;
744 #ifndef FCOFNIG_FUN
745 usbd_start_udc();
746 ret = usbd_gadget_attach_driver(parnet_conext, &usb_cdev->drvr.drvr);
747 if (ret < 0)
748 {
749 goto detach;
750 }
751 #endif
752 DPRINTF("composite attach success!\n");
753 return 0; /* Attach success */
754 #ifndef FCOFNIG_FUN
755 detach:
756 (void)composite_detach(dev);
757 PRINT_ERR("%s failed, err=%d!\n", __FUNCTION__, ret);
758 return -1; /* No such device or address */
759 #endif
760 }
761
762 void composite_uninitialize(void *handle);
composite_detach(device_t dev)763 static int composite_detach(device_t dev)
764 {
765 struct composite_softc *usb_cdev = device_get_softc(dev);
766 void *parnet_conext = device_get_softc(device_get_parent(dev));
767 int ret;
768
769 if (usb_cdev == NULL || parnet_conext == NULL)
770 {
771 return -1;
772 }
773 PRINT_ERR("composite_detach!!!!!!!!!!!!!\n");
774 sleep(1);
775 ret = usbd_gadget_detach_driver(parnet_conext, &usb_cdev->drvr.drvr);
776 if (ret != 0)
777 {
778 PRINT_ERR("%s failed, err=%d!\n", __FUNCTION__, ret);
779 return ret;
780 }
781 composite_uninitialize(usb_cdev);
782
783 DPRINTF("%s\n", __FUNCTION__);
784 return (0);
785 }
786
787 /****************************************************************************
788 * Public Functions
789 ****************************************************************************/
790 /****************************************************************************
791 * Name: composite_initialize
792 *
793 * Description:
794 * Register USB composite device as configured. This function will call
795 * board-specific implementations in order to obtain the class objects for
796 * each of the members of the composite.
797 *
798 * Input Parameters:
799 * None
800 *
801 * Returned Value:
802 * A non-NULL "handle" is returned on success. This handle may be used
803 * later with composite_uninitialize() in order to removed the composite
804 * device. This handle is the (untyped) internal representation of the
805 * the class driver instance.
806 *
807 * NULL is returned on any failure.
808 *
809 ****************************************************************************/
810
composite_initialize(struct composite_softc * softc,uint8_t ndevices,struct composite_devdesc_s * pdevices)811 int composite_initialize(struct composite_softc *softc, uint8_t ndevices,
812 struct composite_devdesc_s *pdevices)
813 {
814 struct composite_dev_s *priv;
815 struct composite_driver_s *drvr;
816 int ret;
817 int i;
818
819 /* Convenience pointers into the allocated blob */
820
821 priv = &softc->dev;
822 drvr = &softc->drvr;
823
824 /* Initialize the USB composite driver structure */
825
826 (void)memset_s(priv, sizeof(struct composite_dev_s), 0, sizeof(struct composite_dev_s));
827 priv->cfgdescsize = 0;
828 priv->ninterfaces = 0;
829
830 /* Get the constituent class driver objects */
831
832 for (i = 0; i < ndevices; i++)
833 {
834 (void)memcpy_s(&priv->device[i].compdesc, sizeof(struct composite_devdesc_s),
835 &pdevices[i], sizeof(struct composite_devdesc_s));
836 ret = priv->device[i].compdesc.classobject(priv->device[i].compdesc.minor,
837 &priv->device[i].compdesc.devinfo,
838 &priv->device[i].dev);
839 if (ret < 0)
840 {
841 return -1;
842 }
843 priv->cfgdescsize += priv->device[i].compdesc.cfgdescsize;
844 priv->ninterfaces += priv->device[i].compdesc.devinfo.ninterfaces;
845 }
846 priv->ndevices = ndevices;
847
848 /* Initialize the USB class driver structure */
849
850 drvr->drvr.speed = USB_SPEED_HIGH;
851 drvr->drvr.ops = &g_composite_driverops;
852 drvr->dev = priv;
853
854 return 0;
855 }
856
composite_uninitialize(void * handle)857 void composite_uninitialize(void *handle)
858 {
859 struct composite_softc *usb_cdev = (struct composite_softc *)handle;
860 struct composite_dev_s *cdev = &usb_cdev->dev;
861 int i;
862
863 /* First phase uninitialization each of the member classes */
864
865 for (i = 0; i < cdev->ndevices; i++)
866 {
867 cdev->device[i].compdesc.uninitialize(cdev->device[i].dev);
868 }
869 }
870
usbclass_devobj_get(struct composite_dev_s * cdev,device_type type)871 struct composite_devobj_s *usbclass_devobj_get(struct composite_dev_s *cdev, device_type type)
872 {
873 int i;
874 struct composite_devdesc_s *compdesc;
875
876 for (i = 0; i < NUM_DEVICES_TO_HANDLE; i++)
877 {
878 compdesc = &cdev->device[i].compdesc;
879 if (compdesc->minor == type)
880 {
881 return &cdev->device[i];
882 }
883 }
884
885 return NULL;
886 }
887
888 #undef USB_DEBUG_VAR
889