summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYoungjae Cho <y0.cho@samsung.com>2022-03-18 11:39:29 +0900
committerYoungjae Cho <y0.cho@samsung.com>2022-03-18 12:28:08 +0900
commit2cac696825e5c4a44c9076366e6ce7c2a1debc08 (patch)
tree602c01d647050631cce9fdff9031953c2cb77e1c
parent5e7ac0009024f529bee10090e7a56efb568d4c69 (diff)
downloaddevice-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>
-rw-r--r--src/usb_gadget/usb_cfs_client_common.c4
-rw-r--r--src/usb_gadget/usb_client_common.c2
-rw-r--r--src/usb_gadget/usb_gadget.h30
-rw-r--r--src/usb_gadget/usb_gadget_common.c215
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;