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