if (func->service)
(void)systemd_start_unit_wait_started(func->service, ".service", -1);
+
+ /* func->ffs_service is automatically started by socket activation */
}
cfs_free_gadget(gadget);
func->handler(0);
}
+ cfs_client = container_of(usb, struct cfs_client, client);
+ ret = usbg_disable_gadget(cfs_client->gadget); /* ignore error checking */
+
+ /*
+ * Since ffs_service works with socket activation, you must stop it after disabling gadget.
+ * If usb data may come in after stopping ffs_service and before disabling gadget,
+ * ffs_service wakes up again by socket activation.
+ */
+ for (i = 0; gadget->funcs[i]; ++i) {
+ func = gadget->funcs[i];
+
+ if (func->ffs_service)
+ (void)systemd_stop_unit_wait_stopped(func->ffs_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
* legacy enable(usb plug) : enable gadget -> handler(1) -> ffs_service start -> service start
* legacy disable(usb unplug) : service stop -> ffs_service stop -> handler(0) -> disable gadget
*
- * configfs init(booting) : ffs_service start
- * configfs enable(usb plug) : enable gadget -> handler(1) -> service start
- * configfs disable(usb unplug) : service stop -> handler(0) -> disable gadget
- * configfs deinit : ffs_service stop
+ * configfs init(booting) : ffs_service.socket start
+ * configfs enable(usb plug)* : enable gadget -> handler(1) -> service start
+ * configfs disable(usb unplug) : service stop -> handler(0) -> disable gadget -> ffs_service.service stop
+ * configfs deinit : ffs_service.socket stop
+ *
+ * Since ffs_service works by socket activation, it will be started automatically when data is enqueued to the usb socket.
+ * So when enabling configfs gadget, it doesn't start ffs_service.
*/
struct usb_function {
int id;