Refactoring: replace ffs_service to is_functionfs
[platform/core/system/libdevice-node.git] / hw / usb_cfs_client_common.c
index b3ddee2..39dfca2 100644 (file)
@@ -26,6 +26,7 @@
 #include <sys/types.h>
 #include <sys/mount.h>
 #include <usbg/usbg.h>
+#include <usbg/function/net.h>
 #include <unistd.h>
 
 #include <libsyscommon/dbus-systemd.h>
@@ -205,7 +206,7 @@ static int cfs_find_func(const char *name, const char *instance)
 {
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(_available_funcs); ++i)
+       for (i = 0; _available_funcs[i]; ++i)
                if (cfs_match_func(_available_funcs[i], name, instance))
                        return i;
 
@@ -496,18 +497,12 @@ static bool cfs_is_function_supported(struct usb_client *usb,
        bool res;
        int ret;
 
-       switch (func->function_group) {
-       case USB_FUNCTION_GROUP_SIMPLE:
-       case USB_FUNCTION_GROUP_WITH_POST_SERVICE:
+       if (!func->is_functionfs) {
                ret = usbg_lookup_function_type(func->name);
                res = ret >= 0;
-               break;
-       case USB_FUNCTION_GROUP_WITH_SERVICE:
+       } else {
                /* TODO: Check if socket is available */
                res = true;
-               break;
-       default:
-               res = false;
        }
 
        return res;
@@ -612,6 +607,8 @@ static int cfs_prep_ffs_service(const char *name, const char *instance,
        int ret;
 
        /* TODO: Add some good error handling */
+       if (!socket_name)
+               return -EINVAL;
 
        left = sizeof(buf);
        pos = buf;
@@ -662,6 +659,37 @@ umount_ffs:
        return ret;
 }
 
+static int cfs_set_rndis_mac_addr(usbg_gadget *gadget, usbg_function *func)
+{
+       int i, ret;
+       struct ether_addr ethaddr;
+       struct usbg_gadget_strs strs;
+       struct usbg_f_net *nf = usbg_to_net_function(func);
+
+       if (!nf)
+               return -EINVAL;
+
+       ret = usbg_get_gadget_strs(gadget, LANG_US_ENG, &strs);
+       if (ret != USBG_SUCCESS)
+               return ret;
+
+       for (i = 0; i < ETHER_ADDR_LEN; i++)
+               ethaddr.ether_addr_octet[i] = 0;
+
+       for (i = 0; (i < 256) && strs.serial[i]; i++) {
+               ethaddr.ether_addr_octet[i % (ETHER_ADDR_LEN - 1) + 1] ^= strs.serial[i];
+       }
+       ethaddr.ether_addr_octet[0] &= 0xfe;     /* clear multicast bit */
+       ethaddr.ether_addr_octet[0] |= 0x02;     /* set local assignment bit (IEEE802) */
+
+       usbg_free_gadget_strs(&strs);
+
+       /* host_addr changes mac address */
+       ret = usbg_f_net_set_host_addr(nf, &ethaddr);
+
+       return ret;
+}
+
 static int cfs_set_gadget_config(struct cfs_client *cfs_client,
                                    int config_id,
                                    struct usb_configuration *usb_config)
@@ -702,28 +730,21 @@ static int cfs_set_gadget_config(struct cfs_client *cfs_client,
                int type;
                usbg_function *func;
 
-               switch (usb_func->function_group) {
-               case USB_FUNCTION_GROUP_SIMPLE:
-               case USB_FUNCTION_GROUP_WITH_POST_SERVICE:
+               if (!usb_func->is_functionfs) {
                        type = usbg_lookup_function_type(usb_func->name);
                        if (strlen(usb_func->instance) >= MAX_INSTANCE_LEN)
                                return -ENAMETOOLONG;
                        strncpy(instance, usb_func->instance, MAX_INSTANCE_LEN);
                        instance[MAX_INSTANCE_LEN - 1] = '\0';
-                       break;
-               case USB_FUNCTION_GROUP_WITH_SERVICE:
+               } else {
                        type = USBG_F_FFS;
                        ret = snprintf(instance, sizeof(instance), "%s%c%s",
                                       usb_func->name, NAME_INSTANCE_SEP,
                                       usb_func->instance);
                        if (ret < 0 || ret >= sizeof(instance))
                                return -ENAMETOOLONG;
-                       break;
-               default:
-                       return -EINVAL;
                }
 
-
                func = usbg_get_function(cfs_client->gadget, type, instance);
                if (!func) {
                        ret = usbg_create_function(cfs_client->gadget,
@@ -733,21 +754,20 @@ static int cfs_set_gadget_config(struct cfs_client *cfs_client,
                        if (ret)
                                return ret;
 
-                       if (usb_func->function_group ==
-                           USB_FUNCTION_GROUP_WITH_SERVICE) {
-                               struct usb_function_with_service *fws;
+                       /* Setting rndis mac address. This should be done at this point,
+                        * since the node host_addr changes to read only after the function
+                        * is added to config. */
+                       if (usbg_get_function_type(func) == USBG_F_RNDIS)
+                               (void)cfs_set_rndis_mac_addr(cfs_client->gadget, func); /* A random value is used if fails */
 
-                               fws = container_of(usb_func,
-                                                  struct usb_function_with_service,
-                                                  func);
+                       if (usb_func->is_functionfs) {
                                ret = cfs_prep_ffs_service(usb_func->name,
-                                                          usb_func->instance,
-                                                          instance,
-                                                          fws->service);
+                                                       usb_func->instance,
+                                                       instance,
+                                                       usb_func->service);
                                if (ret)
                                        return ret;
                        }
-
                }
 
                ret = usbg_add_config_function(config, NULL, func);
@@ -806,22 +826,6 @@ static int cfs_reconfigure_gadget(struct usb_client *usb,
                        goto out;
        }
 
-       /* Workaround for enabling extcon notification */
-       /* ******************************************* */
-       /* ******************************************* */
-       {
-               const char *ARTIK_UDC_NAME = "c0040000.dwc2otg";
-               const char *udc_name = usbg_get_udc_name(cfs_client->udc);
-               if (udc_name && !strncmp(udc_name, ARTIK_UDC_NAME, strlen(ARTIK_UDC_NAME))) {
-                       ret = usbg_enable_gadget(cfs_client->gadget, cfs_client->udc);
-                       if (ret)
-                               goto out;
-               }
-       }
-       /* ******************************************* */
-       /* ******************************************* */
-       /* ******************************************* */
-
        ret = cfs_cleanup_left_configs(cfs_client, i);
 
        /* TODO
@@ -836,8 +840,8 @@ static int cfs_enable(struct usb_client *usb)
        int i;
        int ret;
        struct usb_gadget *gadget;
+       struct usb_function *func;
        struct cfs_client *cfs_client;
-       struct usb_function_with_service *fws;
 
        if (!usb)
                return -EINVAL;
@@ -854,11 +858,14 @@ static int cfs_enable(struct usb_client *usb)
        }
 
        for (i = 0; gadget->funcs[i]; ++i) {
-               if (gadget->funcs[i]->function_group != USB_FUNCTION_GROUP_WITH_POST_SERVICE)
-                       continue;
+               func = gadget->funcs[i];
 
-               fws = container_of(gadget->funcs[i], struct usb_function_with_service, func);
-               (void)systemd_start_unit_wait_started(fws->service, ".service", -1);
+               if (func->handler)
+                       func->handler(1);
+
+               /* functionfs service is automatically started by socket activation */
+               if (!func->is_functionfs && func->service)
+                       (void)systemd_start_unit_wait_started(func->service, ".service", -1);
        }
 
        cfs_free_gadget(gadget);
@@ -871,8 +878,8 @@ static int cfs_disable(struct usb_client *usb)
        int i;
        int ret;
        struct usb_gadget *gadget;
+       struct usb_function *func;
        struct cfs_client *cfs_client;
-       struct usb_function_with_service *fws;
 
        if (!usb)
                return -EINVAL;
@@ -882,17 +889,33 @@ static int cfs_disable(struct usb_client *usb)
                return ret;
 
        for (i = 0; gadget->funcs[i]; ++i) {
-               if (gadget->funcs[i]->function_group != USB_FUNCTION_GROUP_WITH_POST_SERVICE)
-                       continue;
+               func = gadget->funcs[i];
 
-               fws = container_of(gadget->funcs[i], struct usb_function_with_service, func);
-               (void)systemd_stop_unit_wait_stopped(fws->service, ".service", -1);
+               if (!func->is_functionfs && func->service)
+                       (void)systemd_stop_unit_wait_stopped(func->service, ".service", -1);
+
+               if (func->handler)
+                       func->handler(0);
+       }
+
+       cfs_client = container_of(usb, struct cfs_client, client);
+       ret = usbg_disable_gadget(cfs_client->gadget); /* ignore error checking */
+
+       /*
+        * Since functionfs service works with socket activation, you must stop it after disabling gadget.
+        * If usb data may come in after stopping functionfs service and before disabling gadget,
+        * functionfs service wakes up again by socket activation.
+        */
+       for (i = 0; gadget->funcs[i]; ++i) {
+               func = gadget->funcs[i];
+
+               if (func->is_functionfs && func->service)
+                       (void)systemd_stop_unit_wait_stopped(func->service, ".service", -1);
        }
 
        cfs_free_gadget(gadget);
 
-       cfs_client = container_of(usb, struct cfs_client, client);
-       return usbg_disable_gadget(cfs_client->gadget);
+       return ret;
 }
 
 EXPORT
@@ -970,15 +993,10 @@ int hw_cfs_gadget_close(struct hw_common *common)
                        continue;
 
                usb_func = _available_funcs[ret];
-               if (usb_func->function_group ==
-                   USB_FUNCTION_GROUP_WITH_SERVICE) {
-                       struct usb_function_with_service *fws;
-
-                       fws = container_of(usb_func,
-                                          struct usb_function_with_service,
-                                          func);
-                       systemd_stop_unit_wait_stopped(fws->service, ".socket", -1);
-                       systemd_stop_unit_wait_stopped(fws->service, ".service", -1);
+
+               if (usb_func->is_functionfs && usb_func->service) {
+                       (void)systemd_stop_unit_wait_stopped(usb_func->service, ".socket", -1);
+                       (void)systemd_stop_unit_wait_stopped(usb_func->service, ".service", -1);
                }
        }