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