summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorINSUN PYO <insun.pyo@samsung.com>2020-03-19 11:43:30 +0900
committerINSUN PYO <insun.pyo@samsung.com>2020-03-19 03:55:46 +0000
commit7803a3c5a1b0293a5bda490c26c95ae8b967e001 (patch)
treec17d758d364f106093ef7d59f4f81c1ceeee5d62
parent52e9dce09444267176cc1aade368944aadf8cc58 (diff)
downloadlibdevice-node-7803a3c5a1b0293a5bda490c26c95ae8b967e001.tar.gz
libdevice-node-7803a3c5a1b0293a5bda490c26c95ae8b967e001.tar.bz2
libdevice-node-7803a3c5a1b0293a5bda490c26c95ae8b967e001.zip
Fixed a possibility that the function handler might be called twice
Configfs can use more than one configs. (/sys/kernel/config/usb_gadget/hal-gadget/configs/hal-config.1 and /sys/kernel/config/usb_gadget/hal-gadget/configs/hal-config.2) One usb function can be included in two config simultaneously. In this situation, a handler associated with function can be called twice for a usb function. To prevent duplicate calls, it handles only the handlers of functions enabled in configfs, not the usb functions included in all configs. Change-Id: I5e02dadc5d2688f0ad9210ad5ab149fb95ab05ba
-rw-r--r--hw/usb_cfs_client_common.c92
1 files changed, 47 insertions, 45 deletions
diff --git a/hw/usb_cfs_client_common.c b/hw/usb_cfs_client_common.c
index 12e73c4..846eb77 100644
--- a/hw/usb_cfs_client_common.c
+++ b/hw/usb_cfs_client_common.c
@@ -16,8 +16,8 @@
* limitations under the License.
*/
-#include <string.h>
#include <errno.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mount.h>
@@ -28,11 +28,6 @@
#include <hw/usb_client.h>
-#define zalloc(amount) calloc(1, amount)
-
-#define MAX_GADGET_STR_LEN 256
-#define MAX_FUNCS 32
-
#define CONFIGFS_PATH "/sys/kernel/config"
#define CONFIGFS_GADGET_NAME "hal-gadget"
@@ -47,6 +42,12 @@
#define EXPORT __attribute__ ((visibility("default")))
#endif
+enum cfs_function_service_operation {
+ CFS_FUNCTION_SERVICE_START,
+ CFS_FUNCTION_SERVICE_STOP,
+ CFS_FUNCTION_SERVICE_POST_STOP,
+};
+
struct cfs_client {
struct usb_client client;
usbg_state *ctx;
@@ -556,48 +557,49 @@ out:
return ret;
}
-static void cfs_start_stop_service_handler(usbg_gadget *gadget, bool start, bool post_stop)
+static void cfs_start_stop_service_and_handler(usbg_gadget *gadget, enum cfs_function_service_operation operation)
{
int index;
const char *name;
const char *instance;
- usbg_config *config;
- usbg_binding *binding;
usbg_function *function;
struct usb_function *usb_function;
- /* Execute service and handler related to functions bound to configs */
- usbg_for_each_config(config, gadget) {
- usbg_for_each_binding(binding, config) {
- function = usbg_get_binding_target(binding);
- instance = usbg_get_function_instance(function);
- name = usbg_get_function_type_str(usbg_get_function_type(function));
-
- index = cfs_find_func(name, instance);
- if (index < 0)
- continue;
-
- usb_function = _available_funcs[index];
-
- if (start) {
- if (usb_function->handler)
- usb_function->handler(1);
-
- /* functionfs service is automatically started by socket activation */
- if (!usb_function->is_functionfs && usb_function->service)
- (void)systemd_start_unit_wait_started(usb_function->service, ".service", -1);
- } else {
- if (post_stop) {
- if (usb_function->is_functionfs && usb_function->service)
- (void)systemd_stop_unit_wait_stopped(usb_function->service, ".service", -1);
- } else {
- if (!usb_function->is_functionfs && usb_function->service)
- (void)systemd_stop_unit_wait_stopped(usb_function->service, ".service", -1);
-
- if (usb_function->handler)
- usb_function->handler(0);
- }
- }
+ usbg_for_each_function(function, gadget) {
+ instance = usbg_get_function_instance(function);
+ name = usbg_get_function_type_str(usbg_get_function_type(function));
+
+ index = cfs_find_func(name, instance);
+ if (index < 0)
+ continue;
+
+ usb_function = _available_funcs[index];
+
+ switch(operation) {
+ case CFS_FUNCTION_SERVICE_START:
+ if (usb_function->handler)
+ usb_function->handler(1);
+
+ /* functionfs service is automatically started by socket activation */
+ if (!usb_function->is_functionfs && usb_function->service)
+ (void)systemd_start_unit_wait_started(usb_function->service, ".service", -1);
+ break;
+
+ case CFS_FUNCTION_SERVICE_STOP:
+ if (!usb_function->is_functionfs && usb_function->service)
+ (void)systemd_stop_unit_wait_stopped(usb_function->service, ".service", -1);
+
+ if (usb_function->handler)
+ usb_function->handler(0);
+ break;
+
+ case CFS_FUNCTION_SERVICE_POST_STOP:
+ if (usb_function->is_functionfs && usb_function->service)
+ (void)systemd_stop_unit_wait_stopped(usb_function->service, ".service", -1);
+ break;
+
+ default:
+ break;
}
}
}
@@ -616,7 +618,7 @@ static int cfs_enable(struct usb_client *usb)
if (ret)
return ret;
- cfs_start_stop_service_handler(cfs_client->gadget, true, false);
+ cfs_start_stop_service_and_handler(cfs_client->gadget, CFS_FUNCTION_SERVICE_START);
return 0;
}
@@ -631,7 +633,7 @@ static int cfs_disable(struct usb_client *usb)
cfs_client = container_of(usb, struct cfs_client, client);
- cfs_start_stop_service_handler(cfs_client->gadget, false, false);
+ cfs_start_stop_service_and_handler(cfs_client->gadget, CFS_FUNCTION_SERVICE_STOP);
ret = usbg_disable_gadget(cfs_client->gadget); /* ignore error checking */
@@ -640,7 +642,7 @@ static int cfs_disable(struct usb_client *usb)
* If usb data may come in after stopping functionfs service and before disabling gadget,
* functionfs service wakes up again by socket activation.
*/
- cfs_start_stop_service_handler(cfs_client->gadget, false, true);
+ cfs_start_stop_service_and_handler(cfs_client->gadget, CFS_FUNCTION_SERVICE_POST_STOP);
return ret;
}
@@ -655,7 +657,7 @@ int hw_cfs_gadget_open(struct hw_info *info,
if (!info || !common)
return -EINVAL;
- cfs_client = zalloc(sizeof(*cfs_client));
+ cfs_client = calloc(1, sizeof(*cfs_client));
if (!cfs_client)
return -ENOMEM;