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