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.
24 #include <libsyscommon/dbus-systemd.h>
27 #include <hw/usb_gadget.h>
29 #define zalloc(amount) calloc(1, amount)
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
36 #define DEFAULT_LANG 0x409 /* US_en */
37 #define DEFAULT_MANUFACTURER "Samsung"
38 #define DEFAULT_PRODUCT "TIZEN"
39 #define DEFAULT_SERIAL "01234TEST"
41 #define DEFAULT_BMATTRIBUTES ((1 << 7) | (1 << 6))
42 #define DEFAULT_MAX_POWER 500
45 #define EXPORT __attribute__ ((visibility("default")))
48 static const struct usb_function *_available_funcs[];
50 static void simple_cleanup_config(struct usb_configuration *config)
58 for (i = 0; config->strs[i].lang_code; ++i)
59 free(config->strs[i].config_str);
70 static void simple_cleanup_gadget(struct usb_gadget *gadget)
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);
86 if (gadget->configs) {
87 for (i = 0; gadget->configs[i]; ++i)
88 simple_cleanup_config(gadget->configs[i]);
90 free(gadget->configs);
99 static int alloc_default_config(struct usb_configuration **_config)
101 struct usb_configuration *config;
103 config = zalloc(sizeof(*config));
107 config->strs = calloc(1, sizeof(*config->strs));
111 config->attrs.bmAttributs = DEFAULT_BMATTRIBUTES;
112 config->attrs.MaxPower = DEFAULT_MAX_POWER;
124 static int get_device_serial(char **out)
126 struct hw_info *info;
127 struct hw_common *common;
128 struct hw_board *board;
131 if (hw_get_info(BOARD_HARDWARE_DEVICE_ID, (const struct hw_info **)&info))
134 ret = info->open(info, NULL, &common);
138 board = container_of(common, struct hw_board, common);
139 return board->get_device_serial(out);
142 static int alloc_default_gadget(struct usb_gadget **_gadget)
144 struct usb_gadget *gadget;
145 struct usb_gadget_strings *strs;
146 struct usb_configuration **configs;
149 gadget = zalloc(sizeof(*gadget));
153 gadget->attrs.idVendor = DEFAULT_VID;
154 gadget->attrs.idProduct = DEFAULT_PID;
155 gadget->attrs.bcdDevice = DEFAULT_BCD_DEVICE;
157 strs = calloc(2, sizeof(*strs));
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);
166 strs[0].serial = strdup(DEFAULT_SERIAL);
168 if (!strs[0].manufacturer || !strs[0].product || !strs[0].serial)
173 /* slp-gadget use max 2 confiuration and NULL termination */
174 configs = calloc(3, sizeof(*configs));
178 gadget->configs = configs;
184 free(strs[0].manufacturer);
185 free(strs[0].product);
186 free(strs[0].serial);
194 static inline const struct usb_function *find_func(struct usb_gadget *gadget,
199 for (i = 0; gadget->funcs[i] && gadget->funcs[i]->id != func_id; ++i);
201 return gadget->funcs[i];
204 static int simple_id_to_gadget(struct usb_gadget_id *gadget_id,
205 struct usb_gadget **_gadget)
211 struct usb_gadget *gadget;
212 const struct usb_function **funcs;
213 int functions[2][sizeof(gadget_id->function_mask)*8]; /* zero terminates */
215 if (!gadget_id || !_gadget)
218 ret = alloc_default_gadget(&gadget);
223 * Currently all gadgets use inly single configuration but
224 * slp-gadget is capable to handle two of them
226 * Order of interfaces in configuration is significant
227 * so in this switch we sort our functions in a correct order
229 switch (gadget_id->function_mask) {
231 case USB_FUNCTION_MTP | USB_FUNCTION_ACM:
233 functions[0][0] = USB_FUNCTION_MTP;
234 functions[0][1] = USB_FUNCTION_ACM;
236 gadget->attrs.idProduct = 0x6860;
239 case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB:
241 functions[0][0] = USB_FUNCTION_MTP;
242 functions[0][1] = USB_FUNCTION_ACM;
243 functions[0][2] = USB_FUNCTION_SDB;
245 gadget->attrs.idProduct = 0x6860;
249 case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DIAG:
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;
256 gadget->attrs.idProduct = 0x6860;
260 case USB_FUNCTION_RNDIS:
262 functions[0][0] = USB_FUNCTION_RNDIS;
264 gadget->attrs.idProduct = 0x6863;
267 case USB_FUNCTION_RNDIS | USB_FUNCTION_DIAG:
269 functions[0][0] = USB_FUNCTION_RNDIS;
270 functions[0][1] = USB_FUNCTION_DIAG;
272 gadget->attrs.idProduct = 0x6864;
275 case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS:
277 functions[0][0] = USB_FUNCTION_ACM;
278 functions[0][1] = USB_FUNCTION_SDB;
279 functions[0][2] = USB_FUNCTION_RNDIS;
281 gadget->attrs.idProduct = 0x6864;
285 case USB_FUNCTION_DIAG | USB_FUNCTION_RMNET:
287 functions[0][0] = USB_FUNCTION_DIAG;
288 functions[0][1] = USB_FUNCTION_RMNET;
290 gadget->attrs.idProduct = 0x685d;
294 case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DM:
296 functions[0][0] = USB_FUNCTION_ACM;
297 functions[0][1] = USB_FUNCTION_SDB;
298 functions[0][2] = USB_FUNCTION_DM;
300 gadget->attrs.idProduct = 0x6860;
308 n_functions = __builtin_popcount(gadget_id->function_mask);
310 funcs = calloc(n_functions + 1, sizeof(*funcs));
316 gadget->funcs = funcs;
319 for (i = 0; _available_funcs[i]; ++i) {
320 int func_id = 1 << i;
322 if (!(gadget_id->function_mask & func_id))
325 gadget->funcs[idx] = _available_funcs[i];
329 for (j = 0; j < n_configs; ++j) {
330 struct usb_configuration *config;
331 int n_funcs_in_config;
333 for (i = 0; functions[j][i]; ++i);
334 n_funcs_in_config = i;
336 ret = alloc_default_config(&config);
340 gadget->configs[j] = config;
341 config->funcs = calloc(n_funcs_in_config + 1,
346 for (i = 0; functions[j][i]; ++i)
347 config->funcs[i] = find_func(gadget, functions[j][i]);
355 simple_cleanup_gadget(gadget);
360 void rndis_handler(int enable)
363 (void)systemd_start_unit_wait_started("rndis.service", NULL, -1);
365 (void)systemd_stop_unit_wait_stopped("rndis.service", NULL, -1);
368 #define DEFINE_USB_FUNCTION(_id, _name, _is_functionfs, _service, _handler) \
369 static const struct usb_function _##_name##_function = { \
372 .instance = "default", \
373 .is_functionfs = _is_functionfs, \
374 .service = _service, \
375 .handler = _handler, \
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);
387 #undef DEFINE_USB_FUNCTION
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 */
402 const struct usb_function *find_usb_function_by_name(const char *name)
406 if(!name || !name[0])
409 for (i = 0; _available_funcs[i]; i++)
410 if (!strcmp(name, _available_funcs[i]->name))
411 return _available_funcs[i];
416 const struct usb_function *find_usb_function_by_name_instance(const char *name, const char *instance)
420 if(!name || !name[0] || !instance || !instance[0])
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];
432 int simple_translator_open(struct hw_info *info,
433 const char *id, struct hw_common **common)
435 struct usb_gadget_translator *simple_translator;
437 if (!info || !common)
440 simple_translator = zalloc(sizeof(*simple_translator));
441 if (!simple_translator)
444 simple_translator->common.info = info;
445 simple_translator->id_to_gadget = simple_id_to_gadget;
446 simple_translator->cleanup_gadget = simple_cleanup_gadget;
448 /* Use mtp-responder-dummy.socket when there is no mtp-responser.socket.
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.
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";
458 *common = &simple_translator->common;
463 int simple_translator_close(struct hw_common *common)
465 struct usb_gadget_translator *simple_translator;
470 simple_translator = container_of(common, struct usb_gadget_translator,
473 free(simple_translator);