4 * Copyright (c) 2016 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_client.h>
21 #include "../shared.h"
27 #define zalloc(amount) calloc(1, amount)
29 #define MAX_GADGET_STR_LEN 256
32 #define LEGACY_ROOTPATH "/sys/class/usb_mode/usb0"
34 /* Device descriptor values */
35 #define LEGACY_ID_VENDOR_PATH LEGACY_ROOTPATH"/idVendor"
36 #define LEGACY_ID_PRODUCT_PATH LEGACY_ROOTPATH"/idProduct"
37 #define LEGACY_BCD_DEVICE_PATH LEGACY_ROOTPATH"/bcdDevice"
38 #define LEGACY_CLASS_PATH LEGACY_ROOTPATH"/bDeviceClass"
39 #define LEGACY_SUBCLASS_PATH LEGACY_ROOTPATH"/bDeviceSubClass"
40 #define LEGACY_PROTOCOL_PATH LEGACY_ROOTPATH"/bDeviceProtocol"
43 #define LEGACY_IMANUFACTURER_PATH LEGACY_ROOTPATH"/iManufacturer"
44 #define LEGACY_IPRODUCT_PATH LEGACY_ROOTPATH"/iProduct"
45 #define LEGACY_ISERIAL_PATH LEGACY_ROOTPATH"/iSerial"
47 /* Functions in each config */
48 #define LEGACY_CONFIG_1_PATH LEGACY_ROOTPATH"/funcs_fconf"
49 #define LEGACY_CONFIG_2_PATH LEGACY_ROOTPATH"/funcs_sconf"
50 /* should be single char */
51 #define LEGACY_FUNC_SEP ","
54 #define LEGACY_ENABLE_PATH LEGACY_ROOTPATH"/enable"
55 #define LEGACY_ENABLE "1"
56 #define LEGACY_DISABLE "0"
58 #define LEGACY_BMATTRIBUTES ((1 << 7) | (1 << 6))
59 #define LEGACY_MAX_POWER 500
61 /* +5 to be always big enough */
62 #define INT_BUF_SIZE (sizeof(int)*8 + 5)
64 static int get_int_from_file(char *path, int *_val)
66 char buf[INT_BUF_SIZE];
71 ret = sys_get_str(path, buf, sizeof(buf));
75 val = strtol(buf, &endptr, 0);
76 if (val == LONG_MIN || val == LONG_MAX ||
77 buf[0] == '\0' || (*endptr != '\0' && *endptr != '\n')
85 static int legacy_read_gadget_attrs_strs(struct usb_gadget *gadget)
89 /* We assume that values received from kernel will be valid */
90 #define GET_VALUE_FROM_SYSFS(path, field, type) \
92 ret = get_int_from_file(path, &val); \
96 gadget->attrs.field = (type)val; \
99 GET_VALUE_FROM_SYSFS(LEGACY_CLASS_PATH, bDeviceClass, uint8_t);
100 GET_VALUE_FROM_SYSFS(LEGACY_SUBCLASS_PATH, bDeviceSubClass, uint8_t);
101 GET_VALUE_FROM_SYSFS(LEGACY_PROTOCOL_PATH, bDeviceProtocol, uint8_t);
102 GET_VALUE_FROM_SYSFS(LEGACY_ID_VENDOR_PATH, idVendor, uint16_t);
103 GET_VALUE_FROM_SYSFS(LEGACY_ID_PRODUCT_PATH, idVendor, uint16_t);
104 GET_VALUE_FROM_SYSFS(LEGACY_BCD_DEVICE_PATH, bcdDevice, uint16_t);
105 #undef GET_VALUE_FROM_SYSFS
107 #define GET_STRING_FROM_SYSFS(path, field) \
109 char buf[MAX_GADGET_STR_LEN]; \
111 ret = sys_get_str(path, buf, sizeof(buf)); \
115 gadget->strs[0].field = strdup(buf); \
116 if (!gadget->strs[0].field) { \
122 GET_STRING_FROM_SYSFS(LEGACY_IMANUFACTURER_PATH, manufacturer);
123 GET_STRING_FROM_SYSFS(LEGACY_IPRODUCT_PATH, product);
124 GET_STRING_FROM_SYSFS(LEGACY_ISERIAL_PATH, serial);
125 #undef GET_STRING_FROM_SYSFS
130 free(gadget->strs[0].product);
132 free(gadget->strs[0].manufacturer);
137 static int legacy_find_func(const char *name)
141 for (i = 0; i < ARRAY_SIZE(_available_funcs); ++i)
142 if (!strcmp(name, _available_funcs[i]->name))
148 static struct usb_function *legacy_find_func_in_gadget(
149 struct usb_gadget *gadget, const char *name)
153 for (i = 0; gadget->funcs[i]; ++i)
154 if (!strcmp(name, gadget->funcs[i]->name))
155 return gadget->funcs[i];
159 static int legacy_alloc_config(int n_funcs, struct usb_configuration **_config)
161 struct usb_configuration *config;
163 config = zalloc(sizeof(*config));
167 config->strs = calloc(1, sizeof(*config->strs));
171 config->funcs = calloc(n_funcs + 1, sizeof(*config->funcs));
176 * We cannot read correct values
177 * so assume that they are always default
179 config->attrs.bmAttributs = LEGACY_BMATTRIBUTES;
180 config->attrs.MaxPower = LEGACY_MAX_POWER;
193 static int legacy_alloc_new_func(struct usb_gadget *gadget, const char *fname,
194 struct usb_function **_func)
196 struct usb_function *func;
199 ret = legacy_find_func(fname);
203 ret = _available_funcs[ret]->clone(_available_funcs[ret], &func);
211 static int legacy_read_config(struct usb_gadget *gadget,
213 struct usb_configuration **_config)
215 struct usb_configuration *config;
216 char buf[MAX_GADGET_STR_LEN];
219 char *sep = LEGACY_FUNC_SEP;
224 ret = sys_get_str(cpath, buf, sizeof(buf));
229 if (buf[0] == '\0' || buf[0] == '\n')
232 /* count number of functions in this config */
234 for (i = 0; buf[i] != '\0'; ++i)
235 if (buf[i] == sep[0])
238 ret = legacy_alloc_config(f_cnt, &config);
243 for (fname = strsep(&begin, sep); fname; fname = strsep(&begin, sep)) {
244 struct usb_function *func;
246 func = legacy_find_func_in_gadget(gadget, fname);
248 /* new function not added yet to gadget */
249 ret = legacy_alloc_new_func(gadget, fname, &func);
254 config->funcs[f_idx++] = func;
266 static int legacy_get_current_gadget(struct usb_client *usb,
267 struct usb_gadget **_gadget)
269 struct usb_gadget *gadget;
270 struct usb_gadget_strings *strs;
271 struct usb_configuration **configs;
272 struct usb_function **funcs;
276 gadget = zalloc(sizeof(*gadget));
280 strs = calloc(2, sizeof(*strs));
284 strs[0].lang_code = 0x409;
288 ret = legacy_read_gadget_attrs_strs(gadget);
292 /* There will be no more functions than bits in int */
293 funcs = calloc(MAX_FUNCS, sizeof(*funcs));
295 goto free_strs_with_content;
297 gadget->funcs = funcs;
299 /* slp-gadget use max 2 confiuration and NULL termination */
300 configs = calloc(3, sizeof(*configs));
304 gadget->configs = configs;
306 ret = legacy_read_config(gadget, LEGACY_CONFIG_1_PATH, configs + 0);
310 ret = legacy_read_config(gadget, LEGACY_CONFIG_2_PATH, configs + 1);
318 free(configs[0]->funcs);
319 free(configs[0]->strs);
323 for (i = 0; gadget->funcs[i]; ++i)
324 gadget->funcs[i]->free_func(gadget->funcs[i]);
327 free_strs_with_content:
328 free(gadget->strs[0].manufacturer);
329 free(gadget->strs[0].product);
330 free(gadget->strs[0].serial);
339 static bool legacy_is_function_supported(struct usb_client *usb,
340 struct usb_function *func)
346 * Instead of only checking whether we know this function
347 * we should also parse sysfs to check if it is build into
350 ret = legacy_find_func(func->name);
355 static bool legacy_is_gadget_supported(struct usb_client *usb,
356 struct usb_gadget *gadget)
360 if (!gadget || !gadget->configs || !gadget->funcs)
365 * Here is a good place to ensure that serial is immutable
368 /* only strings in US_en are allowed */
369 if (gadget->strs[0].lang_code != 0x409 ||
370 gadget->strs[1].lang_code)
374 for (j = 0; gadget->configs[j]; ++j) {
375 struct usb_configuration *config = gadget->configs[j];
377 if (config->strs && config->strs[0].lang_code)
383 for (i = 0; config->funcs[i]; ++i)
384 if (!legacy_is_function_supported(usb, config->funcs[i]))
394 /* TODO. Maybe move this to sys ? */
395 static int legacy_set_int_hex(char *path, int val)
397 char buf[MAX_GADGET_STR_LEN];
403 snprintf(buf, sizeof(buf), "%x", val);
404 r = sys_set_str(path, buf);
411 static int legacy_set_gadget_attrs(struct usb_gadget_attrs *attrs)
415 ret = sys_set_int(LEGACY_CLASS_PATH, attrs->bDeviceClass);
419 ret = sys_set_int(LEGACY_SUBCLASS_PATH, attrs->bDeviceSubClass);
423 ret = sys_set_int(LEGACY_PROTOCOL_PATH, attrs->bDeviceProtocol);
427 ret = legacy_set_int_hex(LEGACY_ID_VENDOR_PATH, attrs->idVendor);
431 ret = legacy_set_int_hex(LEGACY_ID_PRODUCT_PATH, attrs->idProduct);
435 ret = legacy_set_int_hex(LEGACY_BCD_DEVICE_PATH, attrs->bcdDevice);
440 static int legacy_set_gadget_strs(struct usb_gadget_strings *strs)
446 * Here is a good place to ensure that serial is immutable
449 if (strs->manufacturer) {
450 ret = sys_set_str(LEGACY_IMANUFACTURER_PATH,
457 ret = sys_set_str(LEGACY_IPRODUCT_PATH,
466 static int legacy_set_gadget_config(char *cpath,
467 struct usb_configuration *config)
469 char buf[MAX_GADGET_STR_LEN];
470 int left = sizeof(buf);
481 for (i = 0; config->funcs[i]; ++i) {
482 ret = snprintf(pos, left, "%s" LEGACY_FUNC_SEP,
483 config->funcs[i]->name);
491 /* eliminate last separator */
495 return sys_set_str(cpath, buf);
498 static int legacy_reconfigure_gadget(struct usb_client *usb,
499 struct usb_gadget *gadget)
503 if (!usb || !gadget || !legacy_is_gadget_supported(usb, gadget))
506 ret = legacy_set_gadget_attrs(&gadget->attrs);
511 ret = legacy_set_gadget_strs(gadget->strs + 0);
516 ret = legacy_set_gadget_config(LEGACY_CONFIG_1_PATH, gadget->configs[0]);
520 ret = legacy_set_gadget_config(LEGACY_CONFIG_2_PATH, gadget->configs[1]);
525 static int legacy_enable(struct usb_client *usb)
527 return sys_set_str(LEGACY_ENABLE_PATH,
531 static int legacy_disable(struct usb_client *usb)
533 return sys_set_str(LEGACY_ENABLE_PATH,
537 static void legacy_free_config(struct usb_configuration *config)
545 for (i = 0; config->strs[i].lang_code; ++i)
546 free(config->strs[i].config_str);
552 * Each function will be free later,
553 * for now we cleanup only pointers.
561 static void legacy_free_gadget(struct usb_gadget *gadget)
569 for (i = 0; gadget->strs[i].lang_code; ++i) {
570 free(gadget->strs[i].manufacturer);
571 free(gadget->strs[i].product);
572 free(gadget->strs[i].serial);
577 if (gadget->configs) {
578 for (i = 0; gadget->configs[i]; ++i)
579 legacy_free_config(gadget->configs[i]);
581 free(gadget->configs);
585 for (i = 0; gadget->funcs[i]; ++i)
586 gadget->funcs[i]->free_func(gadget->funcs[i]);
592 static int legacy_gadget_open(struct hw_info *info,
593 const char *id, struct hw_common **common)
595 struct usb_client *legacy;
597 if (!info || !common)
600 legacy = zalloc(sizeof(*legacy));
604 legacy->common.info = info;
605 legacy->get_current_gadget = legacy_get_current_gadget;
606 legacy->reconfigure_gadget = legacy_reconfigure_gadget;
607 legacy->is_gadget_supported = legacy_is_gadget_supported;
608 legacy->is_function_supported = legacy_is_function_supported;
609 legacy->enable = legacy_enable;
610 legacy->disable = legacy_disable;
611 legacy->free_gadget = legacy_free_gadget;
613 *common = &legacy->common;
617 static int legacy_gadget_close(struct hw_common *common)
619 struct usb_client *legacy;
624 legacy = container_of(common, struct usb_client,
631 HARDWARE_MODULE_STRUCTURE = {
632 .magic = HARDWARE_INFO_TAG,
633 .hal_version = HARDWARE_INFO_VERSION,
634 .device_version = USB_CLIENT_HARDWARE_DEVICE_VERSION,
635 .id = USB_CLIENT_HARDWARE_DEVICE_ID,
636 .name = "legacy-gadget",
637 .open = legacy_gadget_open,
638 .close = legacy_gadget_close,