#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>
{
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;
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;
int ret;
/* TODO: Add some good error handling */
+ if (!socket_name)
+ return -EINVAL;
left = sizeof(buf);
pos = buf;
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, ðaddr);
+
+ return ret;
+}
+
static int cfs_set_gadget_config(struct cfs_client *cfs_client,
int config_id,
struct usb_configuration *usb_config)
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,
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);
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
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;
}
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);
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;
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
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);
}
}