Add implementation of usb_client HAL using libusbgx
[platform/adaptation/samsung_exynos/device-manager-plugin-odroid.git] / hw / usb_client / usb_client_configfs.c
1 /*
2  * device-node
3  *
4  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <hw/usb_client.h>
20
21 #include "../shared.h"
22
23 #include <limits.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <usbg/usbg.h>
27
28 #define zalloc(amount) calloc(1, amount)
29
30 #define MAX_GADGET_STR_LEN 256
31 #define MAX_FUNCS 32
32
33 #define CONFIGFS_PATH "/sys/kernel/config"
34
35 #define CONFIGFS_GADGET_NAME "hal-gadget"
36 #define CONFIGFS_CONFIG_LABEL "hal-config"
37
38 struct cfs_client {
39         struct usb_client client;
40         usbg_state *ctx;
41         usbg_gadget *gadget;
42         usbg_udc *udc;
43 };
44
45 /* Based on values in slp-gadget kernel module */
46 struct usbg_gadget_attrs default_g_attrs = {
47         .bcdUSB = 0x0200,
48         .idVendor = 0x04e8,
49         .idProduct = 0x6860,
50         .bcdDevice = 0x0100,
51 };
52
53 struct usbg_gadget_strs default_g_strs = {
54         .manufacturer = "Samsung",
55         .product = "TIZEN",
56         .serial = "01234TEST",
57 };
58
59 static void cfs_free_config(struct usb_configuration *config)
60 {
61         int i;
62
63         if (!config)
64                 return;
65
66         if (config->strs) {
67                 for (i = 0; config->strs[i].lang_code; ++i)
68                         free(config->strs[i].config_str);
69
70                 free(config->strs);
71         }
72
73         /*
74          * Each function will be free later,
75          * for now we cleanup only pointers.
76          */
77         if (config->funcs)
78                 free(config->funcs);
79
80         free(config);
81 }
82
83 static void cfs_free_gadget(struct usb_gadget *gadget)
84 {
85         int i;
86
87         if (!gadget)
88                 return;
89
90         if (gadget->strs) {
91                 for (i = 0; gadget->strs[i].lang_code; ++i) {
92                         free(gadget->strs[i].manufacturer);
93                         free(gadget->strs[i].product);
94                         free(gadget->strs[i].serial);
95                 }
96                 free(gadget->strs);
97         }
98
99         if (gadget->configs) {
100                 for (i = 0; gadget->configs[i]; ++i)
101                         cfs_free_config(gadget->configs[i]);
102
103                 free(gadget->configs);
104         }
105
106         if (gadget->funcs) {
107                 for (i = 0; gadget->funcs[i]; ++i)
108                         gadget->funcs[i]->free_func(gadget->funcs[i]);
109
110                 free(gadget->funcs);
111         }
112 }
113
114 static int cfs_read_gadget_attrs_strs(usbg_gadget *gadget,
115                                       struct usb_gadget *usb_gadget)
116 {
117         struct usbg_gadget_attrs attrs;
118         struct usbg_gadget_strs strs;
119         int ret;
120
121         ret = usbg_get_gadget_attrs(gadget, &attrs);
122         if (ret)
123                 goto out;
124
125         usb_gadget->attrs.bDeviceClass = attrs.bDeviceClass;
126         usb_gadget->attrs.bDeviceSubClass = attrs.bDeviceSubClass;
127         usb_gadget->attrs.bDeviceProtocol = attrs.bDeviceProtocol;
128         usb_gadget->attrs.idVendor = attrs.idVendor;
129         usb_gadget->attrs.idProduct = attrs.idProduct;
130         usb_gadget->attrs.bcdDevice = attrs.bcdDevice;
131
132
133         ret = usbg_get_gadget_strs(gadget, LANG_US_ENG, &strs);
134         if (ret)
135                 goto out;
136
137         usb_gadget->strs[0].manufacturer = strdup(strs.manufacturer);
138         usb_gadget->strs[0].product = strdup(strs.product);
139         usb_gadget->strs[0].serial = strdup(strs.serial);
140
141         if (!usb_gadget->strs[0].manufacturer ||
142             !usb_gadget->strs[0].product ||
143             !usb_gadget->strs[0].serial) {
144                 ret = -ENOMEM;
145                 goto err_strs;
146         }
147
148         return 0;
149 err_strs:
150         free(usb_gadget->strs[0].manufacturer);
151         free(usb_gadget->strs[0].product);
152         free(usb_gadget->strs[0].serial);
153 out:
154         return ret;
155 }
156
157 static int cfs_find_func(const char *name, const char *instance)
158 {
159         int i;
160
161         for (i = 0; i < ARRAY_SIZE(_available_funcs); ++i)
162                 if (!strcmp(name, _available_funcs[i]->name) &&
163                     !strcmp(instance, _available_funcs[i]->instance))
164                         return i;
165
166         return -ENOENT;
167 }
168
169 static int cfs_alloc_new_func(struct usb_gadget *gadget, const char *fname,
170                               const char *instance, struct usb_function **_func)
171 {
172         struct usb_function *func;
173         int ret;
174
175         ret = cfs_find_func(fname, instance);
176         if (ret < 0)
177                 return -ENOTSUP;
178
179         ret = _available_funcs[ret]->clone(_available_funcs[ret], &func);
180         if (ret)
181                 return ret;
182
183         *_func = func;
184         return 0;
185 }
186
187 static int cfs_read_funcs(usbg_gadget *gadget, struct usb_gadget *usb_gadget)
188 {
189         usbg_function *func;
190         int i;
191         int ret;
192
193         i = 0;
194         usbg_for_each_function(func, gadget) {
195                 char *func_name = (char *)usbg_get_function_type_str(
196                                             usbg_get_function_type(func));
197                 char *instance = (char *)usbg_get_function_instance(func);
198
199                 ret = cfs_alloc_new_func(usb_gadget, func_name, instance,
200                                          usb_gadget->funcs + i);
201                 if (ret < 0)
202                         goto clean_prev;
203                 ++i;
204         }
205
206         return 0;
207 clean_prev:
208         while (i >= 0) {
209                 usb_gadget->funcs[i]->free_func(usb_gadget->funcs[i]);
210                 --i;
211         }
212
213         return ret;
214 }
215
216 static struct usb_function *cfs_find_func_in_gadget(
217         struct usb_gadget *gadget, const char *name, const char *instance)
218 {
219         int i;
220
221         for (i = 0; gadget->funcs[i]; ++i)
222                 if (!strcmp(name, gadget->funcs[i]->name)
223                     && !strcmp(instance, gadget->funcs[i]->instance))
224                         return gadget->funcs[i];
225         return NULL;
226 }
227
228 static int cfs_alloc_config(int n_funcs, struct usb_configuration **_config)
229 {
230         struct usb_configuration *config;
231
232         config = zalloc(sizeof(*config));
233         if (!config)
234                 goto out;
235
236         config->strs = calloc(2, sizeof(*config->strs));
237         if (!config->strs)
238                 goto free_config;
239
240         config->funcs = calloc(n_funcs + 1, sizeof(*config->funcs));
241         if (!config->funcs)
242                 goto free_strs;
243
244         *_config = config;
245
246         return 0;
247 free_strs:
248         free(config->strs);
249 free_config:
250         free(config);
251 out:
252         return -ENOMEM;
253 }
254
255 static int cfs_read_config(usbg_config *config, struct usb_gadget *gadget,
256                            struct usb_configuration *usb_config)
257 {
258         usbg_binding *b;
259         usbg_function *func;
260         char *name, *instance;
261         struct usbg_config_attrs c_attrs;
262         struct usbg_config_strs c_strs;
263         int i = 0;
264         int ret;
265
266         usbg_for_each_binding(b, config) {
267                 func = usbg_get_binding_target(b);
268
269                 name = (char *)usbg_get_function_type_str(
270                         usbg_get_function_type(func));
271                 instance = (char *)usbg_get_function_instance(func);
272
273                 usb_config->funcs[i] = cfs_find_func_in_gadget(gadget,
274                                                                name, instance);
275                 if (!usb_config->funcs[i]) {
276                         return -ENOTSUP;
277                 }
278                 ++i;
279         }
280
281         ret = usbg_get_config_attrs(config, &c_attrs);
282         if (ret)
283                 return ret;
284
285         usb_config->attrs.MaxPower = c_attrs.bMaxPower*2;
286         usb_config->attrs.bmAttributs = c_attrs.bmAttributes;
287
288         ret = usbg_get_config_strs(config, LANG_US_ENG, &c_strs);
289         if (ret) {
290                 usb_config->strs[0].lang_code = 0;
291         } else {
292                 usb_config->strs[0].lang_code = LANG_US_ENG;
293                 usb_config->strs[0].config_str = strdup(c_strs.configuration);
294                 if (!usb_config->strs[0].config_str)
295                         return -ENOMEM;
296         }
297
298         return 0;
299 }
300
301 static int cfs_count_bindings(usbg_config *config)
302 {
303         usbg_binding *b;
304         int i = 0;
305
306         usbg_for_each_binding(b, config) ++i;
307
308         return i;
309 }
310
311 static int cfs_read_configs(usbg_gadget *gadget, struct usb_gadget *usb_gadget)
312 {
313         usbg_config *config;
314         int i;
315         int n_funcs;
316         int ret;
317
318         usbg_for_each_config(config, gadget) {
319                 n_funcs = cfs_count_bindings(config);
320
321                 ret = cfs_alloc_config(n_funcs, usb_gadget->configs + i);
322                 if (ret)
323                         goto clean_prev;
324                 ret = cfs_read_config(config, usb_gadget,
325                                       usb_gadget->configs[i]);
326                 if (ret)
327                         goto free_current;
328
329                 ++i;
330         }
331
332         return 0;
333 free_current:
334         free(usb_gadget->configs[i]->strs);
335         free(usb_gadget->configs[i]->funcs);
336         free(usb_gadget->configs[i]);
337 clean_prev:
338         while (i >= 0)
339                 cfs_free_config(usb_gadget->configs[i]);
340         return ret;
341 }
342
343 static int cfs_count_configs(usbg_gadget *gadget)
344 {
345         usbg_config *config;
346         int i = 0;
347
348         usbg_for_each_config(config, gadget) ++i;
349
350         return i;
351 }
352
353 static int cfs_count_functions(usbg_gadget *gadget)
354 {
355         usbg_function *func;
356         int i = 0;
357
358         usbg_for_each_function(func, gadget) ++i;
359
360         return i;
361 }
362
363 static int cfs_get_current_gadget(struct usb_client *usb,
364                                      struct usb_gadget **_usb_gadget)
365 {
366         struct cfs_client *cfs_client;
367         struct usb_gadget *usb_gadget;
368         struct usb_gadget_strings *strs;
369         struct usb_configuration **usb_configs;
370         struct usb_function **usb_funcs;
371         int n_funcs, n_configs;
372         int i;
373         int ret = -ENOMEM;
374
375         if (!usb)
376                 return -EINVAL;
377
378         cfs_client = container_of(usb, struct cfs_client,
379                                   client);
380
381         usb_gadget = zalloc(sizeof(*usb_gadget));
382         if (!usb_gadget)
383                 goto out;
384
385         /*
386          * Currently there is no interface in libusbg which
387          * allows to list all string languages.
388          * That's why we do this only for USA english
389          */
390         strs = calloc(2, sizeof(*strs));
391         if (!strs)
392                 goto free_gadget;
393
394         strs[0].lang_code = LANG_US_ENG;
395
396         usb_gadget->strs = strs;
397
398         ret = cfs_read_gadget_attrs_strs(cfs_client->gadget, usb_gadget);
399         if (ret)
400                 goto free_strs;
401
402
403         n_funcs = cfs_count_functions(cfs_client->gadget);
404         usb_funcs = calloc(n_funcs + 1, sizeof(*usb_funcs));
405         if (!usb_funcs)
406                 goto free_strs_with_content;
407
408         usb_gadget->funcs = usb_funcs;
409
410         ret = cfs_read_funcs(cfs_client->gadget, usb_gadget);
411         if (ret)
412                 goto free_funcs;
413
414         n_configs = cfs_count_configs(cfs_client->gadget);
415         usb_configs = calloc(n_configs + 1, sizeof(*usb_configs));
416         if (!usb_configs)
417                 goto free_funcs_with_content;
418
419         usb_gadget->configs = usb_configs;
420
421         ret = cfs_read_configs(cfs_client->gadget, usb_gadget);
422         if (ret)
423                 goto free_configs;
424
425         *_usb_gadget = usb_gadget;
426         return 0;
427
428 free_configs:
429         free(usb_configs);
430 free_funcs_with_content:
431         for (i = 0; usb_gadget->funcs[i]; ++i)
432                 usb_gadget->funcs[i]->free_func(usb_gadget->funcs[i]);
433 free_funcs:
434         free(usb_funcs);
435 free_strs_with_content:
436         for (i = 0; usb_gadget->strs[i].lang_code; ++i) {
437                 free(usb_gadget->strs[0].manufacturer);
438                 free(usb_gadget->strs[0].product);
439                 free(usb_gadget->strs[0].serial);
440         }
441 free_strs:
442         free(usb_gadget->strs);
443 free_gadget:
444         free(usb_gadget);
445 out:
446         return ret;
447 }
448
449 static bool cfs_is_function_supported(struct usb_client *usb,
450                                          struct usb_function *func)
451 {
452         int ret;
453
454         /* for now only simple functions without userspace service */
455         if (func->function_group != USB_FUNCTION_GROUP_SIMPLE)
456                 return false;
457
458         /*
459          * TODO
460          * Instead of only checking whether we know this function
461          * we should also somehow check that it's realy available
462          * in our kernel.
463          */
464         ret = usbg_lookup_function_type(func->name);
465
466         return ret > 0;
467 }
468
469 static bool cfs_is_gadget_supported(struct usb_client *usb,
470                                        struct usb_gadget *gadget)
471 {
472         int i, j;
473
474         if (!gadget || !gadget->configs || !gadget->funcs)
475                 return false;
476
477         /*
478          * TODO
479          * Here is a good place to ensure that serial is immutable
480          */
481
482         /* No real restrictions for strings */
483         for (j = 0; gadget->configs && gadget->configs[j]; ++j) {
484                 struct usb_configuration *config = gadget->configs[j];
485
486                 if (!config->funcs)
487                         return false;
488
489                 for (i = 0; config->funcs[i]; ++i)
490                         if (!cfs_is_function_supported(usb, config->funcs[i]))
491                                 return false;
492         }
493
494         if (j == 0)
495                 return false;
496
497         return true;
498 }
499
500 static int cfs_set_gadget_attrs(struct cfs_client *cfs_client,
501                                 struct usb_gadget_attrs *attrs)
502 {
503         int ret;
504         struct usbg_gadget_attrs gadget_attrs;
505
506         ret = usbg_get_gadget_attrs(cfs_client->gadget, &gadget_attrs);
507         if (ret)
508                 return ret;
509
510         gadget_attrs.bDeviceClass = attrs->bDeviceClass;
511         gadget_attrs.bDeviceSubClass = attrs->bDeviceSubClass;
512         gadget_attrs.bDeviceProtocol = attrs->bDeviceProtocol;
513         gadget_attrs.idVendor = attrs->idVendor;
514         gadget_attrs.idProduct = attrs->idProduct;
515         gadget_attrs.bcdDevice = attrs->bcdDevice;
516
517         ret = usbg_set_gadget_attrs(cfs_client->gadget, &gadget_attrs);
518
519         return ret;
520 }
521
522 static int cfs_set_gadget_strs(struct cfs_client *cfs_client,
523                                   struct usb_gadget_strings *strs)
524 {
525         int ret = 0;
526
527         /*
528          * TODO
529          * Here is a good place to ensure that serial is immutable
530          */
531 #define SET_STR(FIELD, STR_ID)                          \
532         if (strs->FIELD) {                              \
533                 ret = usbg_set_gadget_str(cfs_client->gadget,   \
534                                           STR_ID,               \
535                                           strs->lang_code,      \
536                                           strs->FIELD);         \
537                 if (ret)                                        \
538                         return ret;                             \
539         }
540
541         SET_STR(manufacturer, USBG_STR_MANUFACTURER);
542         SET_STR(product, USBG_STR_PRODUCT);
543         SET_STR(serial, USBG_STR_SERIAL_NUMBER);
544 #undef SET_STR
545         return ret;
546 }
547
548 static int cfs_set_gadget_config(struct cfs_client *cfs_client,
549                                     int config_id,
550                                     struct usb_configuration *usb_config)
551 {
552         struct usbg_config_attrs cattrs = {
553                 .bmAttributes = usb_config->attrs.bmAttributs,
554                 .bMaxPower = usb_config->attrs.MaxPower/2,
555         };
556         usbg_config *config;
557         int i;
558         int ret;
559
560         if (!usb_config->funcs || !usb_config->funcs[0])
561                 return -EINVAL;
562
563         config = usbg_get_config(cfs_client->gadget, config_id, NULL);
564         if (config) {
565                 ret = usbg_rm_config(config, USBG_RM_RECURSE);
566                 if (ret)
567                         return ret;
568         }
569
570         ret = usbg_create_config(cfs_client->gadget, config_id,
571                                  CONFIGFS_CONFIG_LABEL, &cattrs, NULL, &config);
572         if (ret)
573                 return ret;
574
575         for (i = 0; usb_config->strs && usb_config->strs[i].lang_code; ++i) {
576                 ret = usbg_set_config_string(config, usb_config->strs[i].lang_code,
577                                              usb_config->strs[i].config_str);
578                 if (ret)
579                         return ret;
580         }
581
582         for (i = 0; usb_config->funcs && usb_config->funcs[i]; ++i) {
583                 struct usb_function *usb_func = usb_config->funcs[i];
584                 int type = usbg_lookup_function_type(usb_func->name);
585                 usbg_function *func;
586
587                 func = usbg_get_function(cfs_client->gadget,
588                                          type, usb_func->instance);
589                 if (!func) {
590                         ret = usbg_create_function(cfs_client->gadget,
591                                                    type,
592                                                    usb_func->instance,
593                                                    NULL, &func);
594                         if (ret)
595                                 return ret;
596                 }
597
598                 ret = usbg_add_config_function(config, NULL, func);
599                 if (ret)
600                         return ret;
601         }
602
603         return ret;
604 }
605
606 static int cfs_cleanup_left_configs(struct cfs_client *cfs_client,
607                                     int last_config)
608 {
609         usbg_config *lconfig, *config;
610         int ret;
611
612         lconfig = usbg_get_config(cfs_client->gadget, last_config, NULL);
613         for (config = usbg_get_next_config(lconfig);
614              config;
615              config = usbg_get_next_config(lconfig)) {
616                 ret = usbg_rm_config(config, USBG_RM_RECURSE);
617                 if (ret)
618                         return ret;
619         }
620
621         return 0;
622 }
623
624 static int cfs_reconfigure_gadget(struct usb_client *usb,
625                                   struct usb_gadget *gadget)
626 {
627         struct cfs_client *cfs_client;
628         int i;
629         int ret;
630
631         if (!usb)
632                 return -EINVAL;
633
634         cfs_client = container_of(usb, struct cfs_client,
635                                   client);
636
637         if (!usb || !gadget || !cfs_is_gadget_supported(usb, gadget))
638                 return -EINVAL;
639
640         ret = cfs_set_gadget_attrs(cfs_client, &gadget->attrs);
641         if (ret)
642                 goto out;
643
644         for (i = 0; gadget->strs && gadget->strs[i].lang_code > 0; ++i) {
645                 ret = cfs_set_gadget_strs(cfs_client, gadget->strs + i);
646                 if (ret)
647                         goto out;
648         }
649
650         for (i = 0; gadget->configs && gadget->configs[i]; ++i) {
651                 ret = cfs_set_gadget_config(cfs_client, i + 1,
652                                             gadget->configs[i]);
653                 if (ret)
654                         goto out;
655         }
656
657         ret = cfs_cleanup_left_configs(cfs_client, i);
658
659         /* TODO
660          * Cleanup things which are left after previous gadget
661          */
662 out:
663         return ret;
664 }
665
666 static int cfs_enable(struct usb_client *usb)
667 {
668         struct cfs_client *cfs_client;
669
670         if (!usb)
671                 return -EINVAL;
672
673         cfs_client = container_of(usb, struct cfs_client,
674                                   client);
675
676         return usbg_enable_gadget(cfs_client->gadget, cfs_client->udc);
677 }
678
679 static int cfs_disable(struct usb_client *usb)
680 {
681         struct cfs_client *cfs_client;
682
683         if (!usb)
684                 return -EINVAL;
685
686         cfs_client = container_of(usb, struct cfs_client,
687                                   client);
688
689         return usbg_disable_gadget(cfs_client->gadget);
690 }
691
692 static int cfs_gadget_open(struct hw_info *info,
693                 const char *id, struct hw_common **common)
694 {
695         struct cfs_client *cfs_client;
696         int ret;
697
698         if (!info || !common)
699                 return -EINVAL;
700
701         cfs_client = zalloc(sizeof(*cfs_client));
702         if (!cfs_client)
703                 return -ENOMEM;
704
705         ret = usbg_init(CONFIGFS_PATH, &cfs_client->ctx);
706         if (ret)
707                 goto err_usbg_init;
708
709         cfs_client->udc = usbg_get_first_udc(cfs_client->ctx);
710         if (!cfs_client->udc) {
711                 ret = -ENODEV;
712                 goto err_no_udc;
713         }
714
715         ret = usbg_create_gadget(cfs_client->ctx, CONFIGFS_GADGET_NAME,
716                                  &default_g_attrs, &default_g_strs,
717                                  &cfs_client->gadget);
718         if (ret)
719                 goto err_create_gadget;
720
721         cfs_client->client.common.info = info;
722         cfs_client->client.get_current_gadget = cfs_get_current_gadget;
723         cfs_client->client.reconfigure_gadget = cfs_reconfigure_gadget;
724         cfs_client->client.is_gadget_supported = cfs_is_gadget_supported;
725         cfs_client->client.is_function_supported = cfs_is_function_supported;
726         cfs_client->client.enable = cfs_enable;
727         cfs_client->client.disable = cfs_disable;
728         cfs_client->client.free_gadget = cfs_free_gadget;
729
730         *common = &cfs_client->client.common;
731         return 0;
732
733 err_create_gadget:
734 err_no_udc:
735         usbg_cleanup(cfs_client->ctx);
736 err_usbg_init:
737         free(cfs_client);
738
739         return ret;
740 }
741
742 static int cfs_gadget_close(struct hw_common *common)
743 {
744         struct cfs_client *cfs_client;
745
746         if (!common)
747                 return -EINVAL;
748
749         cfs_client = container_of(common, struct cfs_client,
750                                   client.common);
751
752         /*
753          * For now we don't check for errors
754          * but we should somehow handle them
755          */
756         usbg_rm_gadget(cfs_client->gadget, USBG_RM_RECURSE);
757         usbg_cleanup(cfs_client->ctx);
758         free(cfs_client);
759
760         return 0;
761 }
762
763 HARDWARE_MODULE_STRUCTURE = {
764         .magic = HARDWARE_INFO_TAG,
765         .hal_version = HARDWARE_INFO_VERSION,
766         .device_version = USB_CLIENT_HARDWARE_DEVICE_VERSION,
767         .id = USB_CLIENT_HARDWARE_DEVICE_ID,
768         .name = "cfs-gadget",
769         .open = cfs_gadget_open,
770         .close = cfs_gadget_close,
771 };