• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ----------------------------------------------------------------------------
2  * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
3  * Description: LiteOS USB Driver Composite Devices
4  * Author: Yannik Li
5  * Create: 2021-02-21
6  * Redistribution and use in source and binary forms, with or without modification,
7  * are permitted provided that the following conditions are met:
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  * conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  * of conditions and the following disclaimer in the documentation and/or other materials
12  * provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
14  * to endorse or promote products derived from this software without specific prior written
15  * permission.
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  * --------------------------------------------------------------------------- */
28 /* ----------------------------------------------------------------------------
29  * Notice of Export Control Law
30  * ===============================================
31  * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
32  * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
33  * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
34  * applicable export control laws and regulations.
35  * --------------------------------------------------------------------------- */
36 
37 #include "gadget/composite.h"
38 #include "gadget/cdcacm.h"
39 #include "gadget/rndis.h"
40 #include "f_common.h"
41 
42 #ifdef __cplusplus
43 #if __cplusplus
44 //extern "C" {
45 #endif /* __cplusplus */
46 #endif /* __cplusplus */
47 
48 #define FCONFIG_NSTRIDS                 5
49 
50 #define USB_ETHER_FIRST_INTERFACE_NUM   0
51 #define USB_SERIAL_FIRST_INTERFACE_NUM  2
52 
53 extern int composite_get_config_descriptor(struct usbdev_s *dev,
54                                            struct usbdev_req_s *req, unsigned len);
55 extern void modify_device_descriptor_byspeed(struct usbdev_s *dev, uint8_t *buf);
56 extern int usb_composite_setup(struct usbdevclass_driver_s *driver, struct usbdev_s *dev,
57                                const struct usb_device_request *ctrl, uint8_t *dataout, size_t outlen);
58 
59 int usbdev_fconfig_initialize(struct module *mod, int n, void *arg);
60 
61 /* device driver structure definition */
62 
63 static driver_t g_fconfig_driver_t =
64 {
65   .name    = "fconfig",
66   .methods = NULL,
67   .size    = 0
68 };
69 
70 /* private device class information */
71 
72 static devclass_t g_fconfig_devclass;
73 DRIVER_MODULE(fconfig, simple, g_fconfig_driver_t, g_fconfig_devclass, usbdev_fconfig_initialize, 0);
74 
75 static struct fconfig_softc g_fconfig_softc;
76 
gadget_match(struct usb_obj * obj,void * match_data)77 static int gadget_match(struct usb_obj *obj, void *match_data)
78 {
79   struct composite_softc *com_s = (struct composite_softc *)match_data;
80   struct gadget_info *gi = container_of(obj, struct gadget_info, obj);
81 
82   return gi->com_s == com_s;
83 }
84 
fconfig_find_gadget(struct composite_dev_s * com_dev)85 static struct gadget_info *fconfig_find_gadget(struct composite_dev_s *com_dev)
86 {
87   struct composite_softc *com_s = container_of(com_dev, struct composite_softc, dev);
88   struct fconfig_softc *cdev = &g_fconfig_softc;
89   struct usb_obj *obj;
90 
91   obj = usbobj_find(&cdev->obj, gadget_match, com_s);
92   if (obj)
93     {
94       return container_of(obj, struct gadget_info, obj);
95     }
96 
97   return NULL;
98 }
99 
fconfig_setup_complete(struct usbdev_ep_s * ep,struct usbdev_req_s * req)100 static void fconfig_setup_complete(struct usbdev_ep_s *ep,
101                                    struct usbdev_req_s *req)
102 {
103   (void)ep;
104   if (req->result != 0)
105     {
106       dprintf("%s, result = %d\n", __func__, req->result);
107     }
108 }
109 
fconfig_submit_ctrlreq(struct usbdev_s * dev,struct usbdev_req_s * usb_req)110 static int fconfig_submit_ctrlreq(struct usbdev_s *dev, struct usbdev_req_s *usb_req)
111 {
112   int ret;
113 
114   usb_req->callback = fconfig_setup_complete;
115   ret = EP_SUBMIT(dev->ep0, usb_req);
116   if (ret < 0)
117     {
118       usb_err("%s: endpoint send fail!\n", __FUNCTION__);
119       usb_req->result = 0;
120     }
121   return ret;
122 }
123 
gadget_strings_match(struct usb_obj * obj,void * match_data)124 int gadget_strings_match(struct usb_obj *obj, void *match_data)
125 {
126   struct gadget_strings *strings = container_of(obj, struct gadget_strings, obj);
127   uint16_t language = *(uint16_t *)match_data;
128 
129   return strings->language == language;
130 }
131 
132 #define STRING_ID_LEN 4
fconfig_mkstrdesc(struct composite_dev_s * com_dev,uint16_t language,uint8_t id,uint8_t * buf)133 static int fconfig_mkstrdesc(struct composite_dev_s *com_dev, uint16_t language, uint8_t id, uint8_t *buf)
134 {
135   struct gadget_info *gi;
136   struct usb_string_descriptor *str_desc = (struct usb_string_descriptor *)buf;
137   struct gadget_strings *dev_strings;
138   struct usb_obj *obj;
139   char lang_string[STRING_ID_LEN] = {STRING_ID_LEN, UDESC_STRING, 0x9, 0x4 };
140   int i;
141   int ret = -1;
142 
143   if (id == 0 && language == 0)
144     {
145       ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, (void *)lang_string, lang_string[0]);
146       if (ret != EOK)
147         {
148           return -1;
149         }
150       return lang_string[0];
151     }
152 
153   gi = fconfig_find_gadget(com_dev);
154   if (gi == NULL)
155     {
156       usb_err("%s: can not find gi\n", __FUNCTION__);
157       return -1;
158     }
159   if (id < gi->str_count)
160     {
161       obj = usbobj_find(&gi->strings, gadget_strings_match, &language);
162       if (!obj)
163         {
164           usb_err("%s: can not find the string with id = %u\n", __FUNCTION__, id);
165           return -1;
166         }
167       dev_strings = container_of(obj, struct gadget_strings, obj);
168 
169       for (i = 0; dev_strings->strings[i].s != NULL; i++)
170         {
171           const char *str = dev_strings->strings[i].s;
172           if (dev_strings->strings[i].id == id)
173             {
174               errno_t ret = utf8_to_utf16le(str, buf + 2, strlen(str));
175               if (ret <= 0)
176                 {
177                   usb_err("%s: memcpy_s failed, ret = %d\n", __FUNCTION__, ret);
178                   return -1;
179                 }
180               str_desc->bLength = 2 + (ret * 2);
181               str_desc->bDescriptorType = UDESC_STRING;
182               return str_desc->bLength;
183             }
184         }
185     }
186   else
187     {
188       for (i = 0; i < com_dev->ndevices; i++)
189         {
190           struct usbdev_devinfo_s *devinfo = &com_dev->device[i].compdesc.devinfo;
191           if (id >= (devinfo->strbase + gi->str_count) &&
192               id < (devinfo->strbase + devinfo->nstrings + gi->str_count))
193             {
194               *buf = (uint8_t)com_dev->device[i].compdesc.minor; /* pass minor number to driver */
195               ret = com_dev->device[i].compdesc.mkstrdesc(id - devinfo->strbase - gi->str_count, buf);
196               break;
197             }
198         }
199     }
200   return ret;
201 }
202 
fconfig_mkdevdesc(struct composite_dev_s * priv,uint8_t * buf)203 static void fconfig_mkdevdesc(struct composite_dev_s *priv, uint8_t *buf)
204 {
205   struct gadget_info *gi;
206   struct usb_device_descriptor  *dev_desc;
207   errno_t ret;
208 
209   gi = fconfig_find_gadget(priv);
210   if (gi == NULL)
211     {
212       usb_err("%s: gadget info is NULL\n", __FUNCTION__);
213       return;
214     }
215 
216   ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, gi->dev_desc, sizeof(*gi->dev_desc));
217   if (ret != EOK)
218     {
219       usb_err("%s: memcpy_s fail!, ret:%d\n", __FUNCTION__, ret);
220       return;
221     }
222   dev_desc = ( struct usb_device_descriptor  *)buf;
223   dev_desc->iManufacturer += 1;
224   dev_desc->iProduct += 1;
225   dev_desc->iSerialNumber += 1;
226 }
227 
usb_config_match(struct usb_obj * obj,void * match_data)228 static int usb_config_match(struct usb_obj *obj, void *match_data)
229 {
230   struct gadget_config *cfg = container_of(obj, struct gadget_config, obj);
231   uint8_t config_num = *(uint8_t *)match_data;
232 
233   return (cfg->cfg_num == config_num);
234 }
235 
fconfig_find_cfg(struct composite_dev_s * com_dev,uint32_t * string_num)236 static struct gadget_config *fconfig_find_cfg(struct composite_dev_s *com_dev, uint32_t *string_num)
237 {
238   struct composite_softc *com_s = container_of(com_dev, struct composite_softc, dev);
239   struct fconfig_softc *cdev = &g_fconfig_softc;
240   struct usb_obj *obj;
241   struct gadget_info *gi;
242   uint8_t config_num = 0;
243   struct gadget_config *cfg;
244 
245   obj = usbobj_find(&cdev->obj, gadget_match, com_s);
246   if (!obj)
247     {
248       usb_err("%s: can't find gadget info\n", __FUNCTION__);
249       return NULL;
250     }
251   gi = container_of(obj, struct gadget_info, obj);
252   *string_num = gi->str_count;
253   config_num = 1;
254   obj = usbobj_find(&gi->obj, usb_config_match, &config_num);
255   if (!obj)
256     {
257       usb_err("%s: can't find the configNumber %d\n", __FUNCTION__, config_num);
258       return NULL;
259     }
260   cfg = container_of(obj, struct gadget_config, obj);
261 
262   return cfg;
263 }
264 
modify_string_index_bystrbase(uint8_t * buf,int16_t len,uint32_t dev_str_num,int func_strbase)265 static int modify_string_index_bystrbase(uint8_t *buf, int16_t len,
266                                          uint32_t dev_str_num, int func_strbase)
267 {
268   struct usb_descriptor *descriptors;
269   struct usb_interface_assoc_descriptor *iad;
270   struct usb_interface_descriptor *intf;
271   uint32_t i;
272 
273   descriptors = (struct usb_descriptor *)buf;
274   i = 0;
275   while (i < len)
276     {
277       i += descriptors->bLength;
278       if (descriptors->bDescriptorType == UDESC_IFACE_ASSOC)
279         {
280           iad = (struct usb_interface_assoc_descriptor *)descriptors;
281           iad->iFunction += (uint8_t)(dev_str_num + func_strbase - 1);
282         }
283       else if (descriptors->bDescriptorType == UDESC_INTERFACE)
284         {
285           intf = (struct usb_interface_descriptor *)descriptors;
286           if (intf->bNumEndpoints > 0)
287             {
288               intf->iInterface += (uint8_t)(dev_str_num + func_strbase - 1);
289             }
290         }
291       descriptors = (struct usb_descriptor *)((char *)descriptors + descriptors->bLength);
292     }
293   return 0;
294 }
295 
fconfig_mkcfgdesc(struct composite_dev_s * priv,uint8_t * buf)296 static int fconfig_mkcfgdesc(struct composite_dev_s *priv, uint8_t *buf)
297 {
298   struct gadget_config *cfg;
299   struct usb_config_descriptor *config_desc;
300   int16_t total_len = 0;
301   int16_t len = USB_CONFIG_DESC_SIZE;
302   uint8_t *buf_tmp = buf;
303   uint32_t dev_string_num;
304   int ret, i;
305 
306   cfg = fconfig_find_cfg(priv, &dev_string_num);
307   if (!cfg)
308     {
309       usb_err("%s: can't find gadget config\n", __FUNCTION__);
310       return -1;
311     }
312   ret = memcpy_s(buf_tmp, USB_COMP_EP0_BUFSIZ,
313                  (const void *)cfg->cfg_desc, (uint32_t)len);
314   if (ret != EOK)
315     {
316       usb_err("memcpy_s fail, ret:%d\n", ret);
317       return -1;
318     }
319   total_len += len;
320   buf_tmp += len;
321   for (i = 0; i < priv->ndevices; i++)
322     {
323       struct generic_driver_s *drvr = (struct generic_driver_s *)priv->device[i].dev;
324       struct generic_dev_s *dev = drvr->dev;
325       int func_strbase = priv->device[i].compdesc.devinfo.strbase;
326       uint16_t off_len = 0;
327 
328       dprintf("%s,%d, raw_descs_length = %d\n", __func__, __LINE__, dev->raw_descs_length);
329       dprintf("%s,%d, fs_len = %d\n", __func__, __LINE__, dev->fs_descs_len);
330       dprintf("%s,%d, hs_len = %d\n", __func__, __LINE__, dev->hs_descs_len);
331       dprintf("%s,%d, ss_len = %d\n", __func__, __LINE__, dev->ss_descs_len);
332       dprintf("%s,%d, speed = %d\n", __func__, __LINE__, drvr->drvr.speed);
333       len = dev->fs_descs_len;
334       if (drvr->drvr.speed == USB_SPEED_HIGH)
335         {
336           off_len = dev->fs_descs_len;
337           len = dev->fs_descs_len;
338         }
339       else if (drvr->drvr.speed == USB_SPEED_SUPER)
340         {
341           off_len = dev->fs_descs_len + dev->hs_descs_len;
342           len = dev->ss_descs_len;
343         }
344 
345       ret = memcpy_s(buf_tmp, (USB_COMP_EP0_BUFSIZ - total_len),
346                      (const void *)((uint8_t *)dev->raw_descs + off_len), (uint32_t)len);
347       if (ret != EOK)
348         {
349           usb_err("memcpy_s fail, ret:%d\n", ret);
350           return -1;
351         }
352       modify_string_index_bystrbase(buf_tmp, len, dev_string_num, func_strbase);
353       total_len   += len;
354       buf_tmp += len;
355     }
356   config_desc = (struct usb_config_descriptor *)buf;
357   USETW(config_desc->wTotalLength, total_len);
358   config_desc->bNumInterface = priv->ninterfaces;
359   config_desc->iConfiguration += 1;
360 
361   return total_len;
362 }
363 
fconfig_composite_setup(struct usbdevclass_driver_s * driver,struct usbdev_s * dev,const struct usb_device_request * ctrl,uint8_t * dataout,size_t outlen)364 static int fconfig_composite_setup(struct usbdevclass_driver_s *driver, struct usbdev_s *dev,
365                                    const struct usb_device_request *ctrl, uint8_t *dataout, size_t outlen)
366 {
367   struct composite_driver_s *driv = (struct composite_driver_s *)driver;
368   int value   = 0;
369 
370   if (driv == NULL || driv->dev == NULL || ctrl == NULL || dev == NULL)
371     {
372       usb_err("%s: invalid parameter\n", __FUNCTION__);
373       return -1;
374     }
375 
376   if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR)
377     {
378       uint16_t w_value  = UGETW(ctrl->wValue);
379       uint16_t w_length = UGETW(ctrl->wLength);
380       uint16_t w_Index  = UGETW(ctrl->wIndex);
381       struct composite_dev_s *usb_cdev = driv->dev;
382       struct usbdev_req_s *usb_req = usb_cdev->ctrlreq;
383 
384       usb_req->len = 0;
385       switch (w_value >> 8)
386         {
387         case UDESC_DEVICE:
388           usb_debug("UDESC_DEVICE, usb_req:%x, buf:%x\n", usb_req, usb_req->buf);
389           value = MIN(w_length, (UINT16)sizeof(struct usb_device_descriptor));
390           fconfig_mkdevdesc(usb_cdev, usb_req->buf);
391           modify_device_descriptor_byspeed(dev, usb_req->buf);
392           usb_req->len = value;
393           return fconfig_submit_ctrlreq(dev, usb_req);
394         case UDESC_CONFIG:
395           usb_debug("%s, UDESC_CONFIG, usb_req:%x, buf:%x\n", __func__, usb_req, usb_req->buf);
396           value = fconfig_mkcfgdesc(usb_cdev, usb_req->buf);
397           if (value < 0)
398             {
399               break;
400             }
401           usb_req->len = value;
402           (void)composite_get_config_descriptor(dev, usb_req, w_length);
403           dprintf("%s, UDESC_CONFIG, usb_req->len: %x\n", __func__, usb_req->len);
404           return fconfig_submit_ctrlreq(dev, usb_req);
405 
406         case UDESC_STRING:
407           {
408             uint8_t strid = w_value & 0xff;
409             usb_debug("UDESC_STRING:%d\n", strid);
410             value = fconfig_mkstrdesc(usb_cdev, w_Index, strid, usb_req->buf);
411             if (value < 0)
412               {
413                 usb_err("%s: make string desc error\n", __FUNCTION__);
414                 return value;
415               }
416             usb_req->len = MIN(w_length, value);
417             return fconfig_submit_ctrlreq(dev, usb_req);
418           }
419         default:
420           /* will be processed by usb_composite_setup() */
421           break;
422         }
423     }
424 
425   return usb_composite_setup(driver, dev, ctrl, dataout, outlen);
426 }
427 
fconfig_do_composite_initialize(struct composite_softc * softc,uint8_t ndevices,struct composite_devdesc_s * pdevices)428 int fconfig_do_composite_initialize(struct composite_softc *softc, uint8_t ndevices,
429                                     struct composite_devdesc_s *pdevices)
430 {
431   struct composite_driver_s *drvr = &softc->drvr;
432   int ret;
433 
434   ret = composite_initialize(softc, ndevices, pdevices);
435   if (ret != 0)
436     {
437       return -1;
438     }
439 
440   drvr->drvr.ops->setup = fconfig_composite_setup;
441   return 0;
442 }
443 
usbdev_fconfig_initialize(struct module * mod,int n,void * arg)444 int usbdev_fconfig_initialize(struct module *mod, int n, void *arg)
445 {
446   struct fconfig_softc *cdev = &g_fconfig_softc;
447   struct composite_softc *com_s  = (struct composite_softc *)arg;
448   int ret;
449 
450   (void)mod;
451   (void)memset_s(cdev, sizeof(*cdev), 0, sizeof(*cdev));
452   usbobj_init(&cdev->obj, "fconfig", NULL);
453 
454   if (com_s == NULL)
455     {
456       usb_err("%s: com_s is null\n", __FUNCTION__);
457       return -1;
458     }
459   cdev->com_s = com_s;
460   com_s->dev.config = 1;
461   /* register fconfig device */
462   ret = fconfig_fops_init(cdev);
463   if (ret != LOS_OK)
464     {
465       usb_err("%s: create fconfig device node failed\n", __FUNCTION__);
466       return -1;
467     }
468   return 0;
469 }
470 
471 #ifdef __cplusplus
472 #if __cplusplus
473 //}
474 #endif /* __cplusplus */
475 #endif /* __cplusplus */
476