4 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <hw/usb_gadget.h>
28 #include <libsyscommon/dbus-systemd.h>
30 #define zalloc(amount) calloc(1, amount)
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
37 #define DEFAULT_LANG 0x409 /* US_en */
38 #define DEFAULT_MANUFACTURER "Samsung"
39 #define DEFAULT_PRODUCT "TIZEN"
40 #define DEFAULT_SERIAL "01234TEST"
42 #define DEFAULT_BMATTRIBUTES ((1 << 7) | (1 << 6))
43 #define DEFAULT_MAX_POWER 500
46 #define EXPORT __attribute__ ((visibility("default")))
49 static void simple_cleanup_config(struct usb_configuration *config)
57 for (i = 0; config->strs[i].lang_code; ++i)
58 free(config->strs[i].config_str);
64 * Each function will be free later,
65 * for now we cleanup only pointers.
73 static void simple_cleanup_gadget(struct usb_gadget *gadget)
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);
89 if (gadget->configs) {
90 for (i = 0; gadget->configs[i]; ++i)
91 simple_cleanup_config(gadget->configs[i]);
93 free(gadget->configs);
97 for (i = 0; gadget->funcs[i]; ++i)
98 gadget->funcs[i]->free_func(gadget->funcs[i]);
106 static int alloc_default_config(struct usb_configuration **_config)
108 struct usb_configuration *config;
110 config = zalloc(sizeof(*config));
114 config->strs = calloc(1, sizeof(*config->strs));
118 config->attrs.bmAttributs = DEFAULT_BMATTRIBUTES;
119 config->attrs.MaxPower = DEFAULT_MAX_POWER;
131 static int get_device_serial(char **out)
133 struct hw_info *info;
134 struct hw_common *common;
135 struct hw_board *board;
138 if (hw_get_info(BOARD_HARDWARE_DEVICE_ID, (const struct hw_info **)&info))
141 ret = info->open(info, NULL, &common);
145 board = container_of(common, struct hw_board, common);
146 return board->get_device_serial(out);
149 static int alloc_default_gadget(struct usb_gadget **_gadget)
151 struct usb_gadget *gadget;
152 struct usb_gadget_strings *strs;
153 struct usb_configuration **configs;
156 gadget = zalloc(sizeof(*gadget));
160 gadget->attrs.idVendor = DEFAULT_VID;
161 gadget->attrs.idProduct = DEFAULT_PID;
162 gadget->attrs.bcdDevice = DEFAULT_BCD_DEVICE;
164 strs = calloc(2, sizeof(*strs));
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);
173 strs[0].serial = strdup(DEFAULT_SERIAL);
175 if (!strs[0].manufacturer || !strs[0].product || !strs[0].serial)
180 /* slp-gadget use max 2 confiuration and NULL termination */
181 configs = calloc(3, sizeof(*configs));
185 gadget->configs = configs;
191 free(strs[0].manufacturer);
192 free(strs[0].product);
193 free(strs[0].serial);
201 static inline struct usb_function *find_func(struct usb_gadget *gadget,
206 for (i = 0; gadget->funcs[i] && gadget->funcs[i]->id != func_id; ++i);
208 return gadget->funcs[i];
211 static int simple_id_to_gadget(struct usb_gadget_id *gadget_id,
212 struct usb_gadget **_gadget)
214 struct usb_gadget *gadget;
216 /* zero terminates */
217 int functions[2][sizeof(gadget_id->function_mask)*8];
219 struct usb_function **funcs;
223 if (!gadget_id || !_gadget)
226 ret = alloc_default_gadget(&gadget);
231 * Currently all gadgets use inly single configuration but
232 * slp-gadget is capable to handle two of them
234 * Order of interfaces in configuration is significant
235 * so in this switch we sort our functions in a correct order
237 switch (gadget_id->function_mask) {
238 case USB_FUNCTION_MTP:
240 functions[0][0] = USB_FUNCTION_MTP;
242 gadget->attrs.idProduct = 0x6860;
245 case USB_FUNCTION_ACM:
247 functions[0][0] = USB_FUNCTION_ACM;
249 gadget->attrs.idProduct = 0x6860;
252 case USB_FUNCTION_SDB:
254 functions[0][0] = USB_FUNCTION_SDB;
256 gadget->attrs.idProduct = 0x685d;
260 case USB_FUNCTION_MTP | USB_FUNCTION_ACM:
262 functions[0][0] = USB_FUNCTION_MTP;
263 functions[0][1] = USB_FUNCTION_ACM;
265 gadget->attrs.idProduct = 0x6860;
268 case USB_FUNCTION_ACM | USB_FUNCTION_SDB:
270 functions[0][0] = USB_FUNCTION_ACM;
271 functions[0][1] = USB_FUNCTION_SDB;
273 gadget->attrs.idProduct = 0x6860;
276 case USB_FUNCTION_MTP | USB_FUNCTION_SDB:
278 functions[0][0] = USB_FUNCTION_MTP;
279 functions[0][1] = USB_FUNCTION_SDB;
281 gadget->attrs.idProduct = 0x6860;
284 case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB:
286 functions[0][0] = USB_FUNCTION_MTP;
287 functions[0][1] = USB_FUNCTION_ACM;
288 functions[0][2] = USB_FUNCTION_SDB;
290 gadget->attrs.idProduct = 0x6860;
294 case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DIAG:
296 functions[0][0] = USB_FUNCTION_MTP;
297 functions[0][1] = USB_FUNCTION_ACM;
298 functions[0][2] = USB_FUNCTION_SDB;
299 functions[0][3] = USB_FUNCTION_DIAG;
301 gadget->attrs.idProduct = 0x6860;
305 case USB_FUNCTION_RNDIS:
307 functions[0][0] = USB_FUNCTION_RNDIS;
309 gadget->attrs.idProduct = 0x6863;
312 case USB_FUNCTION_SDB | USB_FUNCTION_RNDIS:
314 functions[0][0] = USB_FUNCTION_SDB;
315 functions[0][1] = USB_FUNCTION_RNDIS;
317 gadget->attrs.idProduct = 0x6864;
320 case USB_FUNCTION_RNDIS | USB_FUNCTION_DIAG:
322 functions[0][0] = USB_FUNCTION_RNDIS;
323 functions[0][1] = USB_FUNCTION_DIAG;
325 gadget->attrs.idProduct = 0x6864;
328 case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS:
330 functions[0][0] = USB_FUNCTION_ACM;
331 functions[0][1] = USB_FUNCTION_SDB;
332 functions[0][2] = USB_FUNCTION_RNDIS;
334 gadget->attrs.idProduct = 0x6864;
338 case USB_FUNCTION_DIAG | USB_FUNCTION_RMNET:
340 functions[0][0] = USB_FUNCTION_DIAG;
341 functions[0][1] = USB_FUNCTION_RMNET;
343 gadget->attrs.idProduct = 0x685d;
347 case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DM:
349 functions[0][0] = USB_FUNCTION_ACM;
350 functions[0][1] = USB_FUNCTION_SDB;
351 functions[0][2] = USB_FUNCTION_DM;
353 gadget->attrs.idProduct = 0x6860;
361 n_functions = __builtin_popcount(gadget_id->function_mask);
363 funcs = calloc(n_functions + 1, sizeof(*funcs));
369 gadget->funcs = funcs;
372 for (i = 0; _available_funcs[i]; ++i) {
373 int func_id = 1 << i;
375 if (!(gadget_id->function_mask & func_id))
378 ret = _available_funcs[i]->clone(_available_funcs[i],
379 gadget->funcs + idx);
385 for (j = 0; j < n_configs; ++j) {
386 struct usb_configuration *config;
387 int n_funcs_in_config;
389 for (i = 0; functions[j][i]; ++i);
390 n_funcs_in_config = i;
392 ret = alloc_default_config(&config);
396 gadget->configs[j] = config;
397 config->funcs = calloc(n_funcs_in_config + 1,
402 for (i = 0; functions[j][i]; ++i)
403 config->funcs[i] = find_func(gadget, functions[j][i]);
411 simple_cleanup_gadget(gadget);
416 void rndis_handler(int enable)
419 (void)systemd_start_unit_wait_started("rndis.service", NULL, -1);
421 (void)systemd_stop_unit_wait_stopped("rndis.service", NULL, -1);
424 static void free_simple_func(struct usb_function *func)
427 free((void *)func->name);
428 free((void *)func->instance);
429 free((void *)func->ffs_service);
430 free((void *)func->service);
435 static int clone_simple_func(struct usb_function *func,
436 struct usb_function **clone)
438 struct usb_function *other;
443 other = (struct usb_function *)calloc(1, sizeof(struct usb_function));
449 other->name = strdup(func->name);
450 other->instance = strdup(func->instance);
451 if (!other->name || !other->instance)
454 if (func->ffs_service) {
455 other->ffs_service = strdup(func->ffs_service);
456 if (!other->ffs_service)
461 other->service = strdup(func->service);
470 free_simple_func(other);
474 #define DEFINE_USB_FUNCTION(_id, _name, _ffs_service, _service, _handler) \
475 static struct usb_function _##_name##_function = { \
478 .instance = "default", \
479 .ffs_service = _ffs_service, \
480 .service = _service, \
481 .handler = _handler, \
482 .clone = clone_simple_func, \
483 .free_func = free_simple_func, \
486 DEFINE_USB_FUNCTION(USB_FUNCTION_DIAG, diag, NULL, NULL, NULL);
487 DEFINE_USB_FUNCTION(USB_FUNCTION_RMNET, rmnet, NULL, NULL, NULL);
488 DEFINE_USB_FUNCTION(USB_FUNCTION_DM, dm, NULL, NULL, NULL);
489 DEFINE_USB_FUNCTION(USB_FUNCTION_CONN_GADGET, conn_gadget, NULL, NULL, NULL);
490 DEFINE_USB_FUNCTION(USB_FUNCTION_SDB, sdb, "sdbd", NULL, NULL);
491 DEFINE_USB_FUNCTION(USB_FUNCTION_MTP, mtp, "mtp-responder", NULL, NULL);
492 DEFINE_USB_FUNCTION(USB_FUNCTION_ACM, acm, NULL, "data-router", NULL);
493 DEFINE_USB_FUNCTION(USB_FUNCTION_RNDIS, rndis, NULL, "sshd", rndis_handler);
494 #undef DEFINE_USB_FUNCTION
496 /* Caution: index order of arrary is important, because simple_id_to_gadget() uses it. */
497 struct usb_function *_available_funcs[] = {
498 [USB_FUNCTION_IDX_MTP] = &_mtp_function,
499 [USB_FUNCTION_IDX_ACM] = &_acm_function,
500 [USB_FUNCTION_IDX_SDB] = &_sdb_function,
501 [USB_FUNCTION_IDX_RNDIS] = &_rndis_function,
502 [USB_FUNCTION_IDX_DIAG] = &_diag_function,
503 [USB_FUNCTION_IDX_CONN_GADGET] = &_conn_gadget_function,
504 [USB_FUNCTION_IDX_DM] = &_dm_function,
505 [USB_FUNCTION_IDX_RMNET] = &_rmnet_function,
506 [USB_FUNCTION_IDX_MAX] = NULL /* An indicator to end the array */
510 int simple_translator_open(struct hw_info *info,
511 const char *id, struct hw_common **common)
513 struct usb_gadget_translator *simple_translator;
515 if (!info || !common)
518 simple_translator = zalloc(sizeof(*simple_translator));
519 if (!simple_translator)
522 simple_translator->common.info = info;
523 simple_translator->id_to_gadget = simple_id_to_gadget;
524 simple_translator->cleanup_gadget = simple_cleanup_gadget;
526 /* Use mtp-responder-dummy.socket when there is no mtp-responser.socket.
528 * The mtp-responder.socket is special in the configfs environment.
529 * If mtp-responder.socket is missing, gadget configuration will fail.
530 * As a result, all usb operations do not work properly.
531 * So in environments that mtp doesn't support, use dummy mtp.
533 if (access("/usr/lib/systemd/system/mtp-responder.socket", F_OK)) {
534 _available_funcs[USB_FUNCTION_IDX_MTP]->ffs_service = "mtp-responder-dummy";
537 *common = &simple_translator->common;
542 int simple_translator_close(struct hw_common *common)
544 struct usb_gadget_translator *simple_translator;
549 simple_translator = container_of(common, struct usb_gadget_translator,
552 free(simple_translator);