Loading drivers/usb/gadget/Kconfig +5 −3 Original line number Diff line number Diff line Loading @@ -96,8 +96,8 @@ config USB_GADGET_DEBUG_FS to conserve kernel memory, say "N". config USB_GADGET_VBUS_DRAW int "Maximum VBUS Power usage (2-500 mA)" range 2 500 int "Maximum VBUS Power usage (2-900 mA)" range 2 900 default 2 help Some devices need to draw power from USB when they are Loading @@ -106,7 +106,9 @@ config USB_GADGET_VBUS_DRAW such as an AC adapter or batteries. Enter the maximum power your device draws through USB, in milliAmperes. The permitted range of values is 2 - 500 mA; milliAmperes. The permitted range of values depends on the connected speed: for SuperSpeed and up it is 2 - 900 mA, but connections at High Speed or slower will be capped at 500 mA; 0 mA would be legal, but can make some hosts misbehave. This value will be used except for system-specific gadget Loading drivers/usb/gadget/composite.c +135 −3 Original line number Diff line number Diff line Loading @@ -266,6 +266,7 @@ int usb_add_function(struct usb_configuration *config, goto done; function->config = config; function->intf_id = -EINVAL; list_add_tail(&function->list, &config->functions); if (function->bind_deactivated) { Loading Loading @@ -419,6 +420,8 @@ int usb_interface_id(struct usb_configuration *config, if (id < MAX_CONFIG_INTERFACES) { config->interface[id] = function; if (function->intf_id < 0) function->intf_id = id; config->next_interface_id = id + 1; return id; } Loading @@ -426,6 +429,101 @@ int usb_interface_id(struct usb_configuration *config, } EXPORT_SYMBOL_GPL(usb_interface_id); static int usb_func_wakeup_int(struct usb_function *func) { int ret; struct usb_gadget *gadget; pr_debug("%s - %s function wakeup\n", __func__, func->name ? func->name : ""); if (!func || !func->config || !func->config->cdev || !func->config->cdev->gadget) return -EINVAL; gadget = func->config->cdev->gadget; if ((gadget->speed != USB_SPEED_SUPER) || !func->func_wakeup_allowed) { DBG(func->config->cdev, "Function Wakeup is not possible. speed=%u, func_wakeup_allowed=%u\n", gadget->speed, func->func_wakeup_allowed); return -ENOTSUPP; } ret = usb_gadget_func_wakeup(gadget, func->intf_id); return ret; } int usb_func_wakeup(struct usb_function *func) { int ret; unsigned long flags; pr_debug("%s function wakeup\n", func->name ? func->name : ""); spin_lock_irqsave(&func->config->cdev->lock, flags); ret = usb_func_wakeup_int(func); if (ret == -EAGAIN) { DBG(func->config->cdev, "Function wakeup for %s could not complete due to suspend state. Delayed until after bus resume.\n", func->name ? func->name : ""); ret = 0; } else if (ret < 0 && ret != -ENOTSUPP) { ERROR(func->config->cdev, "Failed to wake function %s from suspend state. ret=%d. Canceling USB request.\n", func->name ? func->name : "", ret); } spin_unlock_irqrestore(&func->config->cdev->lock, flags); return ret; } EXPORT_SYMBOL(usb_func_wakeup); int usb_func_ep_queue(struct usb_function *func, struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags) { int ret; struct usb_gadget *gadget; if (!func || !func->config || !func->config->cdev || !func->config->cdev->gadget || !ep || !req) { ret = -EINVAL; goto done; } pr_debug("Function %s queueing new data into ep %u\n", func->name ? func->name : "", ep->address); gadget = func->config->cdev->gadget; if (func->func_is_suspended && func->func_wakeup_allowed) { ret = usb_gadget_func_wakeup(gadget, func->intf_id); if (ret == -EAGAIN) { pr_debug("bus suspended func wakeup for %s delayed until bus resume.\n", func->name ? func->name : ""); } else if (ret < 0 && ret != -ENOTSUPP) { pr_err("Failed to wake function %s from suspend state. ret=%d.\n", func->name ? func->name : "", ret); } goto done; } if (!func->func_is_suspended) ret = 0; if (func->func_is_suspended && !func->func_wakeup_allowed) { ret = -ENOTSUPP; goto done; } ret = usb_ep_queue(ep, req, gfp_flags); done: return ret; } EXPORT_SYMBOL(usb_func_ep_queue); static u8 encode_bMaxPower(enum usb_device_speed speed, struct usb_configuration *c) { Loading @@ -441,7 +539,8 @@ static u8 encode_bMaxPower(enum usb_device_speed speed, case USB_SPEED_SUPER: return DIV_ROUND_UP(val, 8); default: return DIV_ROUND_UP(val, 2); /* only SuperSpeed and faster support > 500mA */ return DIV_ROUND_UP(min(val, 500U), 2); } } Loading Loading @@ -743,6 +842,11 @@ static void reset_config(struct usb_composite_dev *cdev) if (f->disable) f->disable(f); /* USB 3.0 addition */ f->func_is_suspended = false; f->func_wakeup_allowed = false; f->func_wakeup_pending = false; bitmap_zero(f->endpoints, 32); } cdev->config = NULL; Loading Loading @@ -1797,8 +1901,13 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) if (!f) break; value = 0; if (f->func_suspend) value = f->func_suspend(f, w_index >> 8); if (f->func_suspend) { const u8 suspend_opt = w_index >> 8; value = f->func_suspend(f, suspend_opt); DBG(cdev, "%s function: FUNCTION_SUSPEND(%u)", f->name ? f->name : "", suspend_opt); } if (value < 0) { ERROR(cdev, "func_suspend() returned error %d\n", Loading Loading @@ -2256,11 +2365,13 @@ void composite_suspend(struct usb_gadget *gadget) { struct usb_composite_dev *cdev = get_gadget_data(gadget); struct usb_function *f; unsigned long flags; /* REVISIT: should we have config level * suspend/resume callbacks? */ DBG(cdev, "suspend\n"); spin_lock_irqsave(&cdev->lock, flags); if (cdev->config) { list_for_each_entry(f, &cdev->config->functions, list) { if (f->suspend) Loading @@ -2271,6 +2382,7 @@ void composite_suspend(struct usb_gadget *gadget) cdev->driver->suspend(cdev); cdev->suspended = 1; spin_unlock_irqrestore(&cdev->lock, flags); usb_gadget_vbus_draw(gadget, 2); } Loading @@ -2280,6 +2392,8 @@ void composite_resume(struct usb_gadget *gadget) struct usb_composite_dev *cdev = get_gadget_data(gadget); struct usb_function *f; u16 maxpower; int ret; unsigned long flags; /* REVISIT: should we have config level * suspend/resume callbacks? Loading @@ -2287,8 +2401,25 @@ void composite_resume(struct usb_gadget *gadget) DBG(cdev, "resume\n"); if (cdev->driver->resume) cdev->driver->resume(cdev); spin_lock_irqsave(&cdev->lock, flags); if (cdev->config) { list_for_each_entry(f, &cdev->config->functions, list) { ret = usb_func_wakeup_int(f); if (ret) { if (ret == -EAGAIN) { ERROR(f->config->cdev, "Function wakeup for %s could not complete due to suspend state.\n", f->name ? f->name : ""); break; } else if (ret != -ENOTSUPP) { ERROR(f->config->cdev, "Failed to wake function %s from suspend state. ret=%d. Canceling USB request.\n", f->name ? f->name : "", ret); } } if (f->resume) f->resume(f); } Loading @@ -2299,6 +2430,7 @@ void composite_resume(struct usb_gadget *gadget) maxpower : CONFIG_USB_GADGET_VBUS_DRAW); } spin_unlock_irqrestore(&cdev->lock, flags); cdev->suspended = 0; } Loading drivers/usb/gadget/udc/core.c +21 −0 Original line number Diff line number Diff line Loading @@ -479,6 +479,27 @@ int usb_gadget_wakeup(struct usb_gadget *gadget) } EXPORT_SYMBOL_GPL(usb_gadget_wakeup); /** * usb_gadget_func_wakeup - send a function remote wakeup up notification * to the host connected to this gadget * @gadget: controller used to wake up the host * @interface_id: the interface which triggered the remote wakeup event * * Returns zero on success. Otherwise, negative error code is returned. */ int usb_gadget_func_wakeup(struct usb_gadget *gadget, int interface_id) { if (gadget->speed != USB_SPEED_SUPER) return -EOPNOTSUPP; if (!gadget->ops->func_wakeup) return -EOPNOTSUPP; return gadget->ops->func_wakeup(gadget, interface_id); } EXPORT_SYMBOL(usb_gadget_func_wakeup); /** * usb_gadget_set_selfpowered - sets the device selfpowered feature. * @gadget:the device being declared as self-powered Loading include/linux/usb/composite.h +16 −1 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ struct usb_os_desc_table { /** * struct usb_function - describes one function of a configuration * @name: For diagnostics, identifies the function. * @intf_id: Interface ID * @strings: tables of strings, keyed by identifiers assigned during bind() * and by language IDs provided in control requests * @fs_descriptors: Table of full (or low) speed descriptors, using interface and Loading Loading @@ -158,7 +159,14 @@ struct usb_os_desc_table { * @get_status: Returns function status as a reply to * GetStatus() request when the recipient is Interface. * @func_suspend: callback to be called when * SetFeature(FUNCTION_SUSPEND) is reseived * SetFeature(FUNCTION_SUSPEND) is received * @func_is_suspended: Tells whether the function is currently in * Function Suspend state (used in Super Speed mode only). * @func_wakeup_allowed: Tells whether Function Remote Wakeup has been allowed * by the USB host (used in Super Speed mode only). * @func_wakeup_pending: Marks that the function has issued a Function Wakeup * while the USB bus was suspended and therefore a Function Wakeup * notification needs to be sent once the USB bus is resumed. * * A single USB function uses one or more interfaces, and should in most * cases support operation at both full and high speeds. Each function is Loading Loading @@ -186,6 +194,7 @@ struct usb_os_desc_table { struct usb_function { const char *name; int intf_id; struct usb_gadget_strings **strings; struct usb_descriptor_header **fs_descriptors; struct usb_descriptor_header **hs_descriptors; Loading Loading @@ -229,6 +238,9 @@ struct usb_function { int (*get_status)(struct usb_function *); int (*func_suspend)(struct usb_function *, u8 suspend_opt); unsigned func_is_suspended:1; unsigned func_wakeup_allowed:1; unsigned func_wakeup_pending:1; /* private: */ /* internals */ struct list_head list; Loading @@ -244,6 +256,9 @@ int usb_function_deactivate(struct usb_function *); int usb_function_activate(struct usb_function *); int usb_interface_id(struct usb_configuration *, struct usb_function *); int usb_func_wakeup(struct usb_function *func); int usb_get_func_interface_id(struct usb_function *func); int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f, struct usb_ep *_ep); Loading include/linux/usb/gadget.h +22 −0 Original line number Diff line number Diff line Loading @@ -297,6 +297,7 @@ struct usb_udc; struct usb_gadget_ops { int (*get_frame)(struct usb_gadget *); int (*wakeup)(struct usb_gadget *); int (*func_wakeup)(struct usb_gadget *, int interface_id); int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered); int (*vbus_session) (struct usb_gadget *, int is_active); int (*vbus_draw) (struct usb_gadget *, unsigned mA); Loading Loading @@ -544,6 +545,7 @@ static inline int gadget_is_otg(struct usb_gadget *g) #if IS_ENABLED(CONFIG_USB_GADGET) int usb_gadget_frame_number(struct usb_gadget *gadget); int usb_gadget_wakeup(struct usb_gadget *gadget); int usb_gadget_func_wakeup(struct usb_gadget *gadget, int interface_id); int usb_gadget_set_selfpowered(struct usb_gadget *gadget); int usb_gadget_clear_selfpowered(struct usb_gadget *gadget); int usb_gadget_vbus_connect(struct usb_gadget *gadget); Loading @@ -558,6 +560,8 @@ static inline int usb_gadget_frame_number(struct usb_gadget *gadget) { return 0; } static inline int usb_gadget_wakeup(struct usb_gadget *gadget) { return 0; } static int usb_gadget_func_wakeup(struct usb_gadget *gadget, int interface_id) { return 0; } static inline int usb_gadget_set_selfpowered(struct usb_gadget *gadget) { return 0; } static inline int usb_gadget_clear_selfpowered(struct usb_gadget *gadget) Loading Loading @@ -796,6 +800,24 @@ int usb_otg_descriptor_init(struct usb_gadget *gadget, struct usb_descriptor_header *otg_desc); /*-------------------------------------------------------------------------*/ /** * usb_func_ep_queue - queues (submits) an I/O request to a function endpoint. * This function is similar to the usb_ep_queue function, but in addition it * also checks whether the function is in Super Speed USB Function Suspend * state, and if so a Function Wake notification is sent to the host * (USB 3.0 spec, section 9.2.5.2). * @func: the function which issues the USB I/O request. * @ep:the endpoint associated with the request * @req:the request being submitted * @gfp_flags: GFP_* flags to use in case the lower level driver couldn't * pre-allocate all necessary memory with the request. * */ int usb_func_ep_queue(struct usb_function *func, struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags); /*-------------------------------------------------------------------------*/ /* utility to simplify map/unmap of usb_requests to/from DMA */ extern int usb_gadget_map_request_by_dev(struct device *dev, Loading Loading
drivers/usb/gadget/Kconfig +5 −3 Original line number Diff line number Diff line Loading @@ -96,8 +96,8 @@ config USB_GADGET_DEBUG_FS to conserve kernel memory, say "N". config USB_GADGET_VBUS_DRAW int "Maximum VBUS Power usage (2-500 mA)" range 2 500 int "Maximum VBUS Power usage (2-900 mA)" range 2 900 default 2 help Some devices need to draw power from USB when they are Loading @@ -106,7 +106,9 @@ config USB_GADGET_VBUS_DRAW such as an AC adapter or batteries. Enter the maximum power your device draws through USB, in milliAmperes. The permitted range of values is 2 - 500 mA; milliAmperes. The permitted range of values depends on the connected speed: for SuperSpeed and up it is 2 - 900 mA, but connections at High Speed or slower will be capped at 500 mA; 0 mA would be legal, but can make some hosts misbehave. This value will be used except for system-specific gadget Loading
drivers/usb/gadget/composite.c +135 −3 Original line number Diff line number Diff line Loading @@ -266,6 +266,7 @@ int usb_add_function(struct usb_configuration *config, goto done; function->config = config; function->intf_id = -EINVAL; list_add_tail(&function->list, &config->functions); if (function->bind_deactivated) { Loading Loading @@ -419,6 +420,8 @@ int usb_interface_id(struct usb_configuration *config, if (id < MAX_CONFIG_INTERFACES) { config->interface[id] = function; if (function->intf_id < 0) function->intf_id = id; config->next_interface_id = id + 1; return id; } Loading @@ -426,6 +429,101 @@ int usb_interface_id(struct usb_configuration *config, } EXPORT_SYMBOL_GPL(usb_interface_id); static int usb_func_wakeup_int(struct usb_function *func) { int ret; struct usb_gadget *gadget; pr_debug("%s - %s function wakeup\n", __func__, func->name ? func->name : ""); if (!func || !func->config || !func->config->cdev || !func->config->cdev->gadget) return -EINVAL; gadget = func->config->cdev->gadget; if ((gadget->speed != USB_SPEED_SUPER) || !func->func_wakeup_allowed) { DBG(func->config->cdev, "Function Wakeup is not possible. speed=%u, func_wakeup_allowed=%u\n", gadget->speed, func->func_wakeup_allowed); return -ENOTSUPP; } ret = usb_gadget_func_wakeup(gadget, func->intf_id); return ret; } int usb_func_wakeup(struct usb_function *func) { int ret; unsigned long flags; pr_debug("%s function wakeup\n", func->name ? func->name : ""); spin_lock_irqsave(&func->config->cdev->lock, flags); ret = usb_func_wakeup_int(func); if (ret == -EAGAIN) { DBG(func->config->cdev, "Function wakeup for %s could not complete due to suspend state. Delayed until after bus resume.\n", func->name ? func->name : ""); ret = 0; } else if (ret < 0 && ret != -ENOTSUPP) { ERROR(func->config->cdev, "Failed to wake function %s from suspend state. ret=%d. Canceling USB request.\n", func->name ? func->name : "", ret); } spin_unlock_irqrestore(&func->config->cdev->lock, flags); return ret; } EXPORT_SYMBOL(usb_func_wakeup); int usb_func_ep_queue(struct usb_function *func, struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags) { int ret; struct usb_gadget *gadget; if (!func || !func->config || !func->config->cdev || !func->config->cdev->gadget || !ep || !req) { ret = -EINVAL; goto done; } pr_debug("Function %s queueing new data into ep %u\n", func->name ? func->name : "", ep->address); gadget = func->config->cdev->gadget; if (func->func_is_suspended && func->func_wakeup_allowed) { ret = usb_gadget_func_wakeup(gadget, func->intf_id); if (ret == -EAGAIN) { pr_debug("bus suspended func wakeup for %s delayed until bus resume.\n", func->name ? func->name : ""); } else if (ret < 0 && ret != -ENOTSUPP) { pr_err("Failed to wake function %s from suspend state. ret=%d.\n", func->name ? func->name : "", ret); } goto done; } if (!func->func_is_suspended) ret = 0; if (func->func_is_suspended && !func->func_wakeup_allowed) { ret = -ENOTSUPP; goto done; } ret = usb_ep_queue(ep, req, gfp_flags); done: return ret; } EXPORT_SYMBOL(usb_func_ep_queue); static u8 encode_bMaxPower(enum usb_device_speed speed, struct usb_configuration *c) { Loading @@ -441,7 +539,8 @@ static u8 encode_bMaxPower(enum usb_device_speed speed, case USB_SPEED_SUPER: return DIV_ROUND_UP(val, 8); default: return DIV_ROUND_UP(val, 2); /* only SuperSpeed and faster support > 500mA */ return DIV_ROUND_UP(min(val, 500U), 2); } } Loading Loading @@ -743,6 +842,11 @@ static void reset_config(struct usb_composite_dev *cdev) if (f->disable) f->disable(f); /* USB 3.0 addition */ f->func_is_suspended = false; f->func_wakeup_allowed = false; f->func_wakeup_pending = false; bitmap_zero(f->endpoints, 32); } cdev->config = NULL; Loading Loading @@ -1797,8 +1901,13 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) if (!f) break; value = 0; if (f->func_suspend) value = f->func_suspend(f, w_index >> 8); if (f->func_suspend) { const u8 suspend_opt = w_index >> 8; value = f->func_suspend(f, suspend_opt); DBG(cdev, "%s function: FUNCTION_SUSPEND(%u)", f->name ? f->name : "", suspend_opt); } if (value < 0) { ERROR(cdev, "func_suspend() returned error %d\n", Loading Loading @@ -2256,11 +2365,13 @@ void composite_suspend(struct usb_gadget *gadget) { struct usb_composite_dev *cdev = get_gadget_data(gadget); struct usb_function *f; unsigned long flags; /* REVISIT: should we have config level * suspend/resume callbacks? */ DBG(cdev, "suspend\n"); spin_lock_irqsave(&cdev->lock, flags); if (cdev->config) { list_for_each_entry(f, &cdev->config->functions, list) { if (f->suspend) Loading @@ -2271,6 +2382,7 @@ void composite_suspend(struct usb_gadget *gadget) cdev->driver->suspend(cdev); cdev->suspended = 1; spin_unlock_irqrestore(&cdev->lock, flags); usb_gadget_vbus_draw(gadget, 2); } Loading @@ -2280,6 +2392,8 @@ void composite_resume(struct usb_gadget *gadget) struct usb_composite_dev *cdev = get_gadget_data(gadget); struct usb_function *f; u16 maxpower; int ret; unsigned long flags; /* REVISIT: should we have config level * suspend/resume callbacks? Loading @@ -2287,8 +2401,25 @@ void composite_resume(struct usb_gadget *gadget) DBG(cdev, "resume\n"); if (cdev->driver->resume) cdev->driver->resume(cdev); spin_lock_irqsave(&cdev->lock, flags); if (cdev->config) { list_for_each_entry(f, &cdev->config->functions, list) { ret = usb_func_wakeup_int(f); if (ret) { if (ret == -EAGAIN) { ERROR(f->config->cdev, "Function wakeup for %s could not complete due to suspend state.\n", f->name ? f->name : ""); break; } else if (ret != -ENOTSUPP) { ERROR(f->config->cdev, "Failed to wake function %s from suspend state. ret=%d. Canceling USB request.\n", f->name ? f->name : "", ret); } } if (f->resume) f->resume(f); } Loading @@ -2299,6 +2430,7 @@ void composite_resume(struct usb_gadget *gadget) maxpower : CONFIG_USB_GADGET_VBUS_DRAW); } spin_unlock_irqrestore(&cdev->lock, flags); cdev->suspended = 0; } Loading
drivers/usb/gadget/udc/core.c +21 −0 Original line number Diff line number Diff line Loading @@ -479,6 +479,27 @@ int usb_gadget_wakeup(struct usb_gadget *gadget) } EXPORT_SYMBOL_GPL(usb_gadget_wakeup); /** * usb_gadget_func_wakeup - send a function remote wakeup up notification * to the host connected to this gadget * @gadget: controller used to wake up the host * @interface_id: the interface which triggered the remote wakeup event * * Returns zero on success. Otherwise, negative error code is returned. */ int usb_gadget_func_wakeup(struct usb_gadget *gadget, int interface_id) { if (gadget->speed != USB_SPEED_SUPER) return -EOPNOTSUPP; if (!gadget->ops->func_wakeup) return -EOPNOTSUPP; return gadget->ops->func_wakeup(gadget, interface_id); } EXPORT_SYMBOL(usb_gadget_func_wakeup); /** * usb_gadget_set_selfpowered - sets the device selfpowered feature. * @gadget:the device being declared as self-powered Loading
include/linux/usb/composite.h +16 −1 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ struct usb_os_desc_table { /** * struct usb_function - describes one function of a configuration * @name: For diagnostics, identifies the function. * @intf_id: Interface ID * @strings: tables of strings, keyed by identifiers assigned during bind() * and by language IDs provided in control requests * @fs_descriptors: Table of full (or low) speed descriptors, using interface and Loading Loading @@ -158,7 +159,14 @@ struct usb_os_desc_table { * @get_status: Returns function status as a reply to * GetStatus() request when the recipient is Interface. * @func_suspend: callback to be called when * SetFeature(FUNCTION_SUSPEND) is reseived * SetFeature(FUNCTION_SUSPEND) is received * @func_is_suspended: Tells whether the function is currently in * Function Suspend state (used in Super Speed mode only). * @func_wakeup_allowed: Tells whether Function Remote Wakeup has been allowed * by the USB host (used in Super Speed mode only). * @func_wakeup_pending: Marks that the function has issued a Function Wakeup * while the USB bus was suspended and therefore a Function Wakeup * notification needs to be sent once the USB bus is resumed. * * A single USB function uses one or more interfaces, and should in most * cases support operation at both full and high speeds. Each function is Loading Loading @@ -186,6 +194,7 @@ struct usb_os_desc_table { struct usb_function { const char *name; int intf_id; struct usb_gadget_strings **strings; struct usb_descriptor_header **fs_descriptors; struct usb_descriptor_header **hs_descriptors; Loading Loading @@ -229,6 +238,9 @@ struct usb_function { int (*get_status)(struct usb_function *); int (*func_suspend)(struct usb_function *, u8 suspend_opt); unsigned func_is_suspended:1; unsigned func_wakeup_allowed:1; unsigned func_wakeup_pending:1; /* private: */ /* internals */ struct list_head list; Loading @@ -244,6 +256,9 @@ int usb_function_deactivate(struct usb_function *); int usb_function_activate(struct usb_function *); int usb_interface_id(struct usb_configuration *, struct usb_function *); int usb_func_wakeup(struct usb_function *func); int usb_get_func_interface_id(struct usb_function *func); int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f, struct usb_ep *_ep); Loading
include/linux/usb/gadget.h +22 −0 Original line number Diff line number Diff line Loading @@ -297,6 +297,7 @@ struct usb_udc; struct usb_gadget_ops { int (*get_frame)(struct usb_gadget *); int (*wakeup)(struct usb_gadget *); int (*func_wakeup)(struct usb_gadget *, int interface_id); int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered); int (*vbus_session) (struct usb_gadget *, int is_active); int (*vbus_draw) (struct usb_gadget *, unsigned mA); Loading Loading @@ -544,6 +545,7 @@ static inline int gadget_is_otg(struct usb_gadget *g) #if IS_ENABLED(CONFIG_USB_GADGET) int usb_gadget_frame_number(struct usb_gadget *gadget); int usb_gadget_wakeup(struct usb_gadget *gadget); int usb_gadget_func_wakeup(struct usb_gadget *gadget, int interface_id); int usb_gadget_set_selfpowered(struct usb_gadget *gadget); int usb_gadget_clear_selfpowered(struct usb_gadget *gadget); int usb_gadget_vbus_connect(struct usb_gadget *gadget); Loading @@ -558,6 +560,8 @@ static inline int usb_gadget_frame_number(struct usb_gadget *gadget) { return 0; } static inline int usb_gadget_wakeup(struct usb_gadget *gadget) { return 0; } static int usb_gadget_func_wakeup(struct usb_gadget *gadget, int interface_id) { return 0; } static inline int usb_gadget_set_selfpowered(struct usb_gadget *gadget) { return 0; } static inline int usb_gadget_clear_selfpowered(struct usb_gadget *gadget) Loading Loading @@ -796,6 +800,24 @@ int usb_otg_descriptor_init(struct usb_gadget *gadget, struct usb_descriptor_header *otg_desc); /*-------------------------------------------------------------------------*/ /** * usb_func_ep_queue - queues (submits) an I/O request to a function endpoint. * This function is similar to the usb_ep_queue function, but in addition it * also checks whether the function is in Super Speed USB Function Suspend * state, and if so a Function Wake notification is sent to the host * (USB 3.0 spec, section 9.2.5.2). * @func: the function which issues the USB I/O request. * @ep:the endpoint associated with the request * @req:the request being submitted * @gfp_flags: GFP_* flags to use in case the lower level driver couldn't * pre-allocate all necessary memory with the request. * */ int usb_func_ep_queue(struct usb_function *func, struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags); /*-------------------------------------------------------------------------*/ /* utility to simplify map/unmap of usb_requests to/from DMA */ extern int usb_gadget_map_request_by_dev(struct device *dev, Loading