Delete usb mode not supported by tizen
[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         int ret;
215         int idx, i, j;
216         int n_functions;
217         int n_configs = 0;
218         struct usb_gadget *gadget;
219         struct usb_function **funcs;
220         int functions[2][sizeof(gadget_id->function_mask)*8]; /* zero terminates */
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         /* MTP, ACM, SDB */
238         case USB_FUNCTION_MTP | USB_FUNCTION_ACM:
239                 n_configs = 1;
240                 functions[0][0] = USB_FUNCTION_MTP;
241                 functions[0][1] = USB_FUNCTION_ACM;
242                 functions[0][2] = 0;
243                 gadget->attrs.idProduct = 0x6860;
244                 break;
245
246         case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB:
247                 n_configs = 1;
248                 functions[0][0] = USB_FUNCTION_MTP;
249                 functions[0][1] = USB_FUNCTION_ACM;
250                 functions[0][2] = USB_FUNCTION_SDB;
251                 functions[0][3] = 0;
252                 gadget->attrs.idProduct = 0x6860;
253                 break;
254
255         /* DIAG */
256         case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DIAG:
257                 n_configs = 1;
258                 functions[0][0] = USB_FUNCTION_MTP;
259                 functions[0][1] = USB_FUNCTION_ACM;
260                 functions[0][2] = USB_FUNCTION_SDB;
261                 functions[0][3] = USB_FUNCTION_DIAG;
262                 functions[0][4] = 0;
263                 gadget->attrs.idProduct = 0x6860;
264                 break;
265
266         /* RNDIS */
267         case USB_FUNCTION_RNDIS:
268                 n_configs = 1;
269                 functions[0][0] = USB_FUNCTION_RNDIS;
270                 functions[0][1] = 0;
271                 gadget->attrs.idProduct = 0x6863;
272                 break;
273
274         case USB_FUNCTION_RNDIS | USB_FUNCTION_DIAG:
275                 n_configs = 1;
276                 functions[0][0] = USB_FUNCTION_RNDIS;
277                 functions[0][1] = USB_FUNCTION_DIAG;
278                 functions[0][2] = 0;
279                 gadget->attrs.idProduct = 0x6864;
280                 break;
281
282         case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS:
283                 n_configs = 1;
284                 functions[0][0] = USB_FUNCTION_ACM;
285                 functions[0][1] = USB_FUNCTION_SDB;
286                 functions[0][2] = USB_FUNCTION_RNDIS;
287                 functions[0][3] = 0;
288                 gadget->attrs.idProduct = 0x6864;
289                 break;
290
291         /* RMNET */
292         case USB_FUNCTION_DIAG | USB_FUNCTION_RMNET:
293                 n_configs = 1;
294                 functions[0][0] = USB_FUNCTION_DIAG;
295                 functions[0][1] = USB_FUNCTION_RMNET;
296                 functions[0][2] = 0;
297                 gadget->attrs.idProduct = 0x685d;
298                 break;
299
300         /* DM */
301         case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DM:
302                 n_configs = 1;
303                 functions[0][0] = USB_FUNCTION_ACM;
304                 functions[0][1] = USB_FUNCTION_SDB;
305                 functions[0][2] = USB_FUNCTION_DM;
306                 functions[0][3] = 0;
307                 gadget->attrs.idProduct = 0x6860;
308                 break;
309
310         default:
311                 ret = -EINVAL;
312                 goto free_gadget;
313         };
314
315         n_functions = __builtin_popcount(gadget_id->function_mask);
316
317         funcs = calloc(n_functions + 1, sizeof(*funcs));
318         if (!funcs) {
319                 ret = -ENOMEM;
320                 goto free_gadget;
321         }
322
323         gadget->funcs = funcs;
324
325         idx = 0;
326         for (i = 0; _available_funcs[i]; ++i) {
327                 int func_id = 1 << i;
328
329                 if (!(gadget_id->function_mask & func_id))
330                         continue;
331
332                 ret = _available_funcs[i]->clone(_available_funcs[i],
333                         gadget->funcs + idx);
334                 if (ret)
335                         goto free_functions;
336                 ++idx;
337         }
338
339         for (j = 0; j < n_configs; ++j) {
340                 struct usb_configuration *config;
341                 int n_funcs_in_config;
342
343                 for (i = 0; functions[j][i]; ++i);
344                 n_funcs_in_config = i;
345
346                 ret = alloc_default_config(&config);
347                 if (ret)
348                         goto free_configs;
349
350                 gadget->configs[j] = config;
351                 config->funcs = calloc(n_funcs_in_config + 1,
352                                                        sizeof(void *));
353                 if (!config->funcs)
354                         goto free_configs;
355
356                 for (i = 0; functions[j][i]; ++i)
357                         config->funcs[i] = find_func(gadget, functions[j][i]);
358         }
359
360         *_gadget = gadget;
361         return 0;
362
363 free_configs:
364 free_functions:
365 free_gadget:
366         simple_cleanup_gadget(gadget);
367 out:
368         return ret;
369 }
370
371 void rndis_handler(int enable)
372 {
373         if (enable)
374                 (void)systemd_start_unit_wait_started("rndis.service", NULL, -1);
375         else
376                 (void)systemd_stop_unit_wait_stopped("rndis.service", NULL, -1);
377 }
378
379 static void free_simple_func(struct usb_function *func)
380 {
381         if (func) {
382                 free((void *)func->name);
383                 free((void *)func->instance);
384                 free((void *)func->ffs_service);
385                 free((void *)func->service);
386                 free(func);
387         }
388 }
389
390 static int clone_simple_func(struct usb_function *func,
391                               struct usb_function **clone)
392 {
393         struct usb_function *other;
394
395         if (!func || !clone)
396                 return -EINVAL;
397
398         other = (struct usb_function *)calloc(1, sizeof(struct usb_function));
399         if (!other)
400                 return -ENOMEM;
401
402         *other = *func;
403
404         other->name = strdup(func->name);
405         other->instance = strdup(func->instance);
406         if (!other->name || !other->instance)
407                 goto out_nomem;
408
409         if (func->ffs_service) {
410                 other->ffs_service = strdup(func->ffs_service);
411                 if (!other->ffs_service)
412                         goto out_nomem;
413         }
414
415         if (func->service) {
416                 other->service = strdup(func->service);
417                 if (!other->service)
418                         goto out_nomem;
419         }
420
421         *clone = other;
422         return 0;
423
424 out_nomem:
425         free_simple_func(other);
426         return -ENOMEM;
427 }
428
429 #define DEFINE_USB_FUNCTION(_id, _name, _ffs_service, _service, _handler)       \
430         static struct usb_function _##_name##_function = {                      \
431                 .id = _id,                                                      \
432                 .name = #_name,                                                 \
433                 .instance = "default",                                          \
434                 .ffs_service = _ffs_service,                                    \
435                 .service = _service,                                            \
436                 .handler = _handler,                                            \
437                 .clone = clone_simple_func,                                     \
438                 .free_func = free_simple_func,                                  \
439         }
440
441 DEFINE_USB_FUNCTION(USB_FUNCTION_DIAG,        diag,        NULL, NULL,            NULL);
442 DEFINE_USB_FUNCTION(USB_FUNCTION_RMNET,       rmnet,       NULL, NULL,            NULL);
443 DEFINE_USB_FUNCTION(USB_FUNCTION_DM,          dm,          NULL, NULL,            NULL);
444 DEFINE_USB_FUNCTION(USB_FUNCTION_CONN_GADGET, conn_gadget, NULL, NULL,            NULL);
445 DEFINE_USB_FUNCTION(USB_FUNCTION_SDB,         sdb,         "sdbd", NULL,          NULL);
446 DEFINE_USB_FUNCTION(USB_FUNCTION_MTP,         mtp,         "mtp-responder", NULL, NULL);
447 DEFINE_USB_FUNCTION(USB_FUNCTION_ACM,         acm,         NULL, "data-router",   NULL);
448 DEFINE_USB_FUNCTION(USB_FUNCTION_RNDIS,       rndis,       NULL, "sshd",          rndis_handler);
449 #undef DEFINE_USB_FUNCTION
450
451 /* Caution: index order of arrary is important, because simple_id_to_gadget() uses it. */
452 struct usb_function *_available_funcs[] = {
453         [USB_FUNCTION_IDX_MTP]         = &_mtp_function,
454         [USB_FUNCTION_IDX_ACM]         = &_acm_function,
455         [USB_FUNCTION_IDX_SDB]         = &_sdb_function,
456         [USB_FUNCTION_IDX_RNDIS]       = &_rndis_function,
457         [USB_FUNCTION_IDX_DIAG]        = &_diag_function,
458         [USB_FUNCTION_IDX_CONN_GADGET] = &_conn_gadget_function,
459         [USB_FUNCTION_IDX_DM]          = &_dm_function,
460         [USB_FUNCTION_IDX_RMNET]       = &_rmnet_function,
461         [USB_FUNCTION_IDX_MAX]         = NULL /* An indicator to end the array */
462 };
463
464 EXPORT
465 int simple_translator_open(struct hw_info *info,
466                 const char *id, struct hw_common **common)
467 {
468         struct usb_gadget_translator *simple_translator;
469
470         if (!info || !common)
471                 return -EINVAL;
472
473         simple_translator = zalloc(sizeof(*simple_translator));
474         if (!simple_translator)
475                 return -ENOMEM;
476
477         simple_translator->common.info = info;
478         simple_translator->id_to_gadget = simple_id_to_gadget;
479         simple_translator->cleanup_gadget = simple_cleanup_gadget;
480
481         /* Use mtp-responder-dummy.socket when there is no mtp-responser.socket.
482          *
483          * The mtp-responder.socket is special in the configfs environment.
484          * If mtp-responder.socket is missing, gadget configuration will fail.
485          * As a result, all usb operations do not work properly.
486          * So in environments that mtp doesn't support, use dummy mtp.
487          */
488         if (access("/usr/lib/systemd/system/mtp-responder.socket", F_OK)) {
489                 _available_funcs[USB_FUNCTION_IDX_MTP]->ffs_service = "mtp-responder-dummy";
490         }
491
492         *common = &simple_translator->common;
493         return 0;
494 }
495
496 EXPORT
497 int simple_translator_close(struct hw_common *common)
498 {
499         struct usb_gadget_translator *simple_translator;
500
501         if (!common)
502                 return -EINVAL;
503
504         simple_translator = container_of(common, struct usb_gadget_translator,
505                                          common);
506
507         free(simple_translator);
508         return 0;
509 }