From 0a4db185f0788dfc828512d0004c468921bf6c0a Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 2 Mar 2023 11:55:54 +0100 Subject: USB: core: Add API to change the wireless_status This adds the API that allows device specific drivers to tell user-space about whether the wireless device is connected to its receiver dongle. See "USB: core: Add wireless_status sysfs attribute" for a detailed explanation of what this attribute should be used for. Signed-off-by: Bastien Nocera Acked-by: Greg Kroah-Hartman Acked-by: Alan Stern Link: https://lore.kernel.org/r/20230302105555.51417-5-hadess@hadess.net Signed-off-by: Benjamin Tissoires --- drivers/usb/core/message.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'drivers/usb/core/message.c') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index cc404bb7e8f7..33392a6f4972 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1908,6 +1908,45 @@ static void __usb_queue_reset_device(struct work_struct *ws) usb_put_intf(iface); /* Undo _get_ in usb_queue_reset_device() */ } +/* + * Internal function to set the wireless_status sysfs attribute + * See usb_set_wireless_status() for more details + */ +static void __usb_wireless_status_intf(struct work_struct *ws) +{ + struct usb_interface *iface = + container_of(ws, struct usb_interface, wireless_status_work); + + device_lock(iface->dev.parent); + if (iface->sysfs_files_created) + usb_update_wireless_status_attr(iface); + device_unlock(iface->dev.parent); + usb_put_intf(iface); /* Undo _get_ in usb_set_wireless_status() */ +} + +/** + * usb_set_wireless_status - sets the wireless_status struct member + * @dev: the device to modify + * @status: the new wireless status + * + * Set the wireless_status struct member to the new value, and emit + * sysfs changes as necessary. + * + * Returns: 0 on success, -EALREADY if already set. + */ +int usb_set_wireless_status(struct usb_interface *iface, + enum usb_wireless_status status) +{ + if (iface->wireless_status == status) + return -EALREADY; + + usb_get_intf(iface); + iface->wireless_status = status; + schedule_work(&iface->wireless_status_work); + + return 0; +} +EXPORT_SYMBOL_GPL(usb_set_wireless_status); /* * usb_set_configuration - Makes a particular device setting be current @@ -2100,6 +2139,7 @@ free_interfaces: intf->dev.type = &usb_if_device_type; intf->dev.groups = usb_interface_groups; INIT_WORK(&intf->reset_ws, __usb_queue_reset_device); + INIT_WORK(&intf->wireless_status_work, __usb_wireless_status_intf); intf->minor = -1; device_initialize(&intf->dev); pm_runtime_no_callbacks(&intf->dev); -- cgit v1.2.3 From 539adfedbd2d5cda2f9e2d83b35b364834b67d58 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Wed, 5 Apr 2023 11:27:54 +0200 Subject: USB: core: Fix docs warning caused by wireless_status feature Fix wrongly named 'dev' parameter in doc block, should have been iface: drivers/usb/core/message.c:1939: warning: Function parameter or member 'iface' not described in 'usb_set_wireless_status' drivers/usb/core/message.c:1939: warning: Excess function parameter 'dev' description in 'usb_set_wireless_status' And fix missing struct member doc in kernel API, and reorder to match struct: include/linux/usb.h:270: warning: Function parameter or member 'wireless_status_work' not described in 'usb_interface' Reported-by: Stephen Rothwell Link: https://lore.kernel.org/linux-next/20230405114807.5a57bf46@canb.auug.org.au/T/#t Fixes: 0a4db185f078 ("USB: core: Add API to change the wireless_status") Signed-off-by: Bastien Nocera Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20230405092754.36579-1-hadess@hadess.net [bentiss: fix checkpatch warning] Signed-off-by: Benjamin Tissoires --- drivers/usb/core/message.c | 2 +- include/linux/usb.h | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/usb/core/message.c') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 33392a6f4972..b5811620f1de 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1926,7 +1926,7 @@ static void __usb_wireless_status_intf(struct work_struct *ws) /** * usb_set_wireless_status - sets the wireless_status struct member - * @dev: the device to modify + * @iface: the interface to modify * @status: the new wireless status * * Set the wireless_status struct member to the new value, and emit diff --git a/include/linux/usb.h b/include/linux/usb.h index 6dfd59d3d695..0a81e0f5beb4 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -203,14 +203,16 @@ enum usb_wireless_status { * following a reset or suspend operation it doesn't support. * @authorized: This allows to (de)authorize individual interfaces instead * a whole device in contrast to the device authorization. + * @wireless_status: if the USB device uses a receiver/emitter combo, whether + * the emitter is connected. + * @wireless_status_work: Used for scheduling wireless status changes + * from atomic context. * @dev: driver model's view of this device * @usb_dev: if an interface is bound to the USB major, this will point * to the sysfs representation for that device. * @reset_ws: Used for scheduling resets from atomic context. * @resetting_device: USB core reset the device, so use alt setting 0 as * current; needs bandwidth alloc after reset. - * @wireless_status: if the USB device uses a receiver/emitter combo, whether - * the emitter is connected. * * USB device drivers attach to interfaces on a physical device. Each * interface encapsulates a single high level function, such as feeding -- cgit v1.2.3