Extend USB gadget configuration for usb debug mode.
[platform/core/system/libdevice-node.git] / hw / usb_gadget_common.c
1 /*
2  * libdevice-node
3  *
4  * Copyright (c) 2018 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_gadget.h>
20 #include <hw/board.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <string.h>
26
27 #include <libsyscommon/dbus-systemd.h>
28
29 #define zalloc(amount) calloc(1, amount)
30
31 /* Based on slp-gadget and initial version of USB HAL by Taeyoung Kim */
32 #define DEFAULT_VID 0x04e8
33 #define DEFAULT_PID 0x6860
34 #define DEFAULT_BCD_DEVICE 0x0100
35
36 #define DEFAULT_LANG 0x409 /* US_en */
37 #define DEFAULT_MANUFACTURER "Samsung"
38 #define DEFAULT_PRODUCT "TIZEN"
39 #define DEFAULT_SERIAL "01234TEST"
40
41 #define DEFAULT_BMATTRIBUTES ((1 << 7) | (1 << 6))
42 #define DEFAULT_MAX_POWER 500
43
44 #ifndef EXPORT
45 #define EXPORT  __attribute__ ((visibility("default")))
46 #endif
47
48 static void simple_cleanup_config(struct usb_configuration *config)
49 {
50         int i;
51
52         if (!config)
53                 return;
54
55         if (config->strs) {
56                 for (i = 0; config->strs[i].lang_code; ++i)
57                         free(config->strs[i].config_str);
58
59                 free(config->strs);
60         }
61
62         /*
63          * Each function will be free later,
64          * for now we cleanup only pointers.
65          */
66         if (config->funcs)
67                 free(config->funcs);
68
69         free(config);
70 }
71
72 static void simple_cleanup_gadget(struct usb_gadget *gadget)
73 {
74         int i;
75
76         if (!gadget)
77                 return;
78
79         if (gadget->strs) {
80                 for (i = 0; gadget->strs[i].lang_code; ++i) {
81                         free(gadget->strs[i].manufacturer);
82                         free(gadget->strs[i].product);
83                         free(gadget->strs[i].serial);
84                 }
85                 free(gadget->strs);
86         }
87
88         if (gadget->configs) {
89                 for (i = 0; gadget->configs[i]; ++i)
90                         simple_cleanup_config(gadget->configs[i]);
91
92                 free(gadget->configs);
93         }
94
95         if (gadget->funcs) {
96                 for (i = 0; gadget->funcs[i]; ++i)
97                         gadget->funcs[i]->free_func(gadget->funcs[i]);
98
99                 free(gadget->funcs);
100         }
101
102         free(gadget);
103 }
104
105 static int alloc_default_config(struct usb_configuration **_config)
106 {
107         struct usb_configuration *config;
108
109         config = zalloc(sizeof(*config));
110         if (!config)
111                 goto out;
112
113         config->strs = calloc(1, sizeof(*config->strs));
114         if (!config->strs)
115                 goto free_config;
116
117         config->attrs.bmAttributs = DEFAULT_BMATTRIBUTES;
118         config->attrs.MaxPower = DEFAULT_MAX_POWER;
119
120         *_config = config;
121
122         return 0;
123
124 free_config:
125         free(config);
126 out:
127         return -ENOMEM;
128 }
129
130 static int get_device_serial(char **out)
131 {
132         struct hw_info *info;
133         struct hw_common *common;
134         struct hw_board *board;
135         int ret;
136
137         if (hw_get_info(BOARD_HARDWARE_DEVICE_ID, (const struct hw_info **)&info))
138                 return -ENOENT;
139
140         ret = info->open(info, NULL, &common);
141         if (ret < 0)
142                 return ret;
143
144         board = container_of(common, struct hw_board, common);
145         return board->get_device_serial(out);
146 }
147
148 static int alloc_default_gadget(struct usb_gadget **_gadget)
149 {
150         struct usb_gadget *gadget;
151         struct usb_gadget_strings *strs;
152         struct usb_configuration **configs;
153         int ret;
154
155         gadget = zalloc(sizeof(*gadget));
156         if (!gadget)
157                 goto out;
158
159         gadget->attrs.idVendor = DEFAULT_VID;
160         gadget->attrs.idProduct = DEFAULT_PID;
161         gadget->attrs.bcdDevice = DEFAULT_BCD_DEVICE;
162
163         strs = calloc(2, sizeof(*strs));
164         if (!strs)
165                 goto free_gadget;
166
167         strs[0].lang_code = 0x409;
168         strs[0].manufacturer = strdup(DEFAULT_MANUFACTURER);
169         strs[0].product = strdup(DEFAULT_PRODUCT);
170         ret = get_device_serial(&strs[0].serial);
171         if (ret < 0)
172                 strs[0].serial = strdup(DEFAULT_SERIAL);
173
174         if (!strs[0].manufacturer || !strs[0].product || !strs[0].serial)
175                 goto free_strs;
176
177         gadget->strs = strs;
178
179         /* slp-gadget use max 2 confiuration and NULL termination */
180         configs = calloc(3, sizeof(*configs));
181         if (!configs)
182                 goto free_strs;
183
184         gadget->configs = configs;
185         *_gadget = gadget;
186
187         return 0;
188
189 free_strs:
190         free(strs[0].manufacturer);
191         free(strs[0].product);
192         free(strs[0].serial);
193         free(strs);
194 free_gadget:
195         free(gadget);
196 out:
197         return -ENOMEM;
198 }
199
200 static inline struct usb_function *find_func(struct usb_gadget *gadget,
201                                             int func_id)
202 {
203         int i;
204
205         for (i = 0; gadget->funcs[i] && gadget->funcs[i]->id != func_id; ++i);
206
207         return gadget->funcs[i];
208 }
209
210 static int simple_id_to_gadget(struct usb_gadget_id *gadget_id,
211                                struct usb_gadget **_gadget)
212 {
213         struct usb_gadget *gadget;
214         int n_configs = 0;
215         /* zero terminates */
216         int functions[2][sizeof(gadget_id->function_mask)*8];
217         int n_functions;
218         struct usb_function **funcs;
219         int idx, i, j;
220         int ret;
221
222         if (!gadget_id || !_gadget)
223                 return -EINVAL;
224
225         ret = alloc_default_gadget(&gadget);
226         if (ret)
227                 goto out;
228
229         /*
230          * Currently all gadgets use inly single configuration but
231          * slp-gadget is capable to handle two of them
232          *
233          * Order of interfaces in configuration is significant
234          * so in this switch we sort our functions in a correct order
235          */
236         switch (gadget_id->function_mask) {
237         case USB_FUNCTION_SDB:
238                 n_configs = 1;
239                 functions[0][0] = USB_FUNCTION_SDB;
240                 functions[0][1] = 0;
241                 gadget->attrs.idProduct = 0x685d;
242                 break;
243
244         case USB_FUNCTION_MTP:
245                 n_configs = 1;
246                 functions[0][0] = USB_FUNCTION_MTP;
247                 functions[0][1] = 0;
248                 gadget->attrs.idProduct = 0x6860;
249                 break;
250
251         case USB_FUNCTION_RNDIS:
252                 n_configs = 1;
253                 functions[0][0] = USB_FUNCTION_RNDIS;
254                 functions[0][1] = 0;
255                 gadget->attrs.idProduct = 0x6863;
256                 break;
257
258         case USB_FUNCTION_ACM | USB_FUNCTION_SDB:
259                 n_configs = 1;
260                 functions[0][0] = USB_FUNCTION_ACM;
261                 functions[0][1] = USB_FUNCTION_SDB;
262                 functions[0][2] = 0;
263                 gadget->attrs.idProduct = 0x6860;
264                 break;
265
266         case USB_FUNCTION_MTP | USB_FUNCTION_SDB:
267                 n_configs = 1;
268                 functions[0][0] = USB_FUNCTION_MTP;
269                 functions[0][1] = USB_FUNCTION_SDB;
270                 functions[0][2] = 0;
271                 gadget->attrs.idProduct = 0x6860;
272                 break;
273
274         case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB:
275                 n_configs = 1;
276                 functions[0][0] = USB_FUNCTION_MTP;
277                 functions[0][1] = USB_FUNCTION_ACM;
278                 functions[0][2] = USB_FUNCTION_SDB;
279                 functions[0][3] = 0;
280                 gadget->attrs.idProduct = 0x6860;
281                 break;
282
283         case USB_FUNCTION_RNDIS | USB_FUNCTION_SDB:
284                 n_configs = 1;
285                 functions[0][0] = USB_FUNCTION_RNDIS;
286                 functions[0][1] = USB_FUNCTION_SDB;
287                 functions[0][2] = 0;
288                 gadget->attrs.idProduct = 0x6864;
289                 break;
290
291 #if 0
292         case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DIAG:
293                 n_configs = 1;
294                 functions[0][0] = USB_FUNCTION_MTP;
295                 functions[0][1] = USB_FUNCTION_ACM;
296                 functions[0][2] = USB_FUNCTION_SDB;
297                 functions[0][3] = USB_FUNCTION_DIAG;
298                 functions[0][4] = 0;
299                 gadget->attrs.idProduct = 0x6860;
300                 break;
301
302         case USB_FUNCTION_RNDIS | USB_FUNCTION_SDB | USB_FUNCTION_ACM | USB_FUNCTION_DIAG:
303                 n_configs = 1;
304                 functions[0][0] = USB_FUNCTION_RNDIS;
305                 functions[0][1] = USB_FUNCTION_SDB;
306                 functions[0][2] = USB_FUNCTION_ACM;
307                 functions[0][3] = USB_FUNCTION_DIAG;
308                 functions[0][4] = 0;
309                 gadget->attrs.idProduct = 0x6864;
310                 break;
311
312         case USB_FUNCTION_RNDIS | USB_FUNCTION_DIAG:
313                 n_configs = 1;
314                 functions[0][0] = USB_FUNCTION_RNDIS;
315                 functions[0][1] = USB_FUNCTION_DIAG;
316                 functions[0][2] = 0;
317                 gadget->attrs.idProduct = 0x6864;
318                 break;
319 #endif
320
321         case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DM:
322                 n_configs = 1;
323                 functions[0][0] = USB_FUNCTION_ACM;
324                 functions[0][1] = USB_FUNCTION_SDB;
325                 functions[0][2] = USB_FUNCTION_DM;
326                 functions[0][3] = 0;
327                 gadget->attrs.idProduct = 0x6860;
328                 break;
329
330         case USB_FUNCTION_DIAG | USB_FUNCTION_ACM | USB_FUNCTION_RMNET:
331                 n_configs = 1;
332                 functions[0][0] = USB_FUNCTION_DIAG;
333                 functions[0][1] = USB_FUNCTION_ACM;
334                 functions[0][2] = USB_FUNCTION_RMNET;
335                 functions[0][3] = 0;
336                 gadget->attrs.idProduct = 0x685d;
337                 break;
338
339         case USB_FUNCTION_RNDIS | USB_FUNCTION_SDB | USB_FUNCTION_ACM:
340                 n_configs = 1;
341                 functions[0][0] = USB_FUNCTION_RNDIS;
342                 functions[0][1] = USB_FUNCTION_SDB;
343                 functions[0][2] = USB_FUNCTION_ACM;
344                 functions[0][3] = 0;
345                 gadget->attrs.idProduct = 0x6864;
346                 break;
347         };
348
349         if (n_configs > 2 || n_configs <= 0) {
350                 ret = -EINVAL;
351                 goto free_gadget;
352         }
353
354         n_functions = __builtin_popcount(gadget_id->function_mask);
355
356         funcs = calloc(n_functions + 1, sizeof(*funcs));
357         if (!funcs) {
358                 ret = -ENOMEM;
359                 goto free_gadget;
360         }
361
362         gadget->funcs = funcs;
363
364         idx = 0;
365         for (i = 0; _available_funcs[i]; ++i) {
366                 int func_id = 1 << i;
367
368                 if (!(gadget_id->function_mask & func_id))
369                         continue;
370
371                 ret = _available_funcs[i]->clone(_available_funcs[i],
372                         gadget->funcs + idx);
373                 if (ret)
374                         goto free_functions;
375                 ++idx;
376         }
377
378         for (j = 0; j < n_configs; ++j) {
379                 struct usb_configuration *config;
380                 int n_funcs_in_config;
381
382                 for (i = 0; functions[j][i]; ++i);
383                 n_funcs_in_config = i;
384
385                 ret = alloc_default_config(&config);
386                 if (ret)
387                         goto free_configs;
388
389                 gadget->configs[j] = config;
390                 config->funcs = calloc(n_funcs_in_config + 1,
391                                                        sizeof(void *));
392                 if (!config->funcs)
393                         goto free_configs;
394
395                 for (i = 0; functions[j][i]; ++i)
396                         config->funcs[i] = find_func(gadget, functions[j][i]);
397         }
398
399         *_gadget = gadget;
400         return 0;
401 free_configs:
402 free_functions:
403 free_gadget:
404         simple_cleanup_gadget(gadget);
405 out:
406         return ret;
407 }
408
409 void rndis_handler(int enable)
410 {
411         if (enable)
412                 (void)systemd_start_unit_wait_started("rndis.service", NULL, -1);
413         else
414                 (void)systemd_stop_unit_wait_stopped("rndis.service", NULL, -1);
415 }
416
417 static void free_simple_func(struct usb_function *func)
418 {
419         if (func) {
420                 free((void *)func->name);
421                 free((void *)func->instance);
422                 free((void *)func->ffs_service);
423                 free((void *)func->service);
424                 free(func);
425         }
426 }
427
428 static int clone_simple_func(struct usb_function *func,
429                               struct usb_function **clone)
430 {
431         struct usb_function *other;
432
433         if (!func || !clone)
434                 return -EINVAL;
435
436         other = (struct usb_function *)calloc(1, sizeof(struct usb_function));
437         if (!other)
438                 return -ENOMEM;
439
440         *other = *func;
441
442         other->name = strdup(func->name);
443         other->instance = strdup(func->instance);
444         if (!other->name || !other->instance)
445                 goto out_nomem;
446
447         if (func->ffs_service) {
448                 other->ffs_service = strdup(func->ffs_service);
449                 if (!other->ffs_service)
450                         goto out_nomem;
451         }
452
453         if (func->service) {
454                 other->service = strdup(func->service);
455                 if (!other->service)
456                         goto out_nomem;
457         }
458
459         *clone = other;
460         return 0;
461
462 out_nomem:
463         free_simple_func(other);
464         return -ENOMEM;
465 }
466
467 #define DEFINE_USB_FUNCTION(_id, _name, _ffs_service, _service, _handler)       \
468         static struct usb_function _##_name##_function = {                      \
469                 .id = _id,                                                      \
470                 .name = #_name,                                                 \
471                 .instance = "default",                                          \
472                 .ffs_service = _ffs_service,                                    \
473                 .service = _service,                                            \
474                 .handler = _handler,                                            \
475                 .clone = clone_simple_func,                                     \
476                 .free_func = free_simple_func,                                  \
477         }
478
479 DEFINE_USB_FUNCTION(USB_FUNCTION_DIAG,        diag,        NULL, NULL,            NULL);
480 DEFINE_USB_FUNCTION(USB_FUNCTION_RMNET,       rmnet,       NULL, NULL,            NULL);
481 DEFINE_USB_FUNCTION(USB_FUNCTION_DM,          dm,          NULL, NULL,            NULL);
482 DEFINE_USB_FUNCTION(USB_FUNCTION_CONN_GADGET, conn_gadget, NULL, NULL,            NULL);
483 DEFINE_USB_FUNCTION(USB_FUNCTION_SDB,         sdb,         "sdbd", NULL,          NULL);
484 DEFINE_USB_FUNCTION(USB_FUNCTION_MTP,         mtp,         "mtp-responder", NULL, NULL);
485 DEFINE_USB_FUNCTION(USB_FUNCTION_ACM,         acm,         NULL, "data-router",   NULL);
486 DEFINE_USB_FUNCTION(USB_FUNCTION_RNDIS,       rndis,       NULL, "sshd",          rndis_handler);
487 #undef DEFINE_USB_FUNCTION
488
489 /* Caution: index order of arrary is important, because simple_id_to_gadget() uses it. */
490 struct usb_function *_available_funcs[] = {
491         [USB_FUNCTION_IDX_MTP]         = &_mtp_function,
492         [USB_FUNCTION_IDX_ACM]         = &_acm_function,
493         [USB_FUNCTION_IDX_SDB]         = &_sdb_function,
494         [USB_FUNCTION_IDX_RNDIS]       = &_rndis_function,
495         [USB_FUNCTION_IDX_DIAG]        = &_diag_function,
496         [USB_FUNCTION_IDX_CONN_GADGET] = &_conn_gadget_function,
497         [USB_FUNCTION_IDX_DM]          = &_dm_function,
498         [USB_FUNCTION_IDX_RMNET]       = &_rmnet_function,
499         [USB_FUNCTION_IDX_MAX]         = NULL /* An indicator to end the array */
500 };
501
502 EXPORT
503 int simple_translator_open(struct hw_info *info,
504                 const char *id, struct hw_common **common)
505 {
506         struct usb_gadget_translator *simple_translator;
507
508         if (!info || !common)
509                 return -EINVAL;
510
511         simple_translator = zalloc(sizeof(*simple_translator));
512         if (!simple_translator)
513                 return -ENOMEM;
514
515         simple_translator->common.info = info;
516         simple_translator->id_to_gadget = simple_id_to_gadget;
517         simple_translator->cleanup_gadget = simple_cleanup_gadget;
518
519         *common = &simple_translator->common;
520         return 0;
521 }
522
523 EXPORT
524 int simple_translator_close(struct hw_common *common)
525 {
526         struct usb_gadget_translator *simple_translator;
527
528         if (!common)
529                 return -EINVAL;
530
531         simple_translator = container_of(common, struct usb_gadget_translator,
532                                          common);
533
534         free(simple_translator);
535         return 0;
536 }