• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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