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