diff options
author | Youngjae Cho <y0.cho@samsung.com> | 2022-03-18 11:39:29 +0900 |
---|---|---|
committer | Youngjae Cho <y0.cho@samsung.com> | 2022-03-18 12:28:08 +0900 |
commit | 2cac696825e5c4a44c9076366e6ce7c2a1debc08 (patch) | |
tree | 602c01d647050631cce9fdff9031953c2cb77e1c /src | |
parent | 5e7ac0009024f529bee10090e7a56efb568d4c69 (diff) | |
download | device-common-2cac696825e5c4a44c9076366e6ce7c2a1debc08.tar.gz device-common-2cac696825e5c4a44c9076366e6ce7c2a1debc08.tar.bz2 device-common-2cac696825e5c4a44c9076366e6ce7c2a1debc08.zip |
usb-gadget: introduce configurable usb-gadget
Change-Id: I9e71df155d10c7d2a413546b97a2a6ab2993a50e
Signed-off-by: Youngjae Cho <y0.cho@samsung.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/usb_gadget/usb_cfs_client_common.c | 4 | ||||
-rw-r--r-- | src/usb_gadget/usb_client_common.c | 2 | ||||
-rw-r--r-- | src/usb_gadget/usb_gadget.h | 30 | ||||
-rw-r--r-- | src/usb_gadget/usb_gadget_common.c | 215 |
4 files changed, 166 insertions, 85 deletions
diff --git a/src/usb_gadget/usb_cfs_client_common.c b/src/usb_gadget/usb_cfs_client_common.c index 69e3720..5f2f959 100644 --- a/src/usb_gadget/usb_cfs_client_common.c +++ b/src/usb_gadget/usb_cfs_client_common.c @@ -507,7 +507,7 @@ static void cfs_start_stop_service_and_handler(usbg_gadget *gadget, enum cfs_fun break; case CFS_FUNCTION_SERVICE_STOP: - if (!usb_function->is_functionfs && usb_function->service) + if (!usb_function->is_functionfs && usb_function->service && !usb_function->remain_after_disable) (void)systemd_stop_unit_wait_stopped(usb_function->service, ".service", -1); if (usb_function->handler) @@ -515,7 +515,7 @@ static void cfs_start_stop_service_and_handler(usbg_gadget *gadget, enum cfs_fun break; case CFS_FUNCTION_SERVICE_POST_STOP: - if (usb_function->is_functionfs && usb_function->service) + if (usb_function->is_functionfs && usb_function->service && !usb_function->remain_after_disable) (void)systemd_stop_unit_wait_stopped(usb_function->service, ".service", -1); break; diff --git a/src/usb_gadget/usb_client_common.c b/src/usb_gadget/usb_client_common.c index c6743f9..a4699f8 100644 --- a/src/usb_gadget/usb_client_common.c +++ b/src/usb_gadget/usb_client_common.c @@ -313,7 +313,7 @@ second_configuration: if (funcs[i]->service) (void)systemd_start_unit_wait_started(funcs[i]->service, ".service", -1); } else { - if (funcs[i]->service) + if (funcs[i]->service && !funcs[i]->remain_after_disable) (void)systemd_stop_unit_wait_stopped(funcs[i]->service, ".service", -1); if (funcs[i]->handler) diff --git a/src/usb_gadget/usb_gadget.h b/src/usb_gadget/usb_gadget.h index 507196a..1f66457 100644 --- a/src/usb_gadget/usb_gadget.h +++ b/src/usb_gadget/usb_gadget.h @@ -17,6 +17,36 @@ #ifndef __HW_USB_GADGET_H__ #define __HW_USB_GADGET_H__ +/************************************** + * Those symbols must be initialized first in deviced + * + * The usb-gadget source code have been scattered throughout the deviced and device-common. + * Because of this, it might have been implemented that totally same data structure on the + * both side. To avoid this inefficiency, define/initialize the data structure on the + * deviced first, and device-common refer it through extern keyword. The deviced must have + * cflag -rdynamic or ldflag --export-dynamic so that the dlopen-ed device-common can refer + * those variables with extern keyword. + * + * Accessing symbol in this way would be removed when the usb-gadget of the device-common + * is integrated into the deviced. + */ +#include <glib.h> +#include <hal/device/hal-usb_gadget-interface.h> + +struct _usb_mode_mapping_table { + int mode_v; /* Integer defined by vconf */ + unsigned int mode; /* Bitmap of usb function combination */ + struct usb_gadget_attrs attrs; +}; +extern GList *usb_mode_mapping_table_custom; + +struct service_config { + char name[128]; + int remain_after_disable; +}; +extern GList *service_config_list; +/**************************************/ + struct usb_function *find_usb_function_by_id(int id); struct usb_function *find_usb_function_by_name(const char *name); struct usb_function *find_usb_function_by_name_instance(const char *name, const char *instance); diff --git a/src/usb_gadget/usb_gadget_common.c b/src/usb_gadget/usb_gadget_common.c index 5d0ffb0..3233604 100644 --- a/src/usb_gadget/usb_gadget_common.c +++ b/src/usb_gadget/usb_gadget_common.c @@ -20,6 +20,7 @@ #include <unistd.h> #include <libsyscommon/libsystemd.h> +#include <libsyscommon/list.h> #include <hal/device/hal-usb_gadget-interface.h> #include "usb_gadget.h" @@ -129,6 +130,9 @@ static int id_to_gadget(struct usb_gadget_id *gadget_id, char *serial, struct us struct usb_gadget *gadget; int functions[2][sizeof(gadget_id->function_mask)*8]; /* zero terminates */ + GList *elem; + const struct _usb_mode_mapping_table *cm = NULL; + if (!gadget_id || !serial || !_gadget) return -EINVAL; @@ -136,91 +140,115 @@ static int id_to_gadget(struct usb_gadget_id *gadget_id, char *serial, struct us if (ret) goto out; - /* - * Currently all gadgets use inly single configuration but - * slp-gadget is capable to handle two of them - * - * Order of interfaces in configuration is significant - * so in this switch we sort our functions in a correct order - */ - switch (gadget_id->function_mask) { - /* MTP, ACM, SDB */ - case USB_FUNCTION_MTP | USB_FUNCTION_ACM: - n_configs = 1; - functions[0][0] = USB_FUNCTION_MTP; - functions[0][1] = USB_FUNCTION_ACM; - functions[0][2] = 0; - gadget->attrs.idProduct = 0x6860; - break; - - case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB: - n_configs = 1; - functions[0][0] = USB_FUNCTION_MTP; - functions[0][1] = USB_FUNCTION_ACM; - functions[0][2] = USB_FUNCTION_SDB; - functions[0][3] = 0; - gadget->attrs.idProduct = 0x6860; - break; - - /* DIAG */ - case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DIAG: - n_configs = 1; - functions[0][0] = USB_FUNCTION_MTP; - functions[0][1] = USB_FUNCTION_ACM; - functions[0][2] = USB_FUNCTION_SDB; - functions[0][3] = USB_FUNCTION_DIAG; - functions[0][4] = 0; - gadget->attrs.idProduct = 0x6860; - break; - - /* RNDIS */ - case USB_FUNCTION_RNDIS: - n_configs = 1; - functions[0][0] = USB_FUNCTION_RNDIS; - functions[0][1] = 0; - gadget->attrs.idProduct = 0x6863; - break; + /* find custom mode */ + SYS_G_LIST_FOREACH(usb_mode_mapping_table_custom, elem, cm) { + if (cm->mode == gadget_id->function_mask) + break; + } - case USB_FUNCTION_RNDIS | USB_FUNCTION_DIAG: - n_configs = 1; - functions[0][0] = USB_FUNCTION_RNDIS; - functions[0][1] = USB_FUNCTION_DIAG; - functions[0][2] = 0; - gadget->attrs.idProduct = 0x6864; - break; + if (cm) { + int i, j; - case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS: - n_configs = 1; - functions[0][0] = USB_FUNCTION_RNDIS; - functions[0][1] = USB_FUNCTION_ACM; - functions[0][2] = USB_FUNCTION_SDB; - functions[0][3] = 0; - gadget->attrs.idProduct = 0x6864; - break; - - /* RMNET */ - case USB_FUNCTION_DIAG | USB_FUNCTION_RMNET: - n_configs = 1; - functions[0][0] = USB_FUNCTION_DIAG; - functions[0][1] = USB_FUNCTION_RMNET; - functions[0][2] = 0; - gadget->attrs.idProduct = 0x685d; - break; - - /* DM */ - case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DM: + j = 0; n_configs = 1; - functions[0][0] = USB_FUNCTION_ACM; - functions[0][1] = USB_FUNCTION_SDB; - functions[0][2] = USB_FUNCTION_DM; - functions[0][3] = 0; - gadget->attrs.idProduct = 0x6860; - break; - - default: - ret = -EINVAL; - goto free_gadget; - }; + for (i = 0; i < USB_FUNCTION_IDX_MAX; ++i) { + if (cm->mode & (1 << i)) + functions[0][j++] = (1 << i); + } + functions[0][j] = 0; + + if (cm->attrs.idVendor) + gadget->attrs.idVendor = cm->attrs.idVendor; + if (cm->attrs.idProduct) + gadget->attrs.idProduct = cm->attrs.idProduct; + + } else { + /* + * Currently all gadgets use inly single configuration but + * slp-gadget is capable to handle two of them + * + * Order of interfaces in configuration is significant + * so in this switch we sort our functions in a correct order + */ + switch (gadget_id->function_mask) { + /* MTP, ACM, SDB */ + case USB_FUNCTION_MTP | USB_FUNCTION_ACM: + n_configs = 1; + functions[0][0] = USB_FUNCTION_MTP; + functions[0][1] = USB_FUNCTION_ACM; + functions[0][2] = 0; + gadget->attrs.idProduct = 0x6860; + break; + + case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB: + n_configs = 1; + functions[0][0] = USB_FUNCTION_MTP; + functions[0][1] = USB_FUNCTION_ACM; + functions[0][2] = USB_FUNCTION_SDB; + functions[0][3] = 0; + gadget->attrs.idProduct = 0x6860; + break; + + /* DIAG */ + case USB_FUNCTION_MTP | USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DIAG: + n_configs = 1; + functions[0][0] = USB_FUNCTION_MTP; + functions[0][1] = USB_FUNCTION_ACM; + functions[0][2] = USB_FUNCTION_SDB; + functions[0][3] = USB_FUNCTION_DIAG; + functions[0][4] = 0; + gadget->attrs.idProduct = 0x6860; + break; + + /* RNDIS */ + case USB_FUNCTION_RNDIS: + n_configs = 1; + functions[0][0] = USB_FUNCTION_RNDIS; + functions[0][1] = 0; + gadget->attrs.idProduct = 0x6863; + break; + + case USB_FUNCTION_RNDIS | USB_FUNCTION_DIAG: + n_configs = 1; + functions[0][0] = USB_FUNCTION_RNDIS; + functions[0][1] = USB_FUNCTION_DIAG; + functions[0][2] = 0; + gadget->attrs.idProduct = 0x6864; + break; + + case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_RNDIS: + n_configs = 1; + functions[0][0] = USB_FUNCTION_RNDIS; + functions[0][1] = USB_FUNCTION_ACM; + functions[0][2] = USB_FUNCTION_SDB; + functions[0][3] = 0; + gadget->attrs.idProduct = 0x6864; + break; + + /* RMNET */ + case USB_FUNCTION_DIAG | USB_FUNCTION_RMNET: + n_configs = 1; + functions[0][0] = USB_FUNCTION_DIAG; + functions[0][1] = USB_FUNCTION_RMNET; + functions[0][2] = 0; + gadget->attrs.idProduct = 0x685d; + break; + + /* DM */ + case USB_FUNCTION_ACM | USB_FUNCTION_SDB | USB_FUNCTION_DM: + n_configs = 1; + functions[0][0] = USB_FUNCTION_ACM; + functions[0][1] = USB_FUNCTION_SDB; + functions[0][2] = USB_FUNCTION_DM; + functions[0][3] = 0; + gadget->attrs.idProduct = 0x6860; + break; + + default: + ret = -EINVAL; + goto free_gadget; + }; + } for (j = 0; j < n_configs; ++j) { int n_funcs_in_config; @@ -271,6 +299,7 @@ void rndis_handler(int enable) .instance = "default", \ .is_functionfs = _is_functionfs, \ .service = _service, \ + .remain_after_disable = 0, \ .handler = _handler, \ } @@ -337,12 +366,34 @@ struct usb_function *find_usb_function_by_name_instance(const char *name, const return NULL; } +static void set_service_config(gpointer data, gpointer udata) +{ + struct service_config *svc = (struct service_config *) data; + int i; + + for (i = 0; _available_funcs[i]; ++i) { + if (!strcmp(svc->name, _available_funcs[i]->name)) { + _available_funcs[i]->remain_after_disable = svc->remain_after_disable; + _I("%s: remain_after_disable=%d", svc->name, svc->remain_after_disable); + } + } +} + EXPORT int simple_translator_open(hal_backend_usb_gadget_funcs *usb_gadget_funcs) { if (!usb_gadget_funcs) return -EINVAL; + /* e.g. + * /hal/etc/deviced/usb_gadget.conf + * + * [SystemdUnit] + * Name=diag.service + * RemainAfterDisable=yes + */ + g_list_foreach(service_config_list, set_service_config, NULL); + usb_gadget_funcs->id_to_gadget = id_to_gadget; usb_gadget_funcs->cleanup_gadget = cleanup_gadget; |