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
50struct func_info {
51  uint8_t ndevices;
52  int ifnobase;
53  int strbase;
54  struct composite_devdesc_s *devs;
55};
56
57extern void usbdev_generic_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor);
58extern void usbdev_cdcacm_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor);
59extern void usbdev_rndis_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor);
60extern void usbdev_mass_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor);
61extern void usbdev_uac_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor);
62extern void usbdev_uvc_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor);
63extern int gadget_strings_match(struct usb_obj *obj, void *match_data);
64
65struct usbdev_info g_generic_usbdev_info =
66{
67  "generic", DEV_GENERIC, 0, usbdev_generic_initialize_sub
68};
69
70struct usbdev_info *g_fconfig_usbdev_info[] =
71{
72  &g_generic_usbdev_info,
73  NULL,
74};
75
76static 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
92static 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
116static 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
122static 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
146static 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
177static 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
195static 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
217static 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
231static 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
267err:
268  usbm_free(&gi->obj, dev_desc);
269  return -1;
270}
271
272static 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
294static 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
356err:
357  usbm_free(&gi->obj, cfg_desc);
358  usbm_free(&gi->obj, cfg_name);
359  return -1;
360}
361
362static 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
405err:
406  usbm_free(&gi->obj, config_name);
407  return -1;
408}
409
410static 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
468err:
469  usbobj_put(&dev_strings->obj);
470  return -1;
471}
472
473static 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
507void 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
523static 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
579err:
580  usbobj_put(&func_inst->obj);
581  return -1;
582}
583
584static 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
610static 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
663err2:
664  usbm_free(&cfg->obj, func_name);
665err:
666  usbm_free(&gi->obj, config_name);
667  return -1;
668}
669
670static 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
693static 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
716static 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
724static 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
752static 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
782static 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  ret = fconfig_composite_initialize(gi, com_s);
813  if (ret)
814    {
815      usb_err("%s: fcofnig composite init failed\n", __FUNCTION__);
816      goto err;
817    }
818  usbd_start_udc();
819  ret = usbd_gadget_attach_driver(com_s->parnet_conext, &com_s->drvr.drvr);
820  if (ret < 0)
821    {
822      usb_err("%s, usbd_gadget_attach_driver fail\n", __func__);
823      goto err;
824    }
825
826  return 0;
827
828err:
829  usbm_free(&gi->obj, udc_name);
830  return -1;
831}
832
833static int fconfig_disable_udc(struct fconfig_softc *cdev, void *user_data)
834{
835  struct gadget_info *gi = NULL;
836  struct fconfig_udc_info udc_info;
837  int ret;
838
839  ret = memcpy_s(&udc_info, sizeof(udc_info), (void *)user_data, sizeof(udc_info));
840  if (ret != EOK)
841    {
842      usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
843      return -1;
844    }
845
846  gi = gadget_find_by_name(cdev, &udc_info.gadget_name);
847  if (gi == NULL)
848    {
849      usb_err("%s: can't find the gadget\n", __FUNCTION__);
850      goto err;
851    }
852
853  /* disable UDC */
854  usbd_stop_udc();
855  usbm_free(&gi->obj, gi->udc_name);
856  gi->udc_name = NULL;
857  return 0;
858
859err:
860  return -1;
861}
862
863static int change_dev_descritor_info(struct gadget_info *gi,
864                                     struct fconfig_dev_desc_info *desc_info)
865{
866  const char *name = NULL;
867
868  if (desc_info == NULL || gi == NULL)
869    {
870      usb_err("%s: param invail\n", __FUNCTION__);
871      return -1;
872    }
873  name = desc_info->prop.prop_name;
874  if (strcmp(USBDEV_VENDOR, name) == 0)
875    {
876      gi->dev_desc->idVendor[0] = (uint8_t)desc_info->prop.prop_value;
877      gi->dev_desc->idVendor[1] = (uint8_t)(desc_info->prop.prop_value >> 8);
878    }
879  else if (strcmp(USBDEV_IDPRODUCT, name) == 0)
880    {
881      gi->dev_desc->idProduct[0] = (uint8_t)desc_info->prop.prop_value;
882      gi->dev_desc->idProduct[1] = (uint8_t)(desc_info->prop.prop_value >> 8);
883    }
884  else if (strcmp(USBDEV_CLASS, name) == 0)
885    {
886      gi->dev_desc->bDeviceClass = (uint8_t)desc_info->prop.prop_value;
887    }
888  else if (strcmp(USBDEV_SUBCLASS, name) == 0)
889    {
890      gi->dev_desc->bDeviceSubClass = (uint8_t)desc_info->prop.prop_value;
891    }
892  else if (strcmp(USBDEV_PROTOCOL, name) == 0)
893    {
894      gi->dev_desc->bDeviceProtocol = (uint8_t)desc_info->prop.prop_value;
895    }
896  else if (strcmp(USBDEV_MAXSIZE, name) == 0)
897    {
898      gi->dev_desc->bMaxPacketSize = (uint8_t)desc_info->prop.prop_value;
899    }
900  else if (strcmp(USBDEV_NUMCFG, name) == 0)
901    {
902      gi->dev_desc->bNumConfigurations = (uint8_t)desc_info->prop.prop_value;
903    }
904  else if (strcmp(USBDEV_BCD, name) == 0)
905    {
906      gi->dev_desc->bcdUSB[0] = (uint8_t)desc_info->prop.prop_value;
907      gi->dev_desc->bcdUSB[1] = (uint8_t)(desc_info->prop.prop_value >> 8);
908    }
909  else if (strcmp(USBDEV_BCDDEVICE, name) == 0)
910    {
911      gi->dev_desc->bcdDevice[0] = (uint8_t)desc_info->prop.prop_value;
912      gi->dev_desc->bcdDevice[1] = (uint8_t)(desc_info->prop.prop_value >> 8);
913    }
914  else
915    {
916      usb_err("%{public}s: other prop", __func__);
917      return -1;
918    }
919  return 0;
920}
921
922static int fconfig_change_dev_desc_info(struct fconfig_softc *cdev, void *user_data)
923{
924  struct gadget_info *gi = NULL;
925  struct fconfig_dev_desc_info desc_info;
926  int ret;
927
928  ret = memcpy_s(&desc_info, sizeof(desc_info), (void *)user_data, sizeof(desc_info));
929  if (ret != EOK)
930    {
931      usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
932      return -1;
933    }
934
935  gi = gadget_find_by_name(cdev, &desc_info.gadget_name);
936  if (gi == NULL)
937    {
938      usb_err("%s: can't find the gadget\n", __FUNCTION__);
939      return -1;
940    }
941  if (gi->dev_desc == NULL)
942    {
943      usb_err("%s: dev_desc is null\n", __FUNCTION__);
944      return -1;
945    }
946  ret = change_dev_descritor_info(gi, &desc_info);
947  if (ret != EOK)
948    {
949      usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
950      return -1;
951    }
952  return 0;
953}
954
955static int change_dev_descritor_string(struct gadget_info *gi,
956                                       struct fconfig_dev_desc_string *desc_string,
957                                       struct gadget_strings *dev_strings)
958{
959  uint8_t id = 0xff;
960  int i;
961  const char *name = NULL;
962
963  if (desc_string == NULL || gi == NULL || dev_strings == NULL)
964    {
965      usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
966      return -1;
967    }
968  for (i = 0; dev_strings->strings[i].s != NULL; i++)
969    {
970      const char *str = dev_strings->strings[i].s;
971      if (strcmp(str, desc_string->prop.prop_value) == 0)
972        {
973          id = dev_strings->strings[i].id;
974          break;
975        }
976    }
977  if (id == 0xff)
978    {
979      usb_err("%s: not found ringht string ID\n", __FUNCTION__);
980      return -1;
981    }
982  name = desc_string->prop.prop_name;
983  if (strcmp(USBDEV_MANUFACTURER, name) == 0)
984    {
985      gi->dev_desc->iManufacturer = id;
986    }
987  else if (strcmp(USBDEV_PRODUCT, name) == 0)
988    {
989      gi->dev_desc->iProduct = id;
990    }
991  else if (strcmp(USBDEV_SERIALNUM, name) == 0)
992    {
993      gi->dev_desc->iSerialNumber = id;
994    }
995  else
996    {
997      usb_err("%{public}s: other prop", __func__);
998      return -1;
999    }
1000  return 0;
1001}
1002
1003static int fconfig_change_dev_desc_string(struct fconfig_softc *cdev, void *user_data)
1004{
1005  struct usb_obj *obj = NULL;
1006  struct gadget_info *gi = NULL;
1007  struct fconfig_dev_desc_string desc_string;
1008  struct gadget_strings *dev_strings = NULL;
1009  int ret;
1010
1011  ret = memcpy_s(&desc_string, sizeof(desc_string), (void *)user_data, sizeof(desc_string));
1012  if (ret != EOK)
1013    {
1014      usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
1015      return -1;
1016    }
1017
1018  gi = gadget_find_by_name(cdev, &desc_string.gadget_name);
1019  if (gi == NULL)
1020    {
1021      usb_err("%s: can't find the gadget\n", __FUNCTION__);
1022      return -1;
1023    }
1024  if (gi->dev_desc == NULL)
1025    {
1026      usb_err("%s: dev_desc is null\n", __FUNCTION__);
1027      return -1;
1028    }
1029
1030  obj = usbobj_find(&gi->strings, gadget_strings_match, &desc_string.prop.lang);
1031  if (!obj)
1032    {
1033      usb_err("%s: can not find language = 0x%x strings\n", __func__, desc_string.prop.lang);
1034      return -1;
1035    }
1036  dev_strings = container_of(obj, struct gadget_strings, obj);
1037
1038  ret = change_dev_descritor_string(gi, &desc_string, dev_strings);
1039  if (ret != EOK)
1040    {
1041      usb_err("%s: copy config descs from user failed\n", __FUNCTION__);
1042      return -1;
1043    }
1044  return 0;
1045}
1046
1047int fconfig_handle_open(struct usb_handle *handle)
1048{
1049  struct fconfig_softc *cdev = (struct fconfig_softc *)(handle->priv);
1050
1051
1052  if (cdev == NULL)
1053    {
1054      usb_err("Invalid private parameter!\n");
1055      return -1;
1056    }
1057
1058  usbobj_get(&cdev->obj);
1059  return 0;
1060}
1061
1062int fconfig_handle_close(struct usb_handle *handle)
1063{
1064  struct fconfig_softc *cdev = (struct fconfig_softc *)(handle->priv);
1065
1066  if (cdev == NULL)
1067    {
1068      usb_err("Invalid private parameter!\n");
1069      return -1;
1070    }
1071
1072  usbobj_put(&cdev->obj);
1073  return 0;
1074}
1075
1076int fconfig_handle_read(struct usb_handle *handle, void *buffer, size_t len)
1077{
1078  struct fconfig_softc *cdev = (struct fconfig_softc *)(handle->priv);
1079
1080  if (len == 0)
1081    {
1082      usb_err("buflen is 0!\n");
1083      return -1;
1084    }
1085
1086  if (cdev == NULL)
1087    {
1088      usb_err("Invalid private parameter!\n");
1089      return -1;
1090    }
1091
1092  return 0;
1093}
1094
1095int fconfig_handle_write(struct usb_handle *handle, void *buffer, size_t len)
1096{
1097  struct fconfig_softc *cdev = (struct fconfig_softc *)(handle->priv);
1098
1099  if (len == 0)
1100    {
1101      usb_err("buflen is 0!\n");
1102      return -1;
1103    }
1104
1105  if (cdev == NULL)
1106    {
1107      usb_err("Invalid private parameter!\n");
1108      return -1;
1109    }
1110
1111  return 0;
1112}
1113
1114int fconfig_handle_ioctl(struct usb_handle *handle, int cmd, void *arg)
1115{
1116  struct fconfig_softc *cdev = (struct fconfig_softc *)(handle->priv);
1117  void *argp = (void *)arg;
1118  int ret = -1;
1119
1120  if (cdev == NULL || argp == NULL)
1121    {
1122      usb_err("Invalid private parameter!\n");
1123      return -ENODEV;
1124    }
1125
1126  switch (cmd)
1127    {
1128    case FCONFIG_CMD_MAKE_GADGET:
1129	  ret = fconfig_make_gadget(cdev, argp);
1130	  break;
1131
1132    case FCONFIG_CMD_DROP_GADGET:
1133      ret = fconfig_drop_gadget(cdev, argp);
1134      break;
1135
1136    case FCONFIG_CMD_WRITE_DEV_DESC:
1137      ret = fconfig_write_dev_desc(cdev, argp);
1138      break;
1139
1140    case FCONFIG_CMD_ADD_CONFIG:
1141      ret = fconfig_add_gadget_cfg(cdev, argp);
1142      break;
1143
1144    case FCONFIG_CMD_REMOVE_CONFIG:
1145      ret = fconfig_remove_gadget_cfg(cdev, argp);
1146      break;
1147
1148    case FCONFIG_CMD_WRITE_STRINGS:
1149      ret = fconfig_write_strings(cdev, argp);
1150      break;
1151
1152    case FCONFIG_CMD_MAKE_FUNCTION:
1153      ret = fconfig_make_function(cdev, argp);
1154      break;
1155
1156    case FCONFIG_CMD_DROP_FUNCTION:
1157      ret = fconfig_drop_function(cdev, argp);
1158      break;
1159
1160    case FCONFIG_CMD_ENABLE_UDC:
1161      ret = fconfig_enable_udc(cdev, argp);
1162      break;
1163
1164    case FCONFIG_CMD_DISABLE_UDC:
1165      ret = fconfig_disable_udc(cdev, argp);
1166      break;
1167    case FCONFIG_CMD_CHAGE_DEVINFO:
1168      ret = fconfig_change_dev_desc_info(cdev, argp);
1169      break;
1170    case FCONFIG_CMD_CHAGE_DEVSTRING:
1171      ret = fconfig_change_dev_desc_string(cdev, argp);
1172      break;
1173    default:
1174      usb_err("the ioctl %d is not supported\n", cmd);
1175      break;
1176    }
1177
1178  return ret;
1179}
1180
1181static struct UsbHandleOps g_fconfig_handle_fops =
1182{
1183  .open   = fconfig_handle_open,
1184  .close  = fconfig_handle_close,
1185  .read   = fconfig_handle_read,
1186  .write  = fconfig_handle_write,
1187  .ioctl  = fconfig_handle_ioctl,
1188};
1189
1190int fconfig_fops_init(struct fconfig_softc *cdev)
1191{
1192  int ret;
1193  char *devName = NULL;
1194
1195  if (cdev == NULL)
1196    {
1197      usb_err("%s: cdev is NULL\n", __FUNCTION__);
1198      return -1;
1199    }
1200
1201  devName = usbm_malloc(&cdev->obj, strlen(USB_FCONFIG_DEV) + 1);
1202  if (!devName)
1203    {
1204      return -1;
1205    }
1206  ret = snprintf_s(devName, strlen(USB_FCONFIG_DEV) + 1, strlen(USB_FCONFIG_DEV),
1207                   "%s", USB_FCONFIG_DEV);
1208    if (ret < 0)
1209      {
1210        goto free_devname;
1211      }
1212  ret = register_handle(devName, &g_fconfig_handle_fops, cdev, &cdev->obj);
1213  if (ret != OK)
1214    {
1215      usb_err("%s: fconfig device register failed!\n", __FUNCTION__);
1216      goto free_devname;
1217    }
1218
1219  return 0;
1220
1221free_devname:
1222  usbm_free(&cdev->obj, devName);
1223  return ret;
1224}
1225
1226int fconfig_fops_deinit(const struct fconfig_softc *cdev)
1227{
1228  int ret;
1229
1230  if (cdev == NULL)
1231    {
1232      usb_err("%s: cdev is NULL\n", __FUNCTION__);
1233      return -1;
1234    }
1235  ret = unregister_handle(USB_FCONFIG_DEV);
1236  if (ret != OK)
1237    {
1238      usb_err("%s: fconfig device unregister failed!\n", __FUNCTION__);
1239    }
1240
1241  return ret;
1242}
1243
1244#ifdef __cplusplus
1245#if __cplusplus
1246//}
1247#endif /* __cplusplus */
1248#endif /* __cplusplus */
1249