diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-27 11:23:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-27 11:23:36 -0700 |
commit | 34da76dca4673ab1819830b4924bb5b436325b26 (patch) | |
tree | 2f863b0382b5368f1b900fd8be586dd651c01e69 /drivers/usb | |
parent | 725a345b2ee3c24f9ac2078eb73667e22a1b7214 (diff) | |
parent | c3a6ef330a08eba406f82b0b8cbca4e4d9b7c4ba (diff) | |
download | lwn-34da76dca4673ab1819830b4924bb5b436325b26.tar.gz lwn-34da76dca4673ab1819830b4924bb5b436325b26.zip |
Merge tag 'for-linus-2023042601' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Jiri Kosina:
- import a bunch of HID selftests from out-of-tree hid-tools project
(Benjamin Tissoires)
- drastically reducing Bluetooth disconnects on hid-nintendo driven
devices (Daniel J. Ogorchock)
- lazy initialization of battery interfaces in wacom driver (Jason
Gerecke)
- generic support for all Kye tablets (David Yang)
- proper rumble queue overrun handling in hid-nintendo (Daniel J.
Ogorchock)
- support for ADC measurement in logitech-hidpp driver (Bastien Nocera)
- reset GPIO support in i2c-hid (Hans de Goede)
- improved handling of generic "Digitizer" usage (Jason Gerecke)
- support for KEY_CAMERA_FOCUS (Feng Qi)
- quirks for Apple Geyser 3 and Apple Geyser 4 (Alex Henrie)
- assorted functional fixes and device ID additions
* tag 'for-linus-2023042601' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (54 commits)
HID: amd_sfh: Fix max supported HID devices
HID: wacom: generic: Set battery quirk only when we see battery data
HID: wacom: Lazy-init batteries
HID: Ignore battery for ELAN touchscreen on ROG Flow X13 GV301RA
HID: asus: explicitly include linux/leds.h
HID: lg-g15: explicitly include linux/leds.h
HID: steelseries: explicitly include linux/leds.h
HID: apple: Set the tilde quirk flag on the Geyser 3
HID: apple: explicitly include linux/leds.h
HID: mcp2221: fix get and get_direction for gpio
HID: mcp2221: fix report layout for gpio get
HID: wacom: Set a default resolution for older tablets
HID: i2c-hid-of: Add reset GPIO support to i2c-hid-of
HID: i2c-hid-of: Allow using i2c-hid-of on non OF platforms
HID: i2c-hid-of: Consistenly use dev local variable in probe()
HID: kye: Fix rdesc for kye tablets
HID: amd_sfh: Support for additional light sensor
HID: amd_sfh: Handle "no sensors" enabled for SFH1.1
HID: amd_sfh: Increase sensor command timeout for SFH1.1
HID: amd_sfh: Correct the stop all command
...
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/message.c | 40 | ||||
-rw-r--r-- | drivers/usb/core/sysfs.c | 50 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 1 |
3 files changed, 91 insertions, 0 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index cc404bb7e8f7..b5811620f1de 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 + * @iface: the interface 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); diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index b63f78e48c74..323dc02becbe 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -1227,9 +1227,59 @@ static const struct attribute_group intf_assoc_attr_grp = { .is_visible = intf_assoc_attrs_are_visible, }; +static ssize_t wireless_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_interface *intf; + + intf = to_usb_interface(dev); + if (intf->wireless_status == USB_WIRELESS_STATUS_DISCONNECTED) + return sysfs_emit(buf, "%s\n", "disconnected"); + return sysfs_emit(buf, "%s\n", "connected"); +} +static DEVICE_ATTR_RO(wireless_status); + +static struct attribute *intf_wireless_status_attrs[] = { + &dev_attr_wireless_status.attr, + NULL +}; + +static umode_t intf_wireless_status_attr_is_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct usb_interface *intf = to_usb_interface(dev); + + if (a != &dev_attr_wireless_status.attr || + intf->wireless_status != USB_WIRELESS_STATUS_NA) + return a->mode; + return 0; +} + +static const struct attribute_group intf_wireless_status_attr_grp = { + .attrs = intf_wireless_status_attrs, + .is_visible = intf_wireless_status_attr_is_visible, +}; + +int usb_update_wireless_status_attr(struct usb_interface *intf) +{ + struct device *dev = &intf->dev; + int ret; + + ret = sysfs_update_group(&dev->kobj, &intf_wireless_status_attr_grp); + if (ret < 0) + return ret; + + sysfs_notify(&dev->kobj, NULL, "wireless_status"); + kobject_uevent(&dev->kobj, KOBJ_CHANGE); + + return 0; +} + const struct attribute_group *usb_interface_groups[] = { &intf_attr_grp, &intf_assoc_attr_grp, + &intf_wireless_status_attr_grp, NULL }; diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 0eac7d4285d1..3f14e15f07f6 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -15,6 +15,7 @@ extern int usb_create_sysfs_dev_files(struct usb_device *dev); extern void usb_remove_sysfs_dev_files(struct usb_device *dev); extern void usb_create_sysfs_intf_files(struct usb_interface *intf); extern void usb_remove_sysfs_intf_files(struct usb_interface *intf); +extern int usb_update_wireless_status_attr(struct usb_interface *intf); extern int usb_create_ep_devs(struct device *parent, struct usb_host_endpoint *endpoint, struct usb_device *udev); |