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