1 /* ----------------------------------------------------------------------------
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved.
3 * Description: LiteOS USB Driver Config Data Stream
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 <poll.h>
38 #include "implementation/global_implementation.h"
39 #include "gadget/composite.h"
40 #include "f_common.h"
41 #include "devsvc_manager_clnt.h"
42 #include "hdf_device_desc.h"
43
44 #ifdef __cplusplus
45 #if __cplusplus
46 //extern "C" {
47 #endif /* __cplusplus */
48 #endif /* __cplusplus */
49
50 struct func_info {
51 uint8_t ndevices;
52 int ifnobase;
53 int strbase;
54 struct composite_devdesc_s *devs;
55 };
56
57 extern void usbdev_generic_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor);
58 extern void usbdev_cdcacm_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor);
59 extern void usbdev_rndis_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor);
60 extern void usbdev_mass_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor);
61 extern void usbdev_uac_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor);
62 extern void usbdev_uvc_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor);
63 extern int gadget_strings_match(struct usb_obj *obj, void *match_data);
64
65 struct usbdev_info g_generic_usbdev_info =
66 {
67 "generic", DEV_GENERIC, 0, usbdev_generic_initialize_sub
68 };
69
70 struct usbdev_info *g_fconfig_usbdev_info[] =
71 {
72 &g_generic_usbdev_info,
73 NULL,
74 };
75
fconfig_find_usbdev_info(char * name)76 static struct usbdev_info *fconfig_find_usbdev_info(char *name)
77 {
78 struct usbdev_info **dev_info = g_fconfig_usbdev_info;
79 int i;
80
81 for (i = 0; dev_info[i] != NULL; i++)
82 {
83 if (strcmp(dev_info[i]->name, name) == 0)
84 {
85 return dev_info[i];
86 }
87 }
88
89 return NULL;
90 }
91
fconfig_get_string(struct usb_obj * obj,struct fconfig_string * str)92 static char *fconfig_get_string(struct usb_obj *obj, struct fconfig_string *str)
93 {
94 size_t size = str->len;
95 char *buf = NULL;
96 int ret;
97 buf = (char *)usbm_malloc(obj, (size + 1));
98 if (buf == NULL)
99 {
100 usb_err("%s: malloc name buffer failed\n", __FUNCTION__);
101 return NULL;
102 }
103 memset_s(buf, size, 0, size);
104
105 ret = memcpy_s((void *)buf, (size + 1), (void *)str->s, size);
106 if (ret != EOK)
107 {
108 usb_err("%s: copy string from user failed\n", __FUNCTION__);
109 usbm_free(obj, buf);
110 return NULL;
111 }
112 *(buf + str->len) = '\0';
113 return buf;
114 }
115
gadget_match(struct usb_obj * obj,void * match_data)116 static int gadget_match(struct usb_obj *obj, void *match_data)
117 {
118 struct gadget_info *gi = container_of(obj, struct gadget_info, obj);
119 return !strcmp(gi->name, (char *)match_data);
120 }
121
gadget_find_by_name(struct fconfig_softc * cdev,struct fconfig_string * name)122 static struct gadget_info *gadget_find_by_name(struct fconfig_softc *cdev,
123 struct fconfig_string *name)
124 {
125 struct gadget_info *gi = NULL;
126 struct usb_obj *obj = NULL;
127 char *gadget_name = NULL;
128
129 gadget_name = fconfig_get_string(&cdev->obj, name);
130 if (gadget_name == NULL)
131 {
132 usb_err("%s: get gadget name failed\n", __FUNCTION__);
133 return NULL;
134 }
135
136 obj = usbobj_find(&cdev->obj, gadget_match, (void *)gadget_name);
137 if (obj)
138 {
139 gi = container_of(obj, struct gadget_info, obj);
140 }
141
142 usbm_free(&cdev->obj, gadget_name);
143 return gi;
144 }
145
gadget_make(struct fconfig_softc * cdev,char * name)146 static int gadget_make(struct fconfig_softc *cdev, char *name)
147 {
148 struct gadget_info *gi = NULL;
149 unsigned long flags;
150
151 spin_lock_irqsave(&cdev->obj.lock, flags);
152 if (!list_empty(&cdev->obj.children))
153 {
154 usb_err("%s, %d: gadget had make\n", __FUNCTION__, __LINE__);
155 spin_unlock_irqrestore(&cdev->obj.lock, flags);
156 return -1;
157 }
158 spin_unlock_irqrestore(&cdev->obj.lock, flags);
159
160 gi = usbm_malloc(&cdev->obj, sizeof(*gi));
161 if (gi == NULL)
162 {
163 usb_err("%s: malloc gadget failed\n", __FUNCTION__);
164 return -1;
165 }
166
167 memset_s(gi, sizeof(*gi), 0, sizeof(*gi));
168 usbobj_init(&gi->obj, name, usbobj_default_release);
169 usbobj_init(&gi->strings, "strings", usbobj_default_release);
170 gi->name = name;
171 gi->cdev = cdev;
172 gi->com_s = cdev->com_s;
173 usbobj_add(&gi->obj, &cdev->obj);
174 return 0;
175 }
176
gadget_drop(struct fconfig_softc * cdev,struct fconfig_string * name)177 static int gadget_drop(struct fconfig_softc *cdev, struct fconfig_string *name)
178 {
179 struct gadget_info *gi = NULL;
180
181 gi = gadget_find_by_name(cdev, name);
182 if (gi == NULL)
183 {
184 usb_err("%s: can not find gadget\n", __FUNCTION__);
185 return -1;
186 }
187
188 usbm_free(&cdev->obj, (void *)gi->name);
189 usbobj_put(&gi->strings);
190 usbobj_put(&gi->obj);
191 usbm_free(&cdev->obj, gi);
192 return 0;
193 }
194
fconfig_make_gadget(struct fconfig_softc * cdev,void * user_data)195 static int fconfig_make_gadget(struct fconfig_softc *cdev, void *user_data)
196 {
197 struct fconfig_string str;
198 char *name = NULL;
199 int ret;
200
201 ret = memcpy_s(&str, sizeof(str), user_data, sizeof(str));
202 if (ret != EOK)
203 {
204 return -1;
205 }
206
207 name = fconfig_get_string(&cdev->obj, &str);
208 if (name == NULL)
209 {
210 usb_err("%s: get gadget name failed\n", __FUNCTION__);
211 return -1;
212 }
213
214 return gadget_make(cdev, name);
215 }
216
fconfig_drop_gadget(struct fconfig_softc * cdev,void * user_data)217 static int fconfig_drop_gadget(struct fconfig_softc *cdev, void *user_data)
218 {
219 struct fconfig_string str;
220 int ret;
221
222 ret = memcpy_s(&str, sizeof(str), user_data, sizeof(str));
223 if (ret != EOK)
224 {
225 return -1;
226 }
227
228 return gadget_drop(cdev, &str);
229 }
230
fconfig_write_dev_desc(struct fconfig_softc * cdev,void * user_data)231 static int fconfig_write_dev_desc(struct fconfig_softc *cdev, void *user_data)
232 {
233 struct gadget_info *gi = NULL;
234 struct fconfig_dev_desc desc;
235 struct usb_device_descriptor *dev_desc = NULL;
236 int ret;
237
238 ret = memcpy_s(&desc, sizeof(desc), user_data, sizeof(desc));
239 if (ret != EOK)
240 {
241 return -1;
242 }
243
244 gi = gadget_find_by_name(cdev, &desc.gadget_name);
245 if (gi == NULL)
246 {
247 usb_err("%s: can not find the gadget\n", __FUNCTION__);
248 return -1;
249 }
250
251 dev_desc = (struct usb_device_descriptor *)usbm_malloc(&gi->obj, sizeof(*dev_desc));
252 if (dev_desc == NULL)
253 {
254 usb_err("%s: malloc device descriptor failed\n", __FUNCTION__);
255 goto err;
256 }
257
258 ret = memcpy_s(dev_desc, sizeof(*dev_desc), &desc.dev_desc, sizeof(*dev_desc));
259 if (ret != EOK)
260 {
261 goto err;
262 }
263
264 gi->dev_desc = dev_desc;
265 return 0;
266
267 err:
268 usbm_free(&gi->obj, dev_desc);
269 return -1;
270 }
271
fconfig_alloc_gadget_cfg(struct gadget_info * gi,char * cfg_name,struct usb_config_descriptor * cfg_desc)272 static struct gadget_config *fconfig_alloc_gadget_cfg(struct gadget_info *gi, char *cfg_name,
273 struct usb_config_descriptor *cfg_desc)
274 {
275 struct gadget_config *cfg = NULL;
276
277 cfg = (struct gadget_config *)usbm_malloc(&gi->obj, sizeof(*cfg));
278 if (cfg == NULL)
279 {
280 usb_err("%s: malloc usb cfg failed\n", __FUNCTION__);
281 return NULL;
282 }
283 memset_s(cfg, sizeof(*cfg), 0, sizeof(*cfg));
284 usbobj_init(&cfg->obj, cfg_name, usbobj_default_release);
285
286 cfg->gi = gi;
287 cfg->name = cfg_name;
288 cfg->cfg_desc = cfg_desc;
289 cfg->cfg_num = cfg_desc->bConfigurationValue;
290
291 return cfg;
292 }
293
fconfig_add_gadget_cfg(struct fconfig_softc * cdev,void * user_data)294 static int fconfig_add_gadget_cfg(struct fconfig_softc *cdev, void *user_data)
295 {
296 struct usb_config_descriptor *cfg_desc = NULL;
297 struct fconfig_cfg_desc desc;
298 struct gadget_config *cfg = NULL;
299 struct gadget_info *gi = NULL;
300 struct usb_obj *obj = NULL;
301 char *cfg_name = NULL;
302 int ret;
303
304 ret = memcpy_s(&desc, sizeof(desc), user_data, sizeof(desc));
305 if (ret != EOK)
306 {
307 return -1;
308 }
309
310 gi = gadget_find_by_name(cdev, &desc.gadget_name);
311 if (gi == NULL)
312 {
313 usb_err("%s: can't find the gadget\n", __FUNCTION__);
314 goto err;
315 }
316
317 cfg_name = fconfig_get_string(&gi->obj, &desc.config_name);
318 if (cfg_name == NULL)
319 {
320 usb_err("%s: get config name failed\n", __FUNCTION__);
321 goto err;
322 }
323
324 obj = usbobj_find(&gi->obj, usbobj_default_match, cfg_name);
325 if (obj)
326 {
327 usb_err("%s: the config %s has been existed\n",
328 __FUNCTION__, cfg_name);
329 goto err;
330 }
331
332 cfg_desc = (struct usb_config_descriptor *)usbm_malloc(&gi->obj, sizeof(*cfg_desc));
333 if (cfg_desc == NULL)
334 {
335 usb_err("%s: malloc config descriptor failed\n", __FUNCTION__);
336 goto err;
337 }
338
339 ret = memcpy_s(cfg_desc, sizeof(*cfg_desc), &desc.cfg_desc, sizeof(*cfg_desc));
340 if (ret != EOK)
341 {
342 usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
343 goto err;
344 }
345 cfg_desc->bLength = USB_CONFIG_DESC_SIZE;
346 cfg_desc->bDescriptorType = UDESC_CONFIG;
347 cfg = fconfig_alloc_gadget_cfg(gi, cfg_name, cfg_desc);
348 if (cfg == NULL)
349 {
350 usb_err("%s: alloc usb cfg failed\n", __FUNCTION__);
351 goto err;
352 }
353 usbobj_add(&cfg->obj, &gi->obj);
354 return 0;
355
356 err:
357 usbm_free(&gi->obj, cfg_desc);
358 usbm_free(&gi->obj, cfg_name);
359 return -1;
360 }
361
fconfig_remove_gadget_cfg(struct fconfig_softc * cdev,void * user_data)362 static int fconfig_remove_gadget_cfg(struct fconfig_softc *cdev, void *user_data)
363 {
364 struct fconfig_cfg_desc desc;
365 struct gadget_info *gi = NULL;
366 struct gadget_config *cfg = NULL;
367 struct usb_obj *obj = NULL;
368 char *config_name = NULL;
369 int ret;
370
371 ret = memcpy_s(&desc, sizeof(desc), (void *)user_data, sizeof(desc));
372 if (ret != EOK)
373 {
374 usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
375 return -1;
376 }
377
378 gi = gadget_find_by_name(cdev, &desc.gadget_name);
379 if (gi == NULL)
380 {
381 usb_err("%s: can't find the gadget\n", __FUNCTION__);
382 goto err;
383 }
384
385 config_name = fconfig_get_string(&gi->obj, &desc.config_name);
386 if (config_name == NULL)
387 {
388 usb_err("%s: get config name failed\n", __FUNCTION__);
389 goto err;
390 }
391
392 obj = usbobj_find(&gi->obj, usbobj_default_match, config_name);
393 if (!obj)
394 {
395 usb_err("%s: can't find the config %s\n", __FUNCTION__, config_name);
396 goto err;
397 }
398 cfg = container_of(obj, struct gadget_config, obj);
399 usbobj_put(&cfg->obj);
400
401 usbm_free(&gi->obj, cfg->name);
402 usbm_free(&gi->obj, cfg->cfg_desc);
403 return 0;
404
405 err:
406 usbm_free(&gi->obj, config_name);
407 return -1;
408 }
409
fconfig_fill_strings(struct gadget_info * gi,struct fconfig_dev_strings * str_data)410 static int fconfig_fill_strings(struct gadget_info *gi,
411 struct fconfig_dev_strings *str_data)
412 {
413 struct fconfig_usb_string *strings = NULL;
414 struct gadget_strings *dev_strings = NULL;
415 uint32_t size;
416 int i;
417 int ret;
418
419 size = sizeof(*dev_strings);
420 dev_strings = (struct gadget_strings *)usbm_malloc(&gi->obj, size);
421 if (dev_strings == NULL)
422 {
423 usb_err("%s: malloc strings failed\n", __FUNCTION__);
424 return -1;
425 }
426 memset_s(dev_strings, size, 0, size);
427 size = sizeof(struct usbd_string) * (str_data->str_count + 1);
428 dev_strings->strings = usbm_malloc(&gi->obj, size);
429 if (dev_strings == NULL)
430 {
431 usb_err("%s: malloc strings failed\n", __FUNCTION__);
432 return -1;
433 }
434
435 usbobj_init(&dev_strings->obj, "dev_strings", usbobj_default_release);
436 size = sizeof(*strings) * str_data->str_count;
437 strings = (struct fconfig_usb_string *)usbm_malloc(&dev_strings->obj, size);
438 if (strings == NULL)
439 {
440 usb_err("%s: malloc config usb strings failed\n", __FUNCTION__);
441 goto err;
442 }
443 ret = memcpy_s(strings, size, (void *)str_data->strings, size);
444 if (ret != EOK)
445 {
446 usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
447 goto err;
448 }
449 for (i = 0; i < str_data->str_count; i++)
450 {
451 char *str = fconfig_get_string(&dev_strings->obj, &strings[i].str);
452 if (str == NULL)
453 {
454 usb_err("%s: get string failed\n", __FUNCTION__);
455 goto err;
456 }
457 dev_strings->strings[i].id = strings[i].id + 1;
458 dev_strings->strings[i].s = str;
459 }
460 dev_strings->strings[i].id = 0;
461 dev_strings->strings[i].s = NULL;
462 dev_strings->language = str_data->language;
463
464 usbm_free(&dev_strings->obj, strings);
465 usbobj_add(&dev_strings->obj, &gi->strings);
466 return 0;
467
468 err:
469 usbobj_put(&dev_strings->obj);
470 return -1;
471 }
472
fconfig_write_strings(struct fconfig_softc * cdev,void * user_data)473 static int fconfig_write_strings(struct fconfig_softc *cdev, void *user_data)
474 {
475 struct gadget_info *gi = NULL;
476 struct fconfig_dev_strings str_data;
477 int ret;
478
479 ret = memcpy_s(&str_data, sizeof(str_data), (void *)user_data, sizeof(str_data));
480 if (ret != EOK)
481 {
482 usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
483 return -1;
484 }
485
486 gi = gadget_find_by_name(cdev, &str_data.gadget_name);
487 if (gi == NULL)
488 {
489 usb_err("%s: can't find the gadget\n", __FUNCTION__);
490 return -1;
491 }
492
493 /* set the string count for first time */
494 if (!gi->str_count)
495 {
496 gi->str_count = str_data.str_count + 1;
497 }
498 else if (gi->str_count != (str_data.str_count + 1))
499 {
500 usb_err("%s: str_count %u is not equeal to %u\n",
501 __FUNCTION__, str_data.str_count, gi->str_count);
502 return -1;
503 }
504 return fconfig_fill_strings(gi, &str_data);
505 }
506
function_instance_release(struct usb_obj * obj)507 void function_instance_release(struct usb_obj *obj)
508 {
509 int ret;
510 struct function_instance *func_inst = container_of(obj, struct function_instance, obj);
511
512 if (func_inst->minor >= DEV_GENERIC)
513 {
514 ret = usbdev_generic_free_instance(func_inst->name);
515 if (ret != 0)
516 {
517 usb_err("%s: free generic_func_inst %s failed\n", __func__, func_inst->name);
518 }
519 }
520 usbm_free(obj->parent, func_inst);
521 }
522
fconfig_do_make_function(struct gadget_config * cfg,char * func_name)523 static int fconfig_do_make_function(struct gadget_config *cfg, char *func_name)
524 {
525 struct function_instance *func_inst = NULL;
526 struct usbdev_info *dev_info = NULL;
527 char *instance_name = NULL;
528 char *obj_name = NULL;
529
530 /* split the whole name into function name and instance name */
531 instance_name = strchr(func_name, '.');
532 if (instance_name == NULL)
533 {
534 usb_err("%s: unable to locate . in %s\n", __FUNCTION__, func_name);
535 return -1;
536 }
537 *instance_name = '\0';
538 instance_name++;
539
540 func_inst = usbm_malloc(&cfg->obj, sizeof(*func_inst));
541 if (func_inst == NULL)
542 {
543 usb_err("%s: malloc function instance failed\n", __FUNCTION__);
544 return -1;
545 }
546 memset_s(func_inst, sizeof(*func_inst), 0, sizeof(*func_inst));
547 usbobj_init(&func_inst->obj, "", function_instance_release);
548
549 dev_info = fconfig_find_usbdev_info(func_name);
550 if (dev_info == NULL)
551 {
552 usb_err("%s: can not find dev_info\n", __FUNCTION__);
553 goto err;
554 }
555 obj_name = usbm_strdup(&func_inst->obj, instance_name);
556 func_inst->dev_info = dev_info;
557 func_inst->name = obj_name;
558 func_inst->obj.name = obj_name;
559 usbobj_add(&func_inst->obj, &cfg->obj);
560 dprintf("%s, func_inst->obj->name = %s\n", __func__, func_inst->obj.name);
561 if (dev_info->type != DEV_GENERIC)
562 {
563 /*for normal kernel driver */
564 func_inst->minor = dev_info->type;
565 }
566 else
567 {
568 /* for generic device */
569 int ret = usbdev_generic_alloc_instance(func_inst->name);
570 if (ret < DEV_GENERIC)
571 {
572 goto err;
573 }
574 func_inst->minor = ret;
575 }
576
577 return 0;
578
579 err:
580 usbobj_put(&func_inst->obj);
581 return -1;
582 }
583
fconfig_do_drop_function(struct gadget_config * cfg,char * func_name)584 static int fconfig_do_drop_function(struct gadget_config *cfg, char *func_name)
585 {
586 struct usb_obj *obj = NULL;
587 char *instance_name = NULL;
588
589 /* split the whole name into function name and instance name */
590 instance_name = strchr(func_name, '.');
591 if (instance_name == NULL)
592 {
593 usb_err("unable to locate . in %s\n", func_name);
594 return -1;
595 }
596 *instance_name = '\0';
597 instance_name++;
598
599 obj = usbobj_find(&cfg->obj, usbobj_default_match, instance_name);
600 if (!obj)
601 {
602 dprintf("%s, usbobj_find %s obj failed\n", __func__, instance_name);
603 return -1;
604 }
605
606 usbobj_put(obj);
607 return 0;
608 }
609
fconfig_get_function_info(struct fconfig_softc * cdev,void * user_data,char ** name,struct gadget_config ** usb_cfg)610 static int fconfig_get_function_info(struct fconfig_softc *cdev, void *user_data,
611 char **name, struct gadget_config **usb_cfg)
612 {
613 struct fconfig_func_info func_info;
614 struct gadget_config *cfg = NULL;
615 struct gadget_info *gi = NULL;
616 struct usb_obj *obj = NULL;
617 char *config_name = NULL;
618 char *func_name = NULL;
619 int ret;
620
621 ret = memcpy_s(&func_info, sizeof(func_info), (void *)user_data, sizeof(func_info));
622 if (ret != EOK)
623 {
624 usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
625 return -1;
626 }
627
628 gi = gadget_find_by_name(cdev, &func_info.gadget_name);
629 if (gi == NULL)
630 {
631 usb_err("%s: can't find the gadget\n", __FUNCTION__);
632 goto err;
633 }
634
635 config_name = fconfig_get_string(&gi->obj, &func_info.config_name);
636 if (config_name == NULL)
637 {
638 usb_err("%s: get config name failed\n", __FUNCTION__);
639 goto err;
640 }
641
642 /* find config from gadget object by the name */
643 obj = usbobj_find(&gi->obj, usbobj_default_match, config_name);
644 if (!obj)
645 {
646 usb_err("%s: can't find the config %s\n", __FUNCTION__, config_name);
647 goto err;
648 }
649 cfg = container_of(obj, struct gadget_config, obj);
650
651 func_name = fconfig_get_string(obj, &func_info.func_name);
652 if (func_name == NULL)
653 {
654 usb_err("%s: get func name failed\n", __FUNCTION__);
655 goto err2;
656 }
657
658 *name = func_name;
659 *usb_cfg = cfg;
660 usbm_free(&gi->obj, config_name);
661 return 0;
662
663 err2:
664 usbm_free(&cfg->obj, func_name);
665 err:
666 usbm_free(&gi->obj, config_name);
667 return -1;
668 }
669
fconfig_make_function(struct fconfig_softc * cdev,void * user_data)670 static int fconfig_make_function(struct fconfig_softc *cdev, void *user_data)
671 {
672 struct gadget_config *cfg = NULL;
673 char *func_name = NULL;
674 int ret;
675
676 ret = fconfig_get_function_info(cdev, user_data, &func_name, &cfg);
677 if (ret != 0)
678 {
679 usb_err("%s: get function info failed\n", __FUNCTION__);
680 return -1;
681 }
682
683 ret = fconfig_do_make_function(cfg, func_name);
684 if (ret != 0)
685 {
686 usb_err("%s: make function failed\n", __FUNCTION__);
687 }
688 usbm_free(&cfg->obj, func_name);
689
690 return ret;
691 }
692
fconfig_drop_function(struct fconfig_softc * cdev,void * user_data)693 static int fconfig_drop_function(struct fconfig_softc *cdev, void *user_data)
694 {
695 struct gadget_config *cfg = NULL;
696 char *func_name = NULL;
697 int ret;
698
699 ret = fconfig_get_function_info(cdev, user_data, &func_name, &cfg);
700 if (ret != 0)
701 {
702 usb_err("%s: get function info failed\n", __FUNCTION__);
703 return -1;
704 }
705
706 ret = fconfig_do_drop_function(cfg, func_name);
707 if (ret != 0)
708 {
709 usb_err("%s: make function failed\n", __FUNCTION__);
710 }
711
712 usbm_free(&cfg->obj, func_name);
713 return ret;
714 }
715
usb_config_match(struct usb_obj * obj,void * match_data)716 static int usb_config_match(struct usb_obj *obj, void *match_data)
717 {
718 struct gadget_config *cfg = container_of(obj, struct gadget_config, obj);
719 uint8_t config_num = *(uint8_t *)match_data;
720
721 return (cfg->cfg_num == config_num);
722 }
723
func_inst_init(struct usb_obj * obj,void * data)724 static void func_inst_init(struct usb_obj *obj, void *data)
725 {
726 struct function_instance *func = container_of(obj, struct function_instance, obj);
727 struct func_info * info = (struct func_info *)data;
728 struct usbdev_info *dev_info = NULL;
729
730 if (func == NULL || func->dev_info == NULL)
731 {
732 usb_err("%s: get function_instance failed\n", __FUNCTION__);
733 return;
734 }
735 dev_info = func->dev_info;
736
737 if (dev_info->type == DEV_GENERIC)
738 {
739 dev_info->initialize_sub(&info->devs[info->ndevices], info->ifnobase, func->minor);
740 info->devs[info->ndevices].devinfo.strbase = info->strbase;
741 info->ifnobase += info->devs[info->ndevices].devinfo.ninterfaces;
742 info->strbase += info->devs[info->ndevices].devinfo.nstrings;
743 }
744 else
745 {
746 dev_info->initialize_sub(&info->devs[info->ndevices], info->ifnobase, dev_info->type);
747 info->ifnobase += dev_info->ifnum;
748 }
749 info->ndevices++;
750 }
751
fconfig_composite_initialize(struct gadget_info * gi,struct composite_softc * com_s)752 static int fconfig_composite_initialize(struct gadget_info *gi,
753 struct composite_softc *com_s)
754 {
755 struct composite_devdesc_s devs[NUM_DEVICES_TO_HANDLE];
756 struct func_info info;
757 uint8_t config_num = 1;
758 struct usb_obj *obj = NULL;
759 struct gadget_config *cfg = NULL;
760
761 if (com_s)
762 {
763 config_num = com_s->dev.config;
764 }
765 info.devs = devs;
766 info.ndevices = 0;
767 info.ifnobase = 0;
768 info.strbase = 0;
769 config_num = 1;
770 obj = usbobj_find(&gi->obj, usb_config_match, &config_num);
771 if (!obj)
772 {
773 usb_err("%s: can't find the configNumber %d\n", __FUNCTION__, config_num);
774 return -1;
775 }
776 cfg = container_of(obj, struct gadget_config, obj);
777 usbobj_for_each_child(&cfg->obj, NULL, NULL, func_inst_init, &info);
778
779 return fconfig_do_composite_initialize(com_s, info.ndevices, devs);
780 }
781
fconfig_enable_udc(struct fconfig_softc * cdev,void * user_data)782 static int fconfig_enable_udc(struct fconfig_softc *cdev, void *user_data)
783 {
784 struct composite_softc *com_s = cdev->com_s;
785 struct fconfig_udc_info udc_info;
786 struct gadget_info *gi = NULL;
787 char *udc_name = NULL;
788 int ret;
789
790 ret = memcpy_s(&udc_info, sizeof(udc_info), (void *)user_data, sizeof(udc_info));
791 if (ret != EOK)
792 {
793 usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
794 return -1;
795 }
796
797 gi = gadget_find_by_name(cdev, &udc_info.gadget_name);
798 if (gi == NULL)
799 {
800 usb_err("%s: can't find the gadget\n", __FUNCTION__);
801 goto err;
802 }
803
804 udc_name = fconfig_get_string(&gi->obj, &udc_info.udc_name);
805 if (udc_name == NULL)
806 {
807 usb_err("%s: get udc name failed\n", __FUNCTION__);
808 goto err;
809 }
810
811 gi->udc_name = udc_name;
812 /* TODO: Enable UDC */
813 ret = fconfig_composite_initialize(gi, com_s);
814 if (ret)
815 {
816 usb_err("%s: fcofnig composite init failed\n", __FUNCTION__);
817 goto err;
818 }
819 usbd_start_udc();
820 ret = usbd_gadget_attach_driver(com_s->parnet_conext, &com_s->drvr.drvr);
821 if (ret < 0)
822 {
823 usb_err("%s, usbd_gadget_attach_driver fail\n", __func__);
824 goto err;
825 }
826
827 return 0;
828
829 err:
830 usbm_free(&gi->obj, udc_name);
831 return -1;
832 }
833
fconfig_disable_udc(struct fconfig_softc * cdev,void * user_data)834 static int fconfig_disable_udc(struct fconfig_softc *cdev, void *user_data)
835 {
836 struct gadget_info *gi = NULL;
837 struct fconfig_udc_info udc_info;
838 int ret;
839
840 ret = memcpy_s(&udc_info, sizeof(udc_info), (void *)user_data, sizeof(udc_info));
841 if (ret != EOK)
842 {
843 usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
844 return -1;
845 }
846
847 gi = gadget_find_by_name(cdev, &udc_info.gadget_name);
848 if (gi == NULL)
849 {
850 usb_err("%s: can't find the gadget\n", __FUNCTION__);
851 goto err;
852 }
853
854 /* disable UDC */
855 usbd_stop_udc();
856 usbm_free(&gi->obj, gi->udc_name);
857 gi->udc_name = NULL;
858 return 0;
859
860 err:
861 return -1;
862 }
863
change_dev_descritor_info(struct gadget_info * gi,struct fconfig_dev_desc_info * desc_info)864 static int change_dev_descritor_info(struct gadget_info *gi,
865 struct fconfig_dev_desc_info *desc_info)
866 {
867 const char *name = NULL;
868
869 if (desc_info == NULL || gi == NULL)
870 {
871 usb_err("%s: param invail\n", __FUNCTION__);
872 return -1;
873 }
874 name = desc_info->prop.prop_name;
875 if (strcmp(USBDEV_VENDOR, name) == 0)
876 {
877 gi->dev_desc->idVendor[0] = (uint8_t)desc_info->prop.prop_value;
878 gi->dev_desc->idVendor[1] = (uint8_t)(desc_info->prop.prop_value >> 8);
879 }
880 else if (strcmp(USBDEV_IDPRODUCT, name) == 0)
881 {
882 gi->dev_desc->idProduct[0] = (uint8_t)desc_info->prop.prop_value;
883 gi->dev_desc->idProduct[1] = (uint8_t)(desc_info->prop.prop_value >> 8);
884 }
885 else if (strcmp(USBDEV_CLASS, name) == 0)
886 {
887 gi->dev_desc->bDeviceClass = (uint8_t)desc_info->prop.prop_value;
888 }
889 else if (strcmp(USBDEV_SUBCLASS, name) == 0)
890 {
891 gi->dev_desc->bDeviceSubClass = (uint8_t)desc_info->prop.prop_value;
892 }
893 else if (strcmp(USBDEV_PROTOCOL, name) == 0)
894 {
895 gi->dev_desc->bDeviceProtocol = (uint8_t)desc_info->prop.prop_value;
896 }
897 else if (strcmp(USBDEV_MAXSIZE, name) == 0)
898 {
899 gi->dev_desc->bMaxPacketSize = (uint8_t)desc_info->prop.prop_value;
900 }
901 else if (strcmp(USBDEV_NUMCFG, name) == 0)
902 {
903 gi->dev_desc->bNumConfigurations = (uint8_t)desc_info->prop.prop_value;
904 }
905 else if (strcmp(USBDEV_BCD, name) == 0)
906 {
907 gi->dev_desc->bcdUSB[0] = (uint8_t)desc_info->prop.prop_value;
908 gi->dev_desc->bcdUSB[1] = (uint8_t)(desc_info->prop.prop_value >> 8);
909 }
910 else if (strcmp(USBDEV_BCDDEVICE, name) == 0)
911 {
912 gi->dev_desc->bcdDevice[0] = (uint8_t)desc_info->prop.prop_value;
913 gi->dev_desc->bcdDevice[1] = (uint8_t)(desc_info->prop.prop_value >> 8);
914 }
915 else
916 {
917 usb_err("%{public}s: other prop", __func__);
918 return -1;
919 }
920 return 0;
921 }
922
fconfig_change_dev_desc_info(struct fconfig_softc * cdev,void * user_data)923 static int fconfig_change_dev_desc_info(struct fconfig_softc *cdev, void *user_data)
924 {
925 struct gadget_info *gi = NULL;
926 struct fconfig_dev_desc_info desc_info;
927 int ret;
928
929 ret = memcpy_s(&desc_info, sizeof(desc_info), (void *)user_data, sizeof(desc_info));
930 if (ret != EOK)
931 {
932 usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
933 return -1;
934 }
935
936 gi = gadget_find_by_name(cdev, &desc_info.gadget_name);
937 if (gi == NULL)
938 {
939 usb_err("%s: can't find the gadget\n", __FUNCTION__);
940 return -1;
941 }
942 if (gi->dev_desc == NULL)
943 {
944 usb_err("%s: dev_desc is null\n", __FUNCTION__);
945 return -1;
946 }
947 ret = change_dev_descritor_info(gi, &desc_info);
948 if (ret != EOK)
949 {
950 usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
951 return -1;
952 }
953 return 0;
954 }
955
change_dev_descritor_string(struct gadget_info * gi,struct fconfig_dev_desc_string * desc_string,struct gadget_strings * dev_strings)956 static int change_dev_descritor_string(struct gadget_info *gi,
957 struct fconfig_dev_desc_string *desc_string,
958 struct gadget_strings *dev_strings)
959 {
960 uint8_t id = 0xff;
961 int i;
962 const char *name = NULL;
963
964 if (desc_string == NULL || gi == NULL || dev_strings == NULL)
965 {
966 usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
967 return -1;
968 }
969 for (i = 0; dev_strings->strings[i].s != NULL; i++)
970 {
971 const char *str = dev_strings->strings[i].s;
972 if (strcmp(str, desc_string->prop.prop_value) == 0)
973 {
974 id = dev_strings->strings[i].id;
975 break;
976 }
977 }
978 if (id == 0xff)
979 {
980 usb_err("%s: not found ringht string ID\n", __FUNCTION__);
981 return -1;
982 }
983 name = desc_string->prop.prop_name;
984 if (strcmp(USBDEV_MANUFACTURER, name) == 0)
985 {
986 gi->dev_desc->iManufacturer = id;
987 }
988 else if (strcmp(USBDEV_PRODUCT, name) == 0)
989 {
990 gi->dev_desc->iProduct = id;
991 }
992 else if (strcmp(USBDEV_SERIALNUM, name) == 0)
993 {
994 gi->dev_desc->iSerialNumber = id;
995 }
996 else
997 {
998 usb_err("%{public}s: other prop", __func__);
999 return -1;
1000 }
1001 return 0;
1002 }
1003
fconfig_change_dev_desc_string(struct fconfig_softc * cdev,void * user_data)1004 static int fconfig_change_dev_desc_string(struct fconfig_softc *cdev, void *user_data)
1005 {
1006 struct usb_obj *obj = NULL;
1007 struct gadget_info *gi = NULL;
1008 struct fconfig_dev_desc_string desc_string;
1009 struct gadget_strings *dev_strings = NULL;
1010 int ret;
1011
1012 ret = memcpy_s(&desc_string, sizeof(desc_string), (void *)user_data, sizeof(desc_string));
1013 if (ret != EOK)
1014 {
1015 usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
1016 return -1;
1017 }
1018
1019 gi = gadget_find_by_name(cdev, &desc_string.gadget_name);
1020 if (gi == NULL)
1021 {
1022 usb_err("%s: can't find the gadget\n", __FUNCTION__);
1023 return -1;
1024 }
1025 if (gi->dev_desc == NULL)
1026 {
1027 usb_err("%s: dev_desc is null\n", __FUNCTION__);
1028 return -1;
1029 }
1030
1031 obj = usbobj_find(&gi->strings, gadget_strings_match, &desc_string.prop.lang);
1032 if (!obj)
1033 {
1034 usb_err("%s: can not find language = 0x%x strings\n", __func__, desc_string.prop.lang);
1035 return -1;
1036 }
1037 dev_strings = container_of(obj, struct gadget_strings, obj);
1038
1039 ret = change_dev_descritor_string(gi, &desc_string, dev_strings);
1040 if (ret != EOK)
1041 {
1042 usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
1043 return -1;
1044 }
1045 return 0;
1046 }
1047
fconfig_handle_open(struct usb_handle * handle)1048 int fconfig_handle_open(struct usb_handle *handle)
1049 {
1050 struct fconfig_softc *cdev = (struct fconfig_softc *)(handle->priv);
1051
1052
1053 if (cdev == NULL)
1054 {
1055 usb_err("Invalid private parameter!\n");
1056 return -1;
1057 }
1058
1059 usbobj_get(&cdev->obj);
1060 return 0;
1061 }
1062
fconfig_handle_close(struct usb_handle * handle)1063 int fconfig_handle_close(struct usb_handle *handle)
1064 {
1065 struct fconfig_softc *cdev = (struct fconfig_softc *)(handle->priv);
1066
1067 if (cdev == NULL)
1068 {
1069 usb_err("Invalid private parameter!\n");
1070 return -1;
1071 }
1072
1073 usbobj_put(&cdev->obj);
1074 return 0;
1075 }
1076
fconfig_handle_read(struct usb_handle * handle,void * buffer,size_t len)1077 int fconfig_handle_read(struct usb_handle *handle, void *buffer, size_t len)
1078 {
1079 struct fconfig_softc *cdev = (struct fconfig_softc *)(handle->priv);
1080
1081 if (len == 0)
1082 {
1083 usb_err("buflen is 0!\n");
1084 return -1;
1085 }
1086
1087 if (cdev == NULL)
1088 {
1089 usb_err("Invalid private parameter!\n");
1090 return -1;
1091 }
1092
1093 return 0;
1094 }
1095
fconfig_handle_write(struct usb_handle * handle,void * buffer,size_t len)1096 int fconfig_handle_write(struct usb_handle *handle, void *buffer, size_t len)
1097 {
1098 struct fconfig_softc *cdev = (struct fconfig_softc *)(handle->priv);
1099
1100 if (len == 0)
1101 {
1102 usb_err("buflen is 0!\n");
1103 return -1;
1104 }
1105
1106 if (cdev == NULL)
1107 {
1108 usb_err("Invalid private parameter!\n");
1109 return -1;
1110 }
1111
1112 return 0;
1113 }
1114
fconfig_handle_ioctl(struct usb_handle * handle,int cmd,void * arg)1115 int fconfig_handle_ioctl(struct usb_handle *handle, int cmd, void *arg)
1116 {
1117 struct fconfig_softc *cdev = (struct fconfig_softc *)(handle->priv);
1118 void *argp = (void *)arg;
1119 int ret = -1;
1120
1121 if (cdev == NULL || argp == NULL)
1122 {
1123 usb_err("Invalid private parameter!\n");
1124 return -ENODEV;
1125 }
1126
1127 switch (cmd)
1128 {
1129 case FCONFIG_CMD_MAKE_GADGET:
1130 ret = fconfig_make_gadget(cdev, argp);
1131 break;
1132
1133 case FCONFIG_CMD_DROP_GADGET:
1134 ret = fconfig_drop_gadget(cdev, argp);
1135 break;
1136
1137 case FCONFIG_CMD_WRITE_DEV_DESC:
1138 ret = fconfig_write_dev_desc(cdev, argp);
1139 break;
1140
1141 case FCONFIG_CMD_ADD_CONFIG:
1142 ret = fconfig_add_gadget_cfg(cdev, argp);
1143 break;
1144
1145 case FCONFIG_CMD_REMOVE_CONFIG:
1146 ret = fconfig_remove_gadget_cfg(cdev, argp);
1147 break;
1148
1149 case FCONFIG_CMD_WRITE_STRINGS:
1150 ret = fconfig_write_strings(cdev, argp);
1151 break;
1152
1153 case FCONFIG_CMD_MAKE_FUNCTION:
1154 ret = fconfig_make_function(cdev, argp);
1155 break;
1156
1157 case FCONFIG_CMD_DROP_FUNCTION:
1158 ret = fconfig_drop_function(cdev, argp);
1159 break;
1160
1161 case FCONFIG_CMD_ENABLE_UDC:
1162 ret = fconfig_enable_udc(cdev, argp);
1163 break;
1164
1165 case FCONFIG_CMD_DISABLE_UDC:
1166 ret = fconfig_disable_udc(cdev, argp);
1167 break;
1168 case FCONFIG_CMD_CHAGE_DEVINFO:
1169 ret = fconfig_change_dev_desc_info(cdev, argp);
1170 break;
1171 case FCONFIG_CMD_CHAGE_DEVSTRING:
1172 ret = fconfig_change_dev_desc_string(cdev, argp);
1173 break;
1174 default:
1175 usb_err("the ioctl %d is not supported\n", cmd);
1176 break;
1177 }
1178
1179 return ret;
1180 }
1181
1182 static struct UsbHandleOps g_fconfig_handle_fops =
1183 {
1184 .open = fconfig_handle_open,
1185 .close = fconfig_handle_close,
1186 .read = fconfig_handle_read,
1187 .write = fconfig_handle_write,
1188 .ioctl = fconfig_handle_ioctl,
1189 };
1190
fconfig_fops_init(struct fconfig_softc * cdev)1191 int fconfig_fops_init(struct fconfig_softc *cdev)
1192 {
1193 int ret;
1194 char *devName = NULL;
1195
1196 if (cdev == NULL)
1197 {
1198 usb_err("%s: cdev is NULL\n", __FUNCTION__);
1199 return -1;
1200 }
1201
1202 devName = usbm_malloc(&cdev->obj, strlen(USB_FCONFIG_DEV) + 1);
1203 if (!devName)
1204 {
1205 return -1;
1206 }
1207 ret = snprintf_s(devName, strlen(USB_FCONFIG_DEV) + 1, strlen(USB_FCONFIG_DEV),
1208 "%s", USB_FCONFIG_DEV);
1209 if (ret < 0)
1210 {
1211 goto free_devname;
1212 }
1213 ret = register_handle(devName, &g_fconfig_handle_fops, cdev, &cdev->obj);
1214 if (ret != OK)
1215 {
1216 usb_err("%s: fconfig device register failed!\n", __FUNCTION__);
1217 goto free_devname;
1218 }
1219
1220 return 0;
1221
1222 free_devname:
1223 usbm_free(&cdev->obj, devName);
1224 return ret;
1225 }
1226
fconfig_fops_deinit(const struct fconfig_softc * cdev)1227 int fconfig_fops_deinit(const struct fconfig_softc *cdev)
1228 {
1229 int ret;
1230
1231 if (cdev == NULL)
1232 {
1233 usb_err("%s: cdev is NULL\n", __FUNCTION__);
1234 return -1;
1235 }
1236 ret = unregister_handle(USB_FCONFIG_DEV);
1237 if (ret != OK)
1238 {
1239 usb_err("%s: fconfig device unregister failed!\n", __FUNCTION__);
1240 }
1241
1242 return ret;
1243 }
1244
1245 #ifdef __cplusplus
1246 #if __cplusplus
1247 //}
1248 #endif /* __cplusplus */
1249 #endif /* __cplusplus */
1250