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