From e90a6df80dc45ab53d2f4f4db297434e48c0208e Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Mon, 25 Feb 2013 11:31:43 +0100 Subject: [PATCH 01/19] HID: Extend the interface with report requests Some drivers send reports directly to underlying device, creating an unwanted dependency on the underlying transport layer. This patch adds hid_hw_request() to the interface, thereby removing usbhid from the lion share of the drivers. Signed-off-by: Henrik Rydberg Signed-off-by: Benjamin Tissoires Reviewed-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 13 +++++++++++++ include/linux/hid.h | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 8e0c4bf94ebc..366fd09d257d 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1243,6 +1243,18 @@ static int usbhid_power(struct hid_device *hid, int lvl) return r; } +static void usbhid_request(struct hid_device *hid, struct hid_report *rep, int reqtype) +{ + switch (reqtype) { + case HID_REQ_GET_REPORT: + usbhid_submit_report(hid, rep, USB_DIR_IN); + break; + case HID_REQ_SET_REPORT: + usbhid_submit_report(hid, rep, USB_DIR_OUT); + break; + } +} + static struct hid_ll_driver usb_hid_driver = { .parse = usbhid_parse, .start = usbhid_start, @@ -1251,6 +1263,7 @@ static struct hid_ll_driver usb_hid_driver = { .close = usbhid_close, .power = usbhid_power, .hidinput_input_event = usb_hidinput_input_event, + .request = usbhid_request, }; static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id) diff --git a/include/linux/hid.h b/include/linux/hid.h index e14b465b1146..261c713d4842 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -662,6 +662,7 @@ struct hid_driver { * @hidinput_input_event: event input event (e.g. ff or leds) * @parse: this method is called only once to parse the device data, * shouldn't allocate anything to not leak memory + * @request: send report request to device (e.g. feature report) */ struct hid_ll_driver { int (*start)(struct hid_device *hdev); @@ -676,6 +677,10 @@ struct hid_ll_driver { unsigned int code, int value); int (*parse)(struct hid_device *hdev); + + void (*request)(struct hid_device *hdev, + struct hid_report *report, int reqtype); + }; #define PM_HINT_FULLON 1<<5 @@ -883,6 +888,21 @@ static inline int hid_hw_power(struct hid_device *hdev, int level) return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0; } + +/** + * hid_hw_request - send report request to device + * + * @hdev: hid device + * @report: report to send + * @reqtype: hid request type + */ +static inline void hid_hw_request(struct hid_device *hdev, + struct hid_report *report, int reqtype) +{ + if (hdev->ll_driver->request) + hdev->ll_driver->request(hdev, report, reqtype); +} + int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, int interrupt); From 3373443befa73ee60e4275e7699b26058b01455a Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Mon, 25 Feb 2013 11:31:44 +0100 Subject: [PATCH 02/19] HID: Extend the interface with wait io request Some drivers need to wait for an io from the underlying device, creating an unwanted dependency on the underlying transport layer. This patch adds wait() to the interface, thereby removing usbhid from the lion share of the drivers. Signed-off-by: Henrik Rydberg Signed-off-by: Benjamin Tissoires Reviewed-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 1 + include/linux/hid.h | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 366fd09d257d..99d95d3368b5 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1264,6 +1264,7 @@ static struct hid_ll_driver usb_hid_driver = { .power = usbhid_power, .hidinput_input_event = usb_hidinput_input_event, .request = usbhid_request, + .wait = usbhid_wait_io, }; static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id) diff --git a/include/linux/hid.h b/include/linux/hid.h index 261c713d4842..7071eb3d36c7 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -663,6 +663,7 @@ struct hid_driver { * @parse: this method is called only once to parse the device data, * shouldn't allocate anything to not leak memory * @request: send report request to device (e.g. feature report) + * @wait: wait for buffered io to complete (send/recv reports) */ struct hid_ll_driver { int (*start)(struct hid_device *hdev); @@ -681,6 +682,8 @@ struct hid_ll_driver { void (*request)(struct hid_device *hdev, struct hid_report *report, int reqtype); + int (*wait)(struct hid_device *hdev); + }; #define PM_HINT_FULLON 1<<5 @@ -903,6 +906,17 @@ static inline void hid_hw_request(struct hid_device *hdev, hdev->ll_driver->request(hdev, report, reqtype); } +/** + * hid_hw_wait - wait for buffered io to complete + * + * @hdev: hid device + */ +static inline void hid_hw_wait(struct hid_device *hdev) +{ + if (hdev->ll_driver->wait) + hdev->ll_driver->wait(hdev); +} + int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, int interrupt); From f3757cea18fadce23c95a4c4bc3123af73a95e65 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 25 Feb 2013 11:31:45 +0100 Subject: [PATCH 03/19] HID: Kconfig: Remove explicit transport layer dependencies Most HID drivers (rightfully) only depend on the HID bus, not the specific transport layer. Remove such dependencies where applicable. Signed-off-by: Benjamin Tissoires Acked-by: Henrik Rydberg Reviewed-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 68 ++++++++++++++++++------------------ drivers/hid/hid-apple.c | 1 - drivers/hid/hid-magicmouse.c | 1 - drivers/hid/hid-speedlink.c | 2 -- drivers/hid/hid-thingm.c | 1 - 5 files changed, 34 insertions(+), 39 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 5f07d85c4189..1b737b44c56e 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -92,7 +92,7 @@ menu "Special HID drivers" config HID_A4TECH tristate "A4 tech mice" if EXPERT - depends on USB_HID + depends on HID default !EXPERT ---help--- Support for A4 tech X5 and WOP-35 / Trust 450L mice. @@ -113,7 +113,7 @@ config HID_ACRUX_FF config HID_APPLE tristate "Apple {i,Power,Mac}Books" if EXPERT - depends on (USB_HID || BT_HIDP) + depends on HID default !EXPERT ---help--- Support for some Apple devices which less or more break @@ -124,27 +124,27 @@ config HID_APPLE config HID_AUREAL tristate "Aureal" - depends on USB_HID + depends on HID ---help--- Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes. config HID_BELKIN tristate "Belkin Flip KVM and Wireless keyboard" if EXPERT - depends on USB_HID + depends on HID default !EXPERT ---help--- Support for Belkin Flip KVM and Wireless keyboard. config HID_CHERRY tristate "Cherry Cymotion keyboard" if EXPERT - depends on USB_HID + depends on HID default !EXPERT ---help--- Support for Cherry Cymotion keyboard. config HID_CHICONY tristate "Chicony Tactical pad" if EXPERT - depends on USB_HID + depends on HID default !EXPERT ---help--- Support for Chicony Tactical pad. @@ -166,7 +166,7 @@ config HID_PRODIKEYS config HID_CYPRESS tristate "Cypress mouse and barcode readers" if EXPERT - depends on USB_HID + depends on HID default !EXPERT ---help--- Support for cypress mouse and barcode readers. @@ -202,13 +202,13 @@ config HID_EMS_FF config HID_ELECOM tristate "ELECOM BM084 bluetooth mouse" - depends on BT_HIDP + depends on HID ---help--- Support for the ELECOM BM084 (bluetooth mouse). config HID_EZKEY tristate "Ezkey BTC 8193 keyboard" if EXPERT - depends on USB_HID + depends on HID default !EXPERT ---help--- Support for Ezkey BTC 8193 keyboard. @@ -231,7 +231,7 @@ config HOLTEK_FF config HID_KEYTOUCH tristate "Keytouch HID devices" - depends on USB_HID + depends on HID ---help--- Support for Keytouch HID devices not fully compliant with the specification. Currently supported: @@ -249,25 +249,25 @@ config HID_KYE config HID_UCLOGIC tristate "UC-Logic" - depends on USB_HID + depends on HID ---help--- Support for UC-Logic tablets. config HID_WALTOP tristate "Waltop" - depends on USB_HID + depends on HID ---help--- Support for Waltop tablets. config HID_GYRATION tristate "Gyration remote control" - depends on USB_HID + depends on HID ---help--- Support for Gyration remote control. config HID_ICADE tristate "ION iCade arcade controller" - depends on BT_HIDP + depends on HID ---help--- Support for the ION iCade arcade controller to work as a joystick. @@ -276,20 +276,20 @@ config HID_ICADE config HID_TWINHAN tristate "Twinhan IR remote control" - depends on USB_HID + depends on HID ---help--- Support for Twinhan IR remote control. config HID_KENSINGTON tristate "Kensington Slimblade Trackball" if EXPERT - depends on USB_HID + depends on HID default !EXPERT ---help--- Support for Kensington Slimblade Trackball. config HID_LCPOWER tristate "LC-Power" - depends on USB_HID + depends on HID ---help--- Support for LC-Power RC1000MCE RF remote control. @@ -308,7 +308,7 @@ config HID_LENOVO_TPKBD config HID_LOGITECH tristate "Logitech devices" if EXPERT - depends on USB_HID + depends on HID default !EXPERT ---help--- Support for Logitech devices that are not fully compliant with HID standard. @@ -374,7 +374,7 @@ config LOGIWHEELS_FF config HID_MAGICMOUSE tristate "Apple MagicMouse multi-touch support" - depends on BT_HIDP + depends on HID ---help--- Support for the Apple Magic Mouse multi-touch. @@ -383,14 +383,14 @@ config HID_MAGICMOUSE config HID_MICROSOFT tristate "Microsoft non-fully HID-compliant devices" if EXPERT - depends on USB_HID + depends on HID default !EXPERT ---help--- Support for Microsoft devices that are not fully compliant with HID standard. config HID_MONTEREY tristate "Monterey Genius KB29E keyboard" if EXPERT - depends on USB_HID + depends on HID default !EXPERT ---help--- Support for Monterey Genius KB29E. @@ -445,7 +445,7 @@ config HID_NTRIG config HID_ORTEK tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad" - depends on USB_HID + depends on HID ---help--- There are certain devices which have LogicalMaximum wrong in the keyboard usage page of their report descriptor. The most prevailing ones so far @@ -473,7 +473,7 @@ config PANTHERLORD_FF config HID_PETALYNX tristate "Petalynx Maxter remote control" - depends on USB_HID + depends on HID ---help--- Support for Petalynx Maxter remote control. @@ -545,14 +545,14 @@ config HID_PICOLCD_CIR config HID_PRIMAX tristate "Primax non-fully HID-compliant devices" - depends on USB_HID + depends on HID ---help--- Support for Primax devices that are not fully compliant with the HID standard. config HID_PS3REMOTE tristate "Sony PS3 BD Remote Control" - depends on BT_HIDP + depends on HID ---help--- Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech Harmony Adapter for PS3, which connect over Bluetooth. @@ -569,7 +569,7 @@ config HID_ROCCAT config HID_SAITEK tristate "Saitek non-fully HID-compliant devices" - depends on USB_HID + depends on HID ---help--- Support for Saitek devices that are not fully compliant with the HID standard. @@ -578,7 +578,7 @@ config HID_SAITEK config HID_SAMSUNG tristate "Samsung InfraRed remote control or keyboards" - depends on USB_HID + depends on HID ---help--- Support for Samsung InfraRed remote control or keyboards. @@ -604,7 +604,7 @@ config HID_STEELSERIES config HID_SUNPLUS tristate "Sunplus wireless desktop" - depends on USB_HID + depends on HID ---help--- Support for Sunplus wireless desktop. @@ -650,20 +650,20 @@ config SMARTJOYPLUS_FF config HID_TIVO tristate "TiVo Slide Bluetooth remote control support" - depends on (USB_HID || BT_HIDP) + depends on HID ---help--- Say Y if you have a TiVo Slide Bluetooth remote control. config HID_TOPSEED tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support" - depends on USB_HID + depends on HID ---help--- Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic CLLRCMCE remote control. config HID_THINGM tristate "ThingM blink(1) USB RGB LED" - depends on USB_HID + depends on HID depends on LEDS_CLASS ---help--- Support for the ThingM blink(1) USB RGB LED. This driver registers a @@ -689,7 +689,7 @@ config THRUSTMASTER_FF config HID_WACOM tristate "Wacom Bluetooth devices support" - depends on BT_HIDP + depends on HID depends on LEDS_CLASS select POWER_SUPPLY ---help--- @@ -697,7 +697,7 @@ config HID_WACOM config HID_WIIMOTE tristate "Nintendo Wii Remote support" - depends on BT_HIDP + depends on HID depends on LEDS_CLASS select POWER_SUPPLY select INPUT_FF_MEMLESS @@ -729,7 +729,7 @@ config ZEROPLUS_FF config HID_ZYDACRON tristate "Zydacron remote control support" - depends on USB_HID + depends on HID ---help--- Support for Zydacron remote control. diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 320a958d4139..9e0c4fbbb840 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "hid-ids.h" diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index f7f113ba083e..ef89573d65fc 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "hid-ids.h" diff --git a/drivers/hid/hid-speedlink.c b/drivers/hid/hid-speedlink.c index e94371a059cb..a2f587d004e1 100644 --- a/drivers/hid/hid-speedlink.c +++ b/drivers/hid/hid-speedlink.c @@ -16,10 +16,8 @@ #include #include #include -#include #include "hid-ids.h" -#include "usbhid/usbhid.h" static const struct hid_device_id speedlink_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE)}, diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c index 2055a52e9a20..99342cfa0ea2 100644 --- a/drivers/hid/hid-thingm.c +++ b/drivers/hid/hid-thingm.c @@ -12,7 +12,6 @@ #include #include #include -#include #include "hid-ids.h" From d881427253da011495f4193663d809d0e9dfa215 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 25 Feb 2013 11:31:46 +0100 Subject: [PATCH 04/19] HID: use hid_hw_request() instead of direct call to usbhid This allows the hid drivers to be independent from the transport layer. The patch was constructed by replacing all occurences of usbhid_submit_report() by its hid_hw_request() counterpart. Then, drivers not requiring USB_HID anymore have their USB_HID dependency cleaned in the Kconfig file. Finally, few drivers still depends on USB_HID. Many of them are requiring the io wait callback. They are found in the next patch. Signed-off-by: Benjamin Tissoires Reviewed-by: Mika Westerberg For the sensor-hub part: Tested-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 30 +++++++------- drivers/hid/hid-axff.c | 6 +-- drivers/hid/hid-dr.c | 8 ++-- drivers/hid/hid-emsff.c | 6 +-- drivers/hid/hid-gaff.c | 10 ++--- drivers/hid/hid-holtekff.c | 4 +- drivers/hid/hid-kye.c | 4 +- drivers/hid/hid-lenovo-tpkbd.c | 4 +- drivers/hid/hid-lg2ff.c | 6 +-- drivers/hid/hid-lg3ff.c | 6 +-- drivers/hid/hid-lg4ff.c | 18 ++++---- drivers/hid/hid-lgff.c | 8 ++-- drivers/hid/hid-logitech-dj.c | 3 +- drivers/hid/hid-multitouch.c | 4 +- drivers/hid/hid-ntrig.c | 6 +-- drivers/hid/hid-picolcd.h | 4 +- drivers/hid/hid-picolcd_backlight.c | 4 +- drivers/hid/hid-picolcd_cir.c | 2 - drivers/hid/hid-picolcd_core.c | 8 ++-- drivers/hid/hid-picolcd_debugfs.c | 2 - drivers/hid/hid-picolcd_fb.c | 7 ++-- drivers/hid/hid-picolcd_lcd.c | 4 +- drivers/hid/hid-picolcd_leds.c | 4 +- drivers/hid/hid-pl.c | 6 +-- drivers/hid/hid-prodikeys.c | 3 +- drivers/hid/hid-sensor-hub.c | 7 ++-- drivers/hid/hid-sjoy.c | 6 +-- drivers/hid/hid-steelseries.c | 3 +- drivers/hid/hid-tmff.c | 6 +-- drivers/hid/hid-zpff.c | 6 +-- drivers/hid/usbhid/hid-core.c | 3 +- drivers/hid/usbhid/hid-pidff.c | 64 ++++++++++++++--------------- drivers/hid/usbhid/hiddev.c | 4 +- drivers/hid/usbhid/usbhid.h | 2 - 34 files changed, 111 insertions(+), 157 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 1b737b44c56e..f0acf2754b69 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -99,7 +99,7 @@ config HID_A4TECH config HID_ACRUX tristate "ACRUX game controller support" - depends on USB_HID + depends on HID ---help--- Say Y here if you want to enable support for ACRUX game controllers. @@ -151,7 +151,7 @@ config HID_CHICONY config HID_PRODIKEYS tristate "Prodikeys PC-MIDI Keyboard support" - depends on USB_HID && SND + depends on HID && SND select SND_RAWMIDI ---help--- Support for Prodikeys PC-MIDI Keyboard device support. @@ -173,7 +173,7 @@ config HID_CYPRESS config HID_DRAGONRISE tristate "DragonRise Inc. game controller" - depends on USB_HID + depends on HID ---help--- Say Y here if you have DragonRise Inc. game controllers. These might be branded as: @@ -192,7 +192,7 @@ config DRAGONRISE_FF config HID_EMS_FF tristate "EMS Production Inc. force feedback support" - depends on USB_HID + depends on HID select INPUT_FF_MEMLESS ---help--- Say Y here if you want to enable force feedback support for devices by @@ -215,7 +215,7 @@ config HID_EZKEY config HID_HOLTEK tristate "Holtek HID devices" - depends on USB_HID + depends on HID ---help--- Support for Holtek based devices: - Holtek On Line Grip based game controller @@ -239,7 +239,7 @@ config HID_KEYTOUCH config HID_KYE tristate "KYE/Genius devices" - depends on USB_HID + depends on HID ---help--- Support for KYE/Genius devices not fully compliant with HID standard: - Ergo Mouse @@ -397,7 +397,7 @@ config HID_MONTEREY config HID_MULTITOUCH tristate "HID Multitouch panels" - depends on USB_HID + depends on HID ---help--- Generic support for HID multitouch panels. @@ -458,7 +458,7 @@ config HID_ORTEK config HID_PANTHERLORD tristate "Pantherlord/GreenAsia game controller" - depends on USB_HID + depends on HID ---help--- Say Y here if you have a PantherLord/GreenAsia based game controller or adapter. @@ -592,13 +592,13 @@ config HID_SONY config HID_SPEEDLINK tristate "Speedlink VAD Cezanne mouse support" - depends on USB_HID + depends on HID ---help--- Support for Speedlink Vicious and Divine Cezanne mouse. config HID_STEELSERIES tristate "Steelseries SRW-S1 steering wheel support" - depends on USB_HID + depends on HID ---help--- Support for Steelseries SRW-S1 steering wheel @@ -610,7 +610,7 @@ config HID_SUNPLUS config HID_GREENASIA tristate "GreenAsia (Product ID 0x12) game controller support" - depends on USB_HID + depends on HID ---help--- Say Y here if you have a GreenAsia (Product ID 0x12) based game controller or adapter. @@ -632,7 +632,7 @@ config HID_HYPERV_MOUSE config HID_SMARTJOYPLUS tristate "SmartJoy PLUS PS2/USB adapter support" - depends on USB_HID + depends on HID ---help--- Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box, Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro. @@ -673,7 +673,7 @@ config HID_THINGM config HID_THRUSTMASTER tristate "ThrustMaster devices support" - depends on USB_HID + depends on HID ---help--- Say Y here if you have a THRUSTMASTER FireStore Dual Power 2 or a THRUSTMASTER Ferrari GT Rumble Wheel. @@ -715,7 +715,7 @@ config HID_WIIMOTE_EXT config HID_ZEROPLUS tristate "Zeroplus based game controller support" - depends on USB_HID + depends on HID ---help--- Say Y here if you have a Zeroplus based game controller. @@ -735,7 +735,7 @@ config HID_ZYDACRON config HID_SENSOR_HUB tristate "HID Sensors framework support" - depends on USB_HID && GENERIC_HARDIRQS + depends on HID && GENERIC_HARDIRQS select MFD_CORE default n -- help--- diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c index 62f0cee032ba..64ab94a55aa7 100644 --- a/drivers/hid/hid-axff.c +++ b/drivers/hid/hid-axff.c @@ -29,14 +29,12 @@ #include #include -#include #include #include #include "hid-ids.h" #ifdef CONFIG_HID_ACRUX_FF -#include "usbhid/usbhid.h" struct axff_device { struct hid_report *report; @@ -68,7 +66,7 @@ static int axff_play(struct input_dev *dev, void *data, struct ff_effect *effect } dbg_hid("running with 0x%02x 0x%02x", left, right); - usbhid_submit_report(hid, axff->report, USB_DIR_OUT); + hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT); return 0; } @@ -114,7 +112,7 @@ static int axff_init(struct hid_device *hid) goto err_free_mem; axff->report = report; - usbhid_submit_report(hid, axff->report, USB_DIR_OUT); + hid_hw_request(hid, axff->report, HID_REQ_SET_REPORT); hid_info(hid, "Force Feedback for ACRUX game controllers by Sergei Kolzun \n"); diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c index 0fe8f65ef01a..ce0644424f58 100644 --- a/drivers/hid/hid-dr.c +++ b/drivers/hid/hid-dr.c @@ -29,14 +29,12 @@ #include #include -#include #include #include #include "hid-ids.h" #ifdef CONFIG_DRAGONRISE_FF -#include "usbhid/usbhid.h" struct drff_device { struct hid_report *report; @@ -68,7 +66,7 @@ static int drff_play(struct input_dev *dev, void *data, drff->report->field[0]->value[1] = 0x00; drff->report->field[0]->value[2] = weak; drff->report->field[0]->value[4] = strong; - usbhid_submit_report(hid, drff->report, USB_DIR_OUT); + hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT); drff->report->field[0]->value[0] = 0xfa; drff->report->field[0]->value[1] = 0xfe; @@ -80,7 +78,7 @@ static int drff_play(struct input_dev *dev, void *data, drff->report->field[0]->value[2] = 0x00; drff->report->field[0]->value[4] = 0x00; dbg_hid("running with 0x%02x 0x%02x", strong, weak); - usbhid_submit_report(hid, drff->report, USB_DIR_OUT); + hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT); return 0; } @@ -132,7 +130,7 @@ static int drff_init(struct hid_device *hid) drff->report->field[0]->value[4] = 0x00; drff->report->field[0]->value[5] = 0x00; drff->report->field[0]->value[6] = 0x00; - usbhid_submit_report(hid, drff->report, USB_DIR_OUT); + hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT); hid_info(hid, "Force Feedback for DragonRise Inc. " "game controllers by Richard Walmsley \n"); diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c index 2e093ab99b43..d82d75bb11f7 100644 --- a/drivers/hid/hid-emsff.c +++ b/drivers/hid/hid-emsff.c @@ -23,11 +23,9 @@ #include #include -#include #include #include "hid-ids.h" -#include "usbhid/usbhid.h" struct emsff_device { struct hid_report *report; @@ -52,7 +50,7 @@ static int emsff_play(struct input_dev *dev, void *data, emsff->report->field[0]->value[2] = strong; dbg_hid("running with 0x%02x 0x%02x\n", strong, weak); - usbhid_submit_report(hid, emsff->report, USB_DIR_OUT); + hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT); return 0; } @@ -104,7 +102,7 @@ static int emsff_init(struct hid_device *hid) emsff->report->field[0]->value[4] = 0x00; emsff->report->field[0]->value[5] = 0x00; emsff->report->field[0]->value[6] = 0x00; - usbhid_submit_report(hid, emsff->report, USB_DIR_OUT); + hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT); hid_info(hid, "force feedback for EMS based devices by Ignaz Forster \n"); diff --git a/drivers/hid/hid-gaff.c b/drivers/hid/hid-gaff.c index 04d2e6aca778..2d8cead3adca 100644 --- a/drivers/hid/hid-gaff.c +++ b/drivers/hid/hid-gaff.c @@ -29,13 +29,11 @@ #include #include -#include #include #include #include "hid-ids.h" #ifdef CONFIG_GREENASIA_FF -#include "usbhid/usbhid.h" struct gaff_device { struct hid_report *report; @@ -63,14 +61,14 @@ static int hid_gaff_play(struct input_dev *dev, void *data, gaff->report->field[0]->value[4] = left; gaff->report->field[0]->value[5] = 0; dbg_hid("running with 0x%02x 0x%02x", left, right); - usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); + hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT); gaff->report->field[0]->value[0] = 0xfa; gaff->report->field[0]->value[1] = 0xfe; gaff->report->field[0]->value[2] = 0x0; gaff->report->field[0]->value[4] = 0x0; - usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); + hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT); return 0; } @@ -122,12 +120,12 @@ static int gaff_init(struct hid_device *hid) gaff->report->field[0]->value[1] = 0x00; gaff->report->field[0]->value[2] = 0x00; gaff->report->field[0]->value[3] = 0x00; - usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); + hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT); gaff->report->field[0]->value[0] = 0xfa; gaff->report->field[0]->value[1] = 0xfe; - usbhid_submit_report(hid, gaff->report, USB_DIR_OUT); + hid_hw_request(hid, gaff->report, HID_REQ_SET_REPORT); hid_info(hid, "Force Feedback for GreenAsia 0x12 devices by Lukasz Lubojanski \n"); diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c index f34d1186a3e1..9a8f05124525 100644 --- a/drivers/hid/hid-holtekff.c +++ b/drivers/hid/hid-holtekff.c @@ -27,12 +27,10 @@ #include #include #include -#include #include "hid-ids.h" #ifdef CONFIG_HOLTEK_FF -#include "usbhid/usbhid.h" MODULE_LICENSE("GPL"); MODULE_AUTHOR("Anssi Hannula "); @@ -102,7 +100,7 @@ static void holtekff_send(struct holtekff_device *holtekff, dbg_hid("sending %*ph\n", 7, data); - usbhid_submit_report(hid, holtekff->field->report, USB_DIR_OUT); + hid_hw_request(hid, holtekff->field->report, HID_REQ_SET_REPORT); } static int holtekff_play(struct input_dev *dev, void *data, diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c index ef72daecfa16..6af90dbdc3d4 100644 --- a/drivers/hid/hid-kye.c +++ b/drivers/hid/hid-kye.c @@ -16,8 +16,6 @@ #include #include #include -#include -#include "usbhid/usbhid.h" #include "hid-ids.h" @@ -361,7 +359,7 @@ static int kye_tablet_enable(struct hid_device *hdev) value[4] = 0x00; value[5] = 0x00; value[6] = 0x00; - usbhid_submit_report(hdev, report, USB_DIR_OUT); + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); return 0; } diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c index 956c3b135f64..a0535fd7a798 100644 --- a/drivers/hid/hid-lenovo-tpkbd.c +++ b/drivers/hid/hid-lenovo-tpkbd.c @@ -68,7 +68,7 @@ static int tpkbd_features_set(struct hid_device *hdev) report->field[2]->value[0] = data_pointer->sensitivity; report->field[3]->value[0] = data_pointer->press_speed; - usbhid_submit_report(hdev, report, USB_DIR_OUT); + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); return 0; } @@ -332,7 +332,7 @@ static void tpkbd_led_brightness_set(struct led_classdev *led_cdev, report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3]; report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1; report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1; - usbhid_submit_report(hdev, report, USB_DIR_OUT); + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); } static int tpkbd_probe_tp(struct hid_device *hdev) diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c index 3c31bc650e5d..b3cd1507dda2 100644 --- a/drivers/hid/hid-lg2ff.c +++ b/drivers/hid/hid-lg2ff.c @@ -23,10 +23,8 @@ #include #include -#include #include -#include "usbhid/usbhid.h" #include "hid-lg.h" struct lg2ff_device { @@ -56,7 +54,7 @@ static int play_effect(struct input_dev *dev, void *data, lg2ff->report->field[0]->value[4] = 0x00; } - usbhid_submit_report(hid, lg2ff->report, USB_DIR_OUT); + hid_hw_request(hid, lg2ff->report, HID_REQ_SET_REPORT); return 0; } @@ -108,7 +106,7 @@ int lg2ff_init(struct hid_device *hid) report->field[0]->value[5] = 0x00; report->field[0]->value[6] = 0x00; - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); hid_info(hid, "Force feedback for Logitech RumblePad/Rumblepad 2 by Anssi Hannula \n"); diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c index f98644c26c1d..e52f181f6aa1 100644 --- a/drivers/hid/hid-lg3ff.c +++ b/drivers/hid/hid-lg3ff.c @@ -22,10 +22,8 @@ #include -#include #include -#include "usbhid/usbhid.h" #include "hid-lg.h" /* @@ -92,7 +90,7 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data, report->field[0]->value[1] = (unsigned char)(-x); report->field[0]->value[31] = (unsigned char)(-y); - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); break; } return 0; @@ -118,7 +116,7 @@ static void hid_lg3ff_set_autocenter(struct input_dev *dev, u16 magnitude) report->field[0]->value[33] = 0x7F; report->field[0]->value[34] = 0x7F; - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); } diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 65a6ec8d3742..7da40a1797cd 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -202,7 +202,7 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *e value[5] = 0x00; value[6] = 0x00; - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); break; } return 0; @@ -225,7 +225,7 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud value[5] = 0x00; value[6] = 0x00; - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); } /* Sends autocentering command compatible with Formula Force EX */ @@ -245,7 +245,7 @@ static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) value[5] = 0x00; value[6] = 0x00; - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); } /* Sends command to set range compatible with G25/G27/Driving Force GT */ @@ -265,7 +265,7 @@ static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range) value[5] = 0x00; value[6] = 0x00; - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); } /* Sends commands to set range compatible with Driving Force Pro wheel */ @@ -294,7 +294,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) report->field[0]->value[1] = 0x02; full_range = 200; } - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); /* Prepare "fine" limit command */ value[0] = 0x81; @@ -306,7 +306,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) value[6] = 0x00; if (range == 200 || range == 900) { /* Do not apply any fine limit */ - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); return; } @@ -320,7 +320,7 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) value[5] = (start_right & 0xe) << 4 | (start_left & 0xe); value[6] = 0xff; - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); } static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd) @@ -334,7 +334,7 @@ static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_n for (i = 0; i < 7; i++) report->field[0]->value[i] = cmd->cmd[j++]; - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); } } @@ -410,7 +410,7 @@ static void lg4ff_set_leds(struct hid_device *hid, __u8 leds) value[4] = 0x00; value[5] = 0x00; value[6] = 0x00; - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); } static void lg4ff_led_set_brightness(struct led_classdev *led_cdev, diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index 27bc54f92f44..d7ea8c845b40 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c @@ -30,10 +30,8 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include -#include #include -#include "usbhid/usbhid.h" #include "hid-lg.h" struct dev_type { @@ -89,7 +87,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef report->field[0]->value[2] = x; report->field[0]->value[3] = y; dbg_hid("(x, y)=(%04x, %04x)\n", x, y); - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); break; case FF_RUMBLE: @@ -104,7 +102,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef report->field[0]->value[2] = left; report->field[0]->value[3] = right; dbg_hid("(left, right)=(%04x, %04x)\n", left, right); - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); break; } return 0; @@ -124,7 +122,7 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) *value++ = 0x80; *value++ = 0x00; *value = 0x00; - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); } int lgff_init(struct hid_device* hid) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 9500f2f3f8fe..3cf62be2ca5d 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -27,7 +27,6 @@ #include #include #include -#include "usbhid/usbhid.h" #include "hid-ids.h" #include "hid-logitech-dj.h" @@ -638,7 +637,7 @@ static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type, hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS); hid_set_field(report->field[0], 2, data[1]); - usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT); + hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT); return 0; diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 7a1ebb867cf4..32258ba60056 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -736,7 +736,7 @@ static void mt_set_input_mode(struct hid_device *hdev) r = re->report_id_hash[td->inputmode]; if (r) { r->field[0]->value[td->inputmode_index] = 0x02; - usbhid_submit_report(hdev, r, USB_DIR_OUT); + hid_hw_request(hdev, r, HID_REQ_SET_REPORT); } } @@ -761,7 +761,7 @@ static void mt_set_maxcontacts(struct hid_device *hdev) max = min(fieldmax, max); if (r->field[0]->value[0] != max) { r->field[0]->value[0] = max; - usbhid_submit_report(hdev, r, USB_DIR_OUT); + hid_hw_request(hdev, r, HID_REQ_SET_REPORT); } } } diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 7757e82416e7..b926592e6c16 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -118,7 +118,7 @@ static inline int ntrig_get_mode(struct hid_device *hdev) if (!report) return -EINVAL; - usbhid_submit_report(hdev, report, USB_DIR_IN); + hid_hw_request(hdev, report, HID_REQ_GET_REPORT); usbhid_wait_io(hdev); return (int)report->field[0]->value[0]; } @@ -137,7 +137,7 @@ static inline void ntrig_set_mode(struct hid_device *hdev, const int mode) if (!report) return; - usbhid_submit_report(hdev, report, USB_DIR_IN); + hid_hw_request(hdev, report, HID_REQ_GET_REPORT); } static void ntrig_report_version(struct hid_device *hdev) @@ -938,7 +938,7 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) /* Let the device settle to ensure the wakeup message gets * through */ usbhid_wait_io(hdev); - usbhid_submit_report(hdev, report, USB_DIR_IN); + hid_hw_request(hdev, report, HID_REQ_GET_REPORT); /* * Sanity check: if the current mode is invalid reset it to diff --git a/drivers/hid/hid-picolcd.h b/drivers/hid/hid-picolcd.h index 020cef69f6a1..2941891ecac2 100644 --- a/drivers/hid/hid-picolcd.h +++ b/drivers/hid/hid-picolcd.h @@ -142,10 +142,10 @@ struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir); #ifdef CONFIG_DEBUG_FS void picolcd_debug_out_report(struct picolcd_data *data, struct hid_device *hdev, struct hid_report *report); -#define usbhid_submit_report(a, b, c) \ +#define hid_hw_request(a, b, c) \ do { \ picolcd_debug_out_report(hid_get_drvdata(a), a, b); \ - usbhid_submit_report(a, b, c); \ + hid_hw_request(a, b, c); \ } while (0) void picolcd_debug_raw_event(struct picolcd_data *data, diff --git a/drivers/hid/hid-picolcd_backlight.c b/drivers/hid/hid-picolcd_backlight.c index b91f30945f9c..a32c5f86b0b3 100644 --- a/drivers/hid/hid-picolcd_backlight.c +++ b/drivers/hid/hid-picolcd_backlight.c @@ -18,8 +18,6 @@ ***************************************************************************/ #include -#include "usbhid/usbhid.h" -#include #include #include @@ -46,7 +44,7 @@ static int picolcd_set_brightness(struct backlight_device *bdev) spin_lock_irqsave(&data->lock, flags); hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0); if (!(data->status & PICOLCD_FAILED)) - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&data->lock, flags); return 0; } diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c index a79e95bb9fb6..e346038f0f11 100644 --- a/drivers/hid/hid-picolcd_cir.c +++ b/drivers/hid/hid-picolcd_cir.c @@ -21,8 +21,6 @@ #include #include #include "hid-ids.h" -#include "usbhid/usbhid.h" -#include #include #include diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c index 31cd93fc3d4b..b48092d0e139 100644 --- a/drivers/hid/hid-picolcd_core.c +++ b/drivers/hid/hid-picolcd_core.c @@ -21,8 +21,6 @@ #include #include #include "hid-ids.h" -#include "usbhid/usbhid.h" -#include #include #include @@ -110,7 +108,7 @@ struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, work = NULL; } else { data->pending = work; - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&data->lock, flags); wait_for_completion_interruptible_timeout(&work->ready, HZ*2); spin_lock_irqsave(&data->lock, flags); @@ -244,7 +242,7 @@ int picolcd_reset(struct hid_device *hdev) spin_unlock_irqrestore(&data->lock, flags); return -ENODEV; } - usbhid_submit_report(hdev, report, USB_DIR_OUT); + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&data->lock, flags); error = picolcd_check_version(hdev); @@ -303,7 +301,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev, spin_lock_irqsave(&data->lock, flags); hid_set_field(report->field[0], 0, timeout & 0xff); hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff); - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&data->lock, flags); return count; } diff --git a/drivers/hid/hid-picolcd_debugfs.c b/drivers/hid/hid-picolcd_debugfs.c index 4809aa1bdb9c..59ab8e157e6b 100644 --- a/drivers/hid/hid-picolcd_debugfs.c +++ b/drivers/hid/hid-picolcd_debugfs.c @@ -19,8 +19,6 @@ #include #include -#include "usbhid/usbhid.h" -#include #include #include diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c index eb003574b634..98f61de9a5e0 100644 --- a/drivers/hid/hid-picolcd_fb.c +++ b/drivers/hid/hid-picolcd_fb.c @@ -20,7 +20,6 @@ #include #include #include "usbhid/usbhid.h" -#include #include #include @@ -143,8 +142,8 @@ static int picolcd_fb_send_tile(struct picolcd_data *data, u8 *vbitmap, else hid_set_field(report2->field[0], 4 + i - 32, tdata[i]); - usbhid_submit_report(data->hdev, report1, USB_DIR_OUT); - usbhid_submit_report(data->hdev, report2, USB_DIR_OUT); + hid_hw_request(data->hdev, report1, HID_REQ_SET_REPORT); + hid_hw_request(data->hdev, report2, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&data->lock, flags); return 0; } @@ -214,7 +213,7 @@ int picolcd_fb_reset(struct picolcd_data *data, int clear) hid_set_field(report->field[0], j, mapcmd[j]); else hid_set_field(report->field[0], j, 0); - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); } spin_unlock_irqrestore(&data->lock, flags); diff --git a/drivers/hid/hid-picolcd_lcd.c b/drivers/hid/hid-picolcd_lcd.c index 2d0ddc5ac65f..89821c2da6d7 100644 --- a/drivers/hid/hid-picolcd_lcd.c +++ b/drivers/hid/hid-picolcd_lcd.c @@ -18,8 +18,6 @@ ***************************************************************************/ #include -#include "usbhid/usbhid.h" -#include #include #include @@ -48,7 +46,7 @@ static int picolcd_set_contrast(struct lcd_device *ldev, int contrast) spin_lock_irqsave(&data->lock, flags); hid_set_field(report->field[0], 0, data->lcd_contrast); if (!(data->status & PICOLCD_FAILED)) - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&data->lock, flags); return 0; } diff --git a/drivers/hid/hid-picolcd_leds.c b/drivers/hid/hid-picolcd_leds.c index 28cb6a4f9634..e994f9c29012 100644 --- a/drivers/hid/hid-picolcd_leds.c +++ b/drivers/hid/hid-picolcd_leds.c @@ -21,8 +21,6 @@ #include #include #include "hid-ids.h" -#include "usbhid/usbhid.h" -#include #include #include @@ -55,7 +53,7 @@ void picolcd_leds_set(struct picolcd_data *data) spin_lock_irqsave(&data->lock, flags); hid_set_field(report->field[0], 0, data->led_state); if (!(data->status & PICOLCD_FAILED)) - usbhid_submit_report(data->hdev, report, USB_DIR_OUT); + hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&data->lock, flags); } diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c index b0199d27787b..d29112fa5cd5 100644 --- a/drivers/hid/hid-pl.c +++ b/drivers/hid/hid-pl.c @@ -43,13 +43,11 @@ #include #include #include -#include #include #include "hid-ids.h" #ifdef CONFIG_PANTHERLORD_FF -#include "usbhid/usbhid.h" struct plff_device { struct hid_report *report; @@ -75,7 +73,7 @@ static int hid_plff_play(struct input_dev *dev, void *data, *plff->strong = left; *plff->weak = right; debug("running with 0x%02x 0x%02x", left, right); - usbhid_submit_report(hid, plff->report, USB_DIR_OUT); + hid_hw_request(hid, plff->report, HID_REQ_SET_REPORT); return 0; } @@ -169,7 +167,7 @@ static int plff_init(struct hid_device *hid) *strong = 0x00; *weak = 0x00; - usbhid_submit_report(hid, plff->report, USB_DIR_OUT); + hid_hw_request(hid, plff->report, HID_REQ_SET_REPORT); } hid_info(hid, "Force feedback for PantherLord/GreenAsia devices by Anssi Hannula \n"); diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 4e1c4bcbdc03..7ed828056414 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c @@ -26,7 +26,6 @@ #include #include #include -#include "usbhid/usbhid.h" #include "hid-ids.h" @@ -306,7 +305,7 @@ static void pcmidi_submit_output_report(struct pcmidi_snd *pm, int state) report->field[0]->value[0] = 0x01; report->field[0]->value[1] = state; - usbhid_submit_report(hdev, report, USB_DIR_OUT); + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); } static int pcmidi_handle_report1(struct pcmidi_snd *pm, u8 *data) diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 6679788bf75a..59d29f853ac0 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -18,7 +18,6 @@ */ #include #include -#include #include "usbhid/usbhid.h" #include #include @@ -204,7 +203,7 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, goto done_proc; } hid_set_field(report->field[field_index], 0, value); - usbhid_submit_report(hsdev->hdev, report, USB_DIR_OUT); + hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT); usbhid_wait_io(hsdev->hdev); done_proc: @@ -227,7 +226,7 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, ret = -EINVAL; goto done_proc; } - usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN); + hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT); usbhid_wait_io(hsdev->hdev); *value = report->field[field_index]->value[0]; @@ -262,7 +261,7 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev, spin_unlock_irqrestore(&data->lock, flags); goto err_free; } - usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN); + hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT); spin_unlock_irqrestore(&data->lock, flags); wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5); switch (data->pending.raw_size) { diff --git a/drivers/hid/hid-sjoy.c b/drivers/hid/hid-sjoy.c index 28f774003f03..37845eccddb5 100644 --- a/drivers/hid/hid-sjoy.c +++ b/drivers/hid/hid-sjoy.c @@ -28,13 +28,11 @@ #include #include -#include #include #include #include "hid-ids.h" #ifdef CONFIG_SMARTJOYPLUS_FF -#include "usbhid/usbhid.h" struct sjoyff_device { struct hid_report *report; @@ -57,7 +55,7 @@ static int hid_sjoyff_play(struct input_dev *dev, void *data, sjoyff->report->field[0]->value[1] = right; sjoyff->report->field[0]->value[2] = left; dev_dbg(&dev->dev, "running with 0x%02x 0x%02x\n", left, right); - usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); + hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT); return 0; } @@ -115,7 +113,7 @@ static int sjoyff_init(struct hid_device *hid) sjoyff->report->field[0]->value[0] = 0x01; sjoyff->report->field[0]->value[1] = 0x00; sjoyff->report->field[0]->value[2] = 0x00; - usbhid_submit_report(hid, sjoyff->report, USB_DIR_OUT); + hid_hw_request(hid, sjoyff->report, HID_REQ_SET_REPORT); } hid_info(hid, "Force feedback for SmartJoy PLUS PS2/USB adapter\n"); diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c index 2ed995cda44a..98e66ac71842 100644 --- a/drivers/hid/hid-steelseries.c +++ b/drivers/hid/hid-steelseries.c @@ -16,7 +16,6 @@ #include #include -#include "usbhid/usbhid.h" #include "hid-ids.h" #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) @@ -132,7 +131,7 @@ static void steelseries_srws1_set_leds(struct hid_device *hdev, __u16 leds) value[14] = 0x00; value[15] = 0x00; - usbhid_submit_report(hdev, report, USB_DIR_OUT); + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); /* Note: LED change does not show on device until the device is read/polled */ } diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c index e4fcf3f702a5..b83376077d72 100644 --- a/drivers/hid/hid-tmff.c +++ b/drivers/hid/hid-tmff.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include "hid-ids.h" @@ -46,7 +45,6 @@ static const signed short ff_joystick[] = { }; #ifdef CONFIG_THRUSTMASTER_FF -#include "usbhid/usbhid.h" /* Usages for thrustmaster devices I know about */ #define THRUSTMASTER_USAGE_FF (HID_UP_GENDESK | 0xbb) @@ -103,7 +101,7 @@ static int tmff_play(struct input_dev *dev, void *data, dbg_hid("(x, y)=(%04x, %04x)\n", x, y); ff_field->value[0] = x; ff_field->value[1] = y; - usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); + hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT); break; case FF_RUMBLE: @@ -117,7 +115,7 @@ static int tmff_play(struct input_dev *dev, void *data, dbg_hid("(left,right)=(%08x, %08x)\n", left, right); ff_field->value[0] = left; ff_field->value[1] = right; - usbhid_submit_report(hid, tmff->report, USB_DIR_OUT); + hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT); break; } return 0; diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c index af66452592e9..6ec28a37c146 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c @@ -24,13 +24,11 @@ #include #include #include -#include #include #include "hid-ids.h" #ifdef CONFIG_ZEROPLUS_FF -#include "usbhid/usbhid.h" struct zpff_device { struct hid_report *report; @@ -59,7 +57,7 @@ static int zpff_play(struct input_dev *dev, void *data, zpff->report->field[2]->value[0] = left; zpff->report->field[3]->value[0] = right; dbg_hid("running with 0x%02x 0x%02x\n", left, right); - usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); + hid_hw_request(hid, zpff->report, HID_REQ_SET_REPORT); return 0; } @@ -104,7 +102,7 @@ static int zpff_init(struct hid_device *hid) zpff->report->field[1]->value[0] = 0x02; zpff->report->field[2]->value[0] = 0x00; zpff->report->field[3]->value[0] = 0x00; - usbhid_submit_report(hid, zpff->report, USB_DIR_OUT); + hid_hw_request(hid, zpff->report, HID_REQ_SET_REPORT); hid_info(hid, "force feedback for Zeroplus based devices by Anssi Hannula \n"); diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 99d95d3368b5..da68687d2c7c 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -639,7 +639,7 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re } } -void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) +static void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir) { struct usbhid_device *usbhid = hid->driver_data; unsigned long flags; @@ -648,7 +648,6 @@ void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, uns __usbhid_submit_report(hid, report, dir); spin_unlock_irqrestore(&usbhid->lock, flags); } -EXPORT_SYMBOL_GPL(usbhid_submit_report); /* Workqueue routine to send requests to change LEDs */ static void hid_led(struct work_struct *work) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index f91c136821f7..0f1efa39ec46 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -263,8 +263,8 @@ static void pidff_set_envelope_report(struct pidff_device *pidff, envelope->attack_level, pidff->set_envelope[PID_ATTACK_LEVEL].value[0]); - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE], - USB_DIR_OUT); + hid_hw_request(pidff->hid, pidff->reports[PID_SET_ENVELOPE], + HID_REQ_SET_REPORT); } /* @@ -290,8 +290,8 @@ static void pidff_set_constant_force_report(struct pidff_device *pidff, pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE], effect->u.constant.level); - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT], - USB_DIR_OUT); + hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONSTANT], + HID_REQ_SET_REPORT); } /* @@ -325,8 +325,8 @@ static void pidff_set_effect_report(struct pidff_device *pidff, pidff->effect_direction); pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay; - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], - USB_DIR_OUT); + hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT], + HID_REQ_SET_REPORT); } /* @@ -357,8 +357,8 @@ static void pidff_set_periodic_report(struct pidff_device *pidff, pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase); pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period; - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC], - USB_DIR_OUT); + hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC], + HID_REQ_SET_REPORT); } @@ -399,8 +399,8 @@ static void pidff_set_condition_report(struct pidff_device *pidff, effect->u.condition[i].left_saturation); pidff_set(&pidff->set_condition[PID_DEAD_BAND], effect->u.condition[i].deadband); - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION], - USB_DIR_OUT); + hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONDITION], + HID_REQ_SET_REPORT); } } @@ -440,8 +440,8 @@ static void pidff_set_ramp_force_report(struct pidff_device *pidff, effect->u.ramp.start_level); pidff_set_signed(&pidff->set_ramp[PID_RAMP_END], effect->u.ramp.end_level); - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP], - USB_DIR_OUT); + hid_hw_request(pidff->hid, pidff->reports[PID_SET_RAMP], + HID_REQ_SET_REPORT); } /* @@ -465,8 +465,8 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) int j; pidff->create_new_effect_type->value[0] = efnum; - usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], - USB_DIR_OUT); + hid_hw_request(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT], + HID_REQ_SET_REPORT); hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum); pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; @@ -475,8 +475,8 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) for (j = 0; j < 60; j++) { hid_dbg(pidff->hid, "pid_block_load requested\n"); - usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD], - USB_DIR_IN); + hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_LOAD], + HID_REQ_GET_REPORT); usbhid_wait_io(pidff->hid); if (pidff->block_load_status->value[0] == pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { @@ -513,8 +513,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n) pidff->effect_operation[PID_LOOP_COUNT].value[0] = n; } - usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], - USB_DIR_OUT); + hid_hw_request(pidff->hid, pidff->reports[PID_EFFECT_OPERATION], + HID_REQ_SET_REPORT); } /** @@ -535,8 +535,8 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value) static void pidff_erase_pid(struct pidff_device *pidff, int pid_id) { pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id; - usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE], - USB_DIR_OUT); + hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_FREE], + HID_REQ_SET_REPORT); } /* @@ -718,8 +718,8 @@ static void pidff_set_gain(struct input_dev *dev, u16 gain) struct pidff_device *pidff = dev->ff->private; pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain); - usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN], - USB_DIR_OUT); + hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN], + HID_REQ_SET_REPORT); } static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) @@ -744,8 +744,8 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude) pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1; pidff->set_effect[PID_START_DELAY].value[0] = 0; - usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT], - USB_DIR_OUT); + hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT], + HID_REQ_SET_REPORT); } /* @@ -1158,18 +1158,18 @@ static void pidff_reset(struct pidff_device *pidff) pidff->device_control->value[0] = pidff->control_id[PID_RESET]; /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ - usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); + hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); usbhid_wait_io(hid); - usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); + hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); usbhid_wait_io(hid); pidff->device_control->value[0] = pidff->control_id[PID_ENABLE_ACTUATORS]; - usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT); + hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); usbhid_wait_io(hid); /* pool report is sometimes messed up, refetch it */ - usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN); + hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT); usbhid_wait_io(hid); if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { @@ -1181,8 +1181,8 @@ static void pidff_reset(struct pidff_device *pidff) break; } hid_dbg(pidff->hid, "pid_pool requested again\n"); - usbhid_submit_report(hid, pidff->reports[PID_POOL], - USB_DIR_IN); + hid_hw_request(hid, pidff->reports[PID_POOL], + HID_REQ_GET_REPORT); usbhid_wait_io(hid); } } @@ -1269,8 +1269,8 @@ int hid_pidff_init(struct hid_device *hid) if (test_bit(FF_GAIN, dev->ffbit)) { pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff); - usbhid_submit_report(hid, pidff->reports[PID_DEVICE_GAIN], - USB_DIR_OUT); + hid_hw_request(hid, pidff->reports[PID_DEVICE_GAIN], + HID_REQ_SET_REPORT); } error = pidff_check_autocenter(pidff, dev); diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 87bd64959a91..430d2a9e4521 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -705,7 +705,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (report == NULL) break; - usbhid_submit_report(hid, report, USB_DIR_IN); + hid_hw_request(hid, report, HID_REQ_GET_REPORT); usbhid_wait_io(hid); r = 0; @@ -724,7 +724,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (report == NULL) break; - usbhid_submit_report(hid, report, USB_DIR_OUT); + hid_hw_request(hid, report, HID_REQ_SET_REPORT); usbhid_wait_io(hid); r = 0; diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index bd87a61e5303..aa1d5ff1208f 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h @@ -38,8 +38,6 @@ int usbhid_wait_io(struct hid_device* hid); void usbhid_close(struct hid_device *hid); int usbhid_open(struct hid_device *hid); void usbhid_init_reports(struct hid_device *hid); -void usbhid_submit_report -(struct hid_device *hid, struct hid_report *report, unsigned char dir); int usbhid_get_power(struct hid_device *hid); void usbhid_put_power(struct hid_device *hid); struct usb_interface *usbhid_find_interface(int minor); From b7966a4d7be0a10329f03330390f4bdaf453d74a Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 25 Feb 2013 11:31:47 +0100 Subject: [PATCH 05/19] HID: use hid_hw_wait() instead of direct call to usbhid This removes most of the dependencies between hid drivers and usbhid. The patch was constructed by replacing all occurences of usbhid_wait_io() by its hid_hw_wait() counterpart. Then, drivers not requiring USB_HID anymore have their USB_HID dependency cleaned in the Kconfig file. As of today, few drivers are still requiring an explicit USB layer dependency: * ntrig (a patch is on its way) * multitouch (one patch following and another on its way) * lenovo tpkbd * roccat * sony The last three are two deeply using direct calls to the usb subsystem to be able to be cleaned right now. Signed-off-by: Benjamin Tissoires Reviewed-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 2 +- drivers/hid/hid-ntrig.c | 4 ++-- drivers/hid/hid-picolcd_fb.c | 5 ++--- drivers/hid/hid-sensor-hub.c | 5 ++--- drivers/hid/usbhid/hid-core.c | 3 +-- drivers/hid/usbhid/hid-pidff.c | 16 ++++++++-------- drivers/hid/usbhid/hiddev.c | 4 ++-- drivers/hid/usbhid/usbhid.h | 1 - 8 files changed, 18 insertions(+), 22 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index f0acf2754b69..c802b0716f48 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -479,7 +479,7 @@ config HID_PETALYNX config HID_PICOLCD tristate "PicoLCD (graphic version)" - depends on USB_HID + depends on HID ---help--- This provides support for Minibox PicoLCD devices, currently only the graphical ones are supported. diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index b926592e6c16..ef95102515e4 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -119,7 +119,7 @@ static inline int ntrig_get_mode(struct hid_device *hdev) return -EINVAL; hid_hw_request(hdev, report, HID_REQ_GET_REPORT); - usbhid_wait_io(hdev); + hid_hw_wait(hdev); return (int)report->field[0]->value[0]; } @@ -937,7 +937,7 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) if (report) { /* Let the device settle to ensure the wakeup message gets * through */ - usbhid_wait_io(hdev); + hid_hw_wait(hdev); hid_hw_request(hdev, report, HID_REQ_GET_REPORT); /* diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c index 98f61de9a5e0..591f6b22aa94 100644 --- a/drivers/hid/hid-picolcd_fb.c +++ b/drivers/hid/hid-picolcd_fb.c @@ -19,7 +19,6 @@ #include #include -#include "usbhid/usbhid.h" #include #include @@ -269,7 +268,7 @@ static void picolcd_fb_update(struct fb_info *info) mutex_unlock(&info->lock); if (!data) return; - usbhid_wait_io(data->hdev); + hid_hw_wait(data->hdev); mutex_lock(&info->lock); n = 0; } @@ -287,7 +286,7 @@ static void picolcd_fb_update(struct fb_info *info) spin_unlock_irqrestore(&fbdata->lock, flags); mutex_unlock(&info->lock); if (data) - usbhid_wait_io(data->hdev); + hid_hw_wait(data->hdev); return; } out: diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 59d29f853ac0..ca7498107327 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -18,7 +18,6 @@ */ #include #include -#include "usbhid/usbhid.h" #include #include #include @@ -204,7 +203,7 @@ int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, } hid_set_field(report->field[field_index], 0, value); hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT); - usbhid_wait_io(hsdev->hdev); + hid_hw_wait(hsdev->hdev); done_proc: mutex_unlock(&data->mutex); @@ -227,7 +226,7 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, goto done_proc; } hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT); - usbhid_wait_io(hsdev->hdev); + hid_hw_wait(hsdev->hdev); *value = report->field[field_index]->value[0]; done_proc: diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index da68687d2c7c..420466bc481a 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -705,7 +705,7 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un return 0; } -int usbhid_wait_io(struct hid_device *hid) +static int usbhid_wait_io(struct hid_device *hid) { struct usbhid_device *usbhid = hid->driver_data; @@ -719,7 +719,6 @@ int usbhid_wait_io(struct hid_device *hid) return 0; } -EXPORT_SYMBOL_GPL(usbhid_wait_io); static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) { diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 0f1efa39ec46..10b616702780 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -471,13 +471,13 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum) pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0; pidff->block_load_status->value[0] = 0; - usbhid_wait_io(pidff->hid); + hid_hw_wait(pidff->hid); for (j = 0; j < 60; j++) { hid_dbg(pidff->hid, "pid_block_load requested\n"); hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_LOAD], HID_REQ_GET_REPORT); - usbhid_wait_io(pidff->hid); + hid_hw_wait(pidff->hid); if (pidff->block_load_status->value[0] == pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) { hid_dbg(pidff->hid, "device reported free memory: %d bytes\n", @@ -551,7 +551,7 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id) effect_id, pidff->pid_id[effect_id]); /* Wait for the queue to clear. We do not want a full fifo to prevent the effect removal. */ - usbhid_wait_io(pidff->hid); + hid_hw_wait(pidff->hid); pidff_playback_pid(pidff, pid_id, 0); pidff_erase_pid(pidff, pid_id); @@ -1159,18 +1159,18 @@ static void pidff_reset(struct pidff_device *pidff) pidff->device_control->value[0] = pidff->control_id[PID_RESET]; /* We reset twice as sometimes hid_wait_io isn't waiting long enough */ hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); - usbhid_wait_io(hid); + hid_hw_wait(hid); hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); - usbhid_wait_io(hid); + hid_hw_wait(hid); pidff->device_control->value[0] = pidff->control_id[PID_ENABLE_ACTUATORS]; hid_hw_request(hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT); - usbhid_wait_io(hid); + hid_hw_wait(hid); /* pool report is sometimes messed up, refetch it */ hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT); - usbhid_wait_io(hid); + hid_hw_wait(hid); if (pidff->pool[PID_SIMULTANEOUS_MAX].value) { while (pidff->pool[PID_SIMULTANEOUS_MAX].value[0] < 2) { @@ -1183,7 +1183,7 @@ static void pidff_reset(struct pidff_device *pidff) hid_dbg(pidff->hid, "pid_pool requested again\n"); hid_hw_request(hid, pidff->reports[PID_POOL], HID_REQ_GET_REPORT); - usbhid_wait_io(hid); + hid_hw_wait(hid); } } } diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 430d2a9e4521..2f1ddca6f2e0 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -706,7 +706,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; hid_hw_request(hid, report, HID_REQ_GET_REPORT); - usbhid_wait_io(hid); + hid_hw_wait(hid); r = 0; break; @@ -725,7 +725,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; hid_hw_request(hid, report, HID_REQ_SET_REPORT); - usbhid_wait_io(hid); + hid_hw_wait(hid); r = 0; break; diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index aa1d5ff1208f..dbb6af699135 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h @@ -34,7 +34,6 @@ #include /* API provided by hid-core.c for USB HID drivers */ -int usbhid_wait_io(struct hid_device* hid); void usbhid_close(struct hid_device *hid); int usbhid_open(struct hid_device *hid); void usbhid_init_reports(struct hid_device *hid); From 4ebc9b636cdc340196138f35ca0788b8da0e1779 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 25 Feb 2013 11:31:48 +0100 Subject: [PATCH 06/19] HID: multitouch: remove explicit usbhid dependency This patch is part of the cleanup of the HID drivers against their low-level transport layer. With new touchscreens relying on I2C, it's better to handle now these dependencies before users get kernel oopses. Signed-off-by: Benjamin Tissoires Reviewed-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 32258ba60056..184ac0a42121 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -32,7 +32,6 @@ #include #include #include -#include "usbhid/usbhid.h" MODULE_AUTHOR("Stephane Chatty "); @@ -907,7 +906,7 @@ static int mt_resume(struct hid_device *hdev) intf = to_usb_interface(hdev->dev.parent); interface = intf->cur_altsetting; - dev = hid_to_usb_dev(hdev); + dev = interface_to_usbdev(intf); /* Some Elan legacy devices require SET_IDLE to be set on resume. * It should be safe to send it to other devices too. From b0a7868181be0a28fc35231d7435c1fb360eb675 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 25 Feb 2013 11:31:49 +0100 Subject: [PATCH 07/19] HID: multitouch: Copyright and note on regression tests This reflects my new company and officialize the regression tests I'm conducting between each change. Signed-off-by: Benjamin Tissoires Acked-by: Henrik Rydberg Reviewed-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 184ac0a42121..3af9efdd13d9 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -2,8 +2,9 @@ * HID driver for multitouch panels * * Copyright (c) 2010-2012 Stephane Chatty - * Copyright (c) 2010-2012 Benjamin Tissoires + * Copyright (c) 2010-2013 Benjamin Tissoires * Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France + * Copyright (c) 2012-2013 Red Hat, Inc * * This code is partly based on hid-egalax.c: * @@ -26,6 +27,17 @@ * any later version. */ +/* + * This driver is regularly tested thanks to the tool hid-test[1]. + * This tool relies on hid-replay[2] and a database of hid devices[3]. + * Please run these regression tests before patching this module so that + * your patch won't break existing known devices. + * + * [1] https://github.com/bentiss/hid-test + * [2] https://github.com/bentiss/hid-replay + * [3] https://github.com/bentiss/hid-devices + */ + #include #include #include From 545bef681088cbf49c9c11d63872698b81eac7eb Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 25 Feb 2013 11:31:50 +0100 Subject: [PATCH 08/19] HID: i2c-hid: implement request() callback This allows HID drivers to also get/set reports through hid_hw_request(). Tested-by: Mika Westerberg Signed-off-by: Benjamin Tissoires Signed-off-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index ec7930217a6d..935f387be95a 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -563,6 +563,37 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, return ret; } +static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep, + int reqtype) +{ + struct i2c_client *client = hid->driver_data; + struct i2c_hid *ihid = i2c_get_clientdata(client); + char *buf; + int ret; + + buf = kzalloc(ihid->bufsize, GFP_KERNEL); + if (!buf) + return; + + switch (reqtype) { + case HID_REQ_GET_REPORT: + ret = i2c_hid_get_raw_report(hid, rep->id, buf, ihid->bufsize, + rep->type); + if (ret < 0) + dev_err(&client->dev, "%s: unable to get report: %d\n", + __func__, ret); + else + hid_input_report(hid, rep->type, buf, ret, 0); + break; + case HID_REQ_SET_REPORT: + hid_output_report(rep, buf); + i2c_hid_output_raw_report(hid, buf, ihid->bufsize, rep->type); + break; + } + + kfree(buf); +} + static int i2c_hid_parse(struct hid_device *hid) { struct i2c_client *client = hid->driver_data; @@ -742,6 +773,7 @@ static struct hid_ll_driver i2c_hid_ll_driver = { .open = i2c_hid_open, .close = i2c_hid_close, .power = i2c_hid_power, + .request = i2c_hid_request, .hidinput_input_event = i2c_hid_hidinput_input_event, }; From 6399f335c2c5fb9c244bbb2b8a437498d260bed7 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 19 Feb 2013 11:22:33 +0200 Subject: [PATCH 09/19] HID: make sensor autodetection independent of underlying bus Instead of limiting HID sensors to USB and I2C busses we can just make everything that has usage page of HID_UP_SENSOR to be included in HID_GROUP_SENSOR_HUB group. This allows the sensor-hub to work over bluetooth (and other transports) as well. Reported-by: Alexander Holler Signed-off-by: Mika Westerberg Reviewed-By: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ff75cabf7393..fea20c650f3f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -728,8 +728,7 @@ static int hid_scan_report(struct hid_device *hid) } else if (page == HID_UP_SENSOR && item.type == HID_ITEM_TYPE_MAIN && item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION && - (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL && - (hid->bus == BUS_USB || hid->bus == BUS_I2C)) + (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL) hid->group = HID_GROUP_SENSOR_HUB; } From c849a6143bec520aff2a6646518b0d041402428b Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Mon, 18 Feb 2013 09:20:21 -0800 Subject: [PATCH 10/19] HID: Separate struct hid_device's driver_lock into two locks. This patch separates struct hid_device's driver_lock into two. The goal is to allow hid device drivers to receive input during their probe() or remove() function calls. This is necessary because some drivers need to communicate with the device to determine parameters needed during probe (e.g., size of a multi-touch surface), and if possible, may perfer to communicate with a device on host-initiated disconnect (e.g., to put it into a low-power state). Historically, three functions used driver_lock: - hid_device_probe: blocks to acquire lock - hid_device_remove: blocks to acquire lock - hid_input_report: if locked returns -EBUSY, else acquires lock This patch adds another lock (driver_input_lock) which is used to block input from occurring. The lock behavior is now: - hid_device_probe: blocks to acq. driver_lock, then driver_input_lock - hid_device_remove: blocks to acq. driver_lock, then driver_input_lock - hid_input_report: if driver_input_lock locked returns -EBUSY, else acquires driver_input_lock This patch also adds two helper functions to be called during probe() or remove(): hid_device_io_start() and hid_device_io_stop(). These functions lock and unlock, respectively, driver_input_lock; they also make a note of whether they did so that hid-core knows if a driver has changed the lock state. This patch results in no behavior change for existing devices and drivers. However, during a probe() or remove() function call in a driver, that driver may now selectively call hid_device_io_start() to let input events come through, then optionally call hid_device_io_stop() to stop them. Signed-off-by: Andrew de los Reyes Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 24 +++++++++++++++++++--- include/linux/hid.h | 46 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ff75cabf7393..680068c0c46a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1267,7 +1267,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i if (!hid) return -ENODEV; - if (down_trylock(&hid->driver_lock)) + if (down_trylock(&hid->driver_input_lock)) return -EBUSY; if (!hid->driver) { @@ -1324,7 +1324,7 @@ nomem: ret = hid_report_raw_event(hid, type, data, size, interrupt); unlock: - up(&hid->driver_lock); + up(&hid->driver_input_lock); return ret; } EXPORT_SYMBOL_GPL(hid_input_report); @@ -1845,6 +1845,11 @@ static int hid_device_probe(struct device *dev) if (down_interruptible(&hdev->driver_lock)) return -EINTR; + if (down_interruptible(&hdev->driver_input_lock)) { + ret = -EINTR; + goto unlock_driver_lock; + } + hdev->io_started = false; if (!hdev->driver) { id = hid_match_device(hdev, hdrv); @@ -1867,6 +1872,9 @@ static int hid_device_probe(struct device *dev) } } unlock: + if (!hdev->io_started) + up(&hdev->driver_input_lock); +unlock_driver_lock: up(&hdev->driver_lock); return ret; } @@ -1875,9 +1883,15 @@ static int hid_device_remove(struct device *dev) { struct hid_device *hdev = container_of(dev, struct hid_device, dev); struct hid_driver *hdrv; + int ret = 0; if (down_interruptible(&hdev->driver_lock)) return -EINTR; + if (down_interruptible(&hdev->driver_input_lock)) { + ret = -EINTR; + goto unlock_driver_lock; + } + hdev->io_started = false; hdrv = hdev->driver; if (hdrv) { @@ -1889,8 +1903,11 @@ static int hid_device_remove(struct device *dev) hdev->driver = NULL; } + if (!hdev->io_started) + up(&hdev->driver_input_lock); +unlock_driver_lock: up(&hdev->driver_lock); - return 0; + return ret; } static ssize_t modalias_show(struct device *dev, struct device_attribute *a, @@ -2329,6 +2346,7 @@ struct hid_device *hid_allocate_device(void) init_waitqueue_head(&hdev->debug_wait); INIT_LIST_HEAD(&hdev->debug_list); sema_init(&hdev->driver_lock, 1); + sema_init(&hdev->driver_input_lock, 1); return hdev; } diff --git a/include/linux/hid.h b/include/linux/hid.h index e14b465b1146..895b85639dec 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -456,7 +456,8 @@ struct hid_device { /* device report descriptor */ unsigned country; /* HID country */ struct hid_report_enum report_enum[HID_REPORT_TYPES]; - struct semaphore driver_lock; /* protects the current driver */ + struct semaphore driver_lock; /* protects the current driver, except during input */ + struct semaphore driver_input_lock; /* protects the current driver */ struct device dev; /* device */ struct hid_driver *driver; struct hid_ll_driver *ll_driver; @@ -477,6 +478,7 @@ struct hid_device { /* device report descriptor */ unsigned int status; /* see STAT flags above */ unsigned claimed; /* Claimed by hidinput, hiddev? */ unsigned quirks; /* Various quirks the device can pull on us */ + bool io_started; /* Protected by driver_lock. If IO has started */ struct list_head inputs; /* The list of inputs */ void *hiddev; /* The hiddev structure */ @@ -599,6 +601,10 @@ struct hid_usage_id { * @resume: invoked on resume if device was not reset (NULL means nop) * @reset_resume: invoked on resume if device was reset (NULL means nop) * + * probe should return -errno on error, or 0 on success. During probe, + * input will not be passed to raw_event unless hid_device_io_start is + * called. + * * raw_event and event should return 0 on no action performed, 1 when no * further processing should be done and negative on error * @@ -737,6 +743,44 @@ const struct hid_device_id *hid_match_id(struct hid_device *hdev, const struct hid_device_id *id); s32 hid_snto32(__u32 value, unsigned n); +/** + * hid_device_io_start - enable HID input during probe, remove + * + * @hid - the device + * + * This should only be called during probe or remove and only be + * called by the thread calling probe or remove. It will allow + * incoming packets to be delivered to the driver. + */ +static inline void hid_device_io_start(struct hid_device *hid) { + if (hid->io_started) { + dev_warn(&hid->dev, "io already started"); + return; + } + hid->io_started = true; + up(&hid->driver_input_lock); +} + +/** + * hid_device_io_stop - disable HID input during probe, remove + * + * @hid - the device + * + * Should only be called after hid_device_io_start. It will prevent + * incoming packets from going to the driver for the duration of + * probe, remove. If called during probe, packets will still go to the + * driver after probe is complete. This function should only be called + * by the thread calling probe or remove. + */ +static inline void hid_device_io_stop(struct hid_device *hid) { + if (!hid->io_started) { + dev_warn(&hid->dev, "io already stopped"); + return; + } + hid->io_started = false; + down(&hid->driver_input_lock); +} + /** * hid_map_usage - map usage input bits * From a9dd22b73085734735cfa07398451b061626cc53 Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Mon, 18 Feb 2013 09:20:22 -0800 Subject: [PATCH 11/19] HID: logitech-dj: Allow incoming packets during probe(). Historically, logitech-dj communicated with the device during probe() to query the list of devices attached. Later, a change was introduced to hid-core that prevented incoming packets for a device during probe(), as many drivers are unable to handle such input. That change broke the device enumeration in logitech-dj, so commit 596264082f10dd4a56 was introduced to workaround that by waiting for normal input before enumerating devices. Now that drivers can opt-in to receive input during probe, this patch changes logitech-dj to do that, so that it can successfully complete enumeration of devices during probe(). Signed-off-by: Andrew de los Reyes Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-dj.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 9500f2f3f8fe..bf647ef18086 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -803,6 +803,9 @@ static int logi_dj_probe(struct hid_device *hdev, goto llopen_failed; } + /* Allow incoming packets to arrive: */ + hid_device_io_start(hdev); + retval = logi_dj_recv_query_paired_devices(djrcv_dev); if (retval < 0) { dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices " From 8af6c08830b1ae114d1a8b548b1f8b056e068887 Mon Sep 17 00:00:00 2001 From: Andrew de los Reyes Date: Mon, 18 Feb 2013 09:20:23 -0800 Subject: [PATCH 12/19] Revert "HID: Fix logitech-dj: missing Unifying device issue" This reverts commit 596264082f10dd4a567c43d4526b2f54ac5520bc. The reverted commit was a workaround needed when drivers became unable to communicate with devices during probe(). Now that such communication is possible, the workaround is not needed. Signed-off-by: Andrew de los Reyes Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-dj.c | 45 ----------------------------------- drivers/hid/hid-logitech-dj.h | 1 - 2 files changed, 46 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index bf647ef18086..199b78c8a5f3 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -193,7 +193,6 @@ static struct hid_ll_driver logi_dj_ll_driver; static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf, size_t count, unsigned char report_type); -static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev); static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev, struct dj_report *dj_report) @@ -234,7 +233,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] & SPFUNCTION_DEVICE_LIST_EMPTY) { dbg_hid("%s: device list is empty\n", __func__); - djrcv_dev->querying_devices = false; return; } @@ -245,12 +243,6 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev, return; } - if (djrcv_dev->paired_dj_devices[dj_report->device_index]) { - /* The device is already known. No need to reallocate it. */ - dbg_hid("%s: device is already known\n", __func__); - return; - } - dj_hiddev = hid_allocate_device(); if (IS_ERR(dj_hiddev)) { dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n", @@ -314,7 +306,6 @@ static void delayedwork_callback(struct work_struct *work) struct dj_report dj_report; unsigned long flags; int count; - int retval; dbg_hid("%s\n", __func__); @@ -347,25 +338,6 @@ static void delayedwork_callback(struct work_struct *work) logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report); break; default: - /* A normal report (i. e. not belonging to a pair/unpair notification) - * arriving here, means that the report arrived but we did not have a - * paired dj_device associated to the report's device_index, this - * means that the original "device paired" notification corresponding - * to this dj_device never arrived to this driver. The reason is that - * hid-core discards all packets coming from a device while probe() is - * executing. */ - if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) { - /* ok, we don't know the device, just re-ask the - * receiver for the list of connected devices. */ - retval = logi_dj_recv_query_paired_devices(djrcv_dev); - if (!retval) { - /* everything went fine, so just leave */ - break; - } - dev_err(&djrcv_dev->hdev->dev, - "%s:logi_dj_recv_query_paired_devices " - "error:%d\n", __func__, retval); - } dbg_hid("%s: unexpected report type\n", __func__); } } @@ -396,12 +368,6 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev, if (!djdev) { dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" " is NULL, index %d\n", dj_report->device_index); - kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); - - if (schedule_work(&djrcv_dev->work) == 0) { - dbg_hid("%s: did not schedule the work item, was already " - "queued\n", __func__); - } return; } @@ -432,12 +398,6 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev, if (dj_device == NULL) { dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]" " is NULL, index %d\n", dj_report->device_index); - kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report)); - - if (schedule_work(&djrcv_dev->work) == 0) { - dbg_hid("%s: did not schedule the work item, was already " - "queued\n", __func__); - } return; } @@ -479,10 +439,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) struct dj_report *dj_report; int retval; - /* no need to protect djrcv_dev->querying_devices */ - if (djrcv_dev->querying_devices) - return 0; - dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL); if (!dj_report) return -ENOMEM; @@ -494,7 +450,6 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) return retval; } - static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, unsigned timeout) { diff --git a/drivers/hid/hid-logitech-dj.h b/drivers/hid/hid-logitech-dj.h index 4a4000340ce1..fd28a5e0ca3b 100644 --- a/drivers/hid/hid-logitech-dj.h +++ b/drivers/hid/hid-logitech-dj.h @@ -101,7 +101,6 @@ struct dj_receiver_dev { struct work_struct work; struct kfifo notif_fifo; spinlock_t lock; - bool querying_devices; }; struct dj_device { From 777d4bb39a585ff54817815544941c2da70a0bb9 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 7 Mar 2013 10:48:29 +0100 Subject: [PATCH 13/19] HID: holtek: Holtek devices depends on USB_HID In the HID drivers tranport cleanup series, I removed the dependency between hid-holtek and usbhid. This was wrong as hid-holtek.c relies extensively on usb calls. This fixes compilation error when CONFIG_USB_SUPPORT is not enabled. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index c802b0716f48..d1dcfc78bed2 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -215,7 +215,7 @@ config HID_EZKEY config HID_HOLTEK tristate "Holtek HID devices" - depends on HID + depends on USB_HID ---help--- Support for Holtek based devices: - Holtek On Line Grip based game controller From 9684819b5a29e62acd8265a92d8f3454de9bb71e Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 27 Feb 2013 16:38:17 +0100 Subject: [PATCH 14/19] HID: ll_driver: Extend the interface with idle requests Some drivers send the idle command directly to underlying device, creating an unwanted dependency on the underlying transport layer. This patch adds hid_hw_idle() to the interface, thereby removing usbhid from the lion share of the drivers. Signed-off-by: Benjamin Tissoires Reviewed-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 15 +++++++++++++++ include/linux/hid.h | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 420466bc481a..effcd3d6f5cf 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1253,6 +1253,20 @@ static void usbhid_request(struct hid_device *hid, struct hid_report *rep, int r } } +static int usbhid_idle(struct hid_device *hid, int report, int idle, + int reqtype) +{ + struct usb_device *dev = hid_to_usb_dev(hid); + struct usb_interface *intf = to_usb_interface(hid->dev.parent); + struct usb_host_interface *interface = intf->cur_altsetting; + int ifnum = interface->desc.bInterfaceNumber; + + if (reqtype != HID_REQ_SET_IDLE) + return -EINVAL; + + return hid_set_idle(dev, ifnum, report, idle); +} + static struct hid_ll_driver usb_hid_driver = { .parse = usbhid_parse, .start = usbhid_start, @@ -1263,6 +1277,7 @@ static struct hid_ll_driver usb_hid_driver = { .hidinput_input_event = usb_hidinput_input_event, .request = usbhid_request, .wait = usbhid_wait_io, + .idle = usbhid_idle, }; static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id) diff --git a/include/linux/hid.h b/include/linux/hid.h index 7071eb3d36c7..863744c38ddc 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -664,6 +664,7 @@ struct hid_driver { * shouldn't allocate anything to not leak memory * @request: send report request to device (e.g. feature report) * @wait: wait for buffered io to complete (send/recv reports) + * @idle: send idle request to device */ struct hid_ll_driver { int (*start)(struct hid_device *hdev); @@ -683,6 +684,7 @@ struct hid_ll_driver { struct hid_report *report, int reqtype); int (*wait)(struct hid_device *hdev); + int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype); }; @@ -906,6 +908,23 @@ static inline void hid_hw_request(struct hid_device *hdev, hdev->ll_driver->request(hdev, report, reqtype); } +/** + * hid_hw_idle - send idle request to device + * + * @hdev: hid device + * @report: report to control + * @idle: idle state + * @reqtype: hid request type + */ +static inline int hid_hw_idle(struct hid_device *hdev, int report, int idle, + int reqtype) +{ + if (hdev->ll_driver->idle) + return hdev->ll_driver->idle(hdev, report, idle, reqtype); + + return 0; +} + /** * hid_hw_wait - wait for buffered io to complete * From 4ba25d3f87fe3ed6634f61da2a6904e2dfd09192 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 27 Feb 2013 16:38:18 +0100 Subject: [PATCH 15/19] HID: multitouch: remove last usb dependency hid-multitouch used to direclty call for a set_idle in the .resume() callback. With the new hid_hw_idle(), this can be dropped and hid-multitouch is now freed from its transport layer. Signed-off-by: Benjamin Tissoires Reviewed-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 3af9efdd13d9..f712772437cb 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -909,26 +909,11 @@ static int mt_reset_resume(struct hid_device *hdev) static int mt_resume(struct hid_device *hdev) { - struct usb_interface *intf; - struct usb_host_interface *interface; - struct usb_device *dev; - - if (hdev->bus != BUS_USB) - return 0; - - intf = to_usb_interface(hdev->dev.parent); - interface = intf->cur_altsetting; - dev = interface_to_usbdev(intf); - /* Some Elan legacy devices require SET_IDLE to be set on resume. * It should be safe to send it to other devices too. * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */ - usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - HID_REQ_SET_IDLE, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, interface->desc.bInterfaceNumber, - NULL, 0, USB_CTRL_SET_TIMEOUT); + hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE); return 0; } From 7c4d577367fb710ea74a56955c5e3546fe5dd7ac Mon Sep 17 00:00:00 2001 From: Huzefa Kankroliwala Date: Wed, 3 Apr 2013 05:45:21 -0700 Subject: [PATCH 16/19] HID: i2c-hid: fix length for set/get report in i2c hid With the current i2c hid driver set/get report does not work as expected, for e.g sensor hub properties like power state, frequency etc is not set properly on the device as a result we do not get events. The problem is that i2c hid driver in function i2c_hid_request sets length equal to default buffer size for which the sensor hub does not respond on get/set commands. Use report length and calculate it based on report size and id. Reviewed-by: Mika Westerberg Reviewed-by: Benjamin Tissoires Signed-off-by: Huzefa Kankroliwala Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 935f387be95a..2b1799a3b212 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -567,18 +567,17 @@ static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype) { struct i2c_client *client = hid->driver_data; - struct i2c_hid *ihid = i2c_get_clientdata(client); char *buf; int ret; + int len = i2c_hid_get_report_length(rep) - 2; - buf = kzalloc(ihid->bufsize, GFP_KERNEL); + buf = kzalloc(len, GFP_KERNEL); if (!buf) return; switch (reqtype) { case HID_REQ_GET_REPORT: - ret = i2c_hid_get_raw_report(hid, rep->id, buf, ihid->bufsize, - rep->type); + ret = i2c_hid_get_raw_report(hid, rep->id, buf, len, rep->type); if (ret < 0) dev_err(&client->dev, "%s: unable to get report: %d\n", __func__, ret); @@ -587,7 +586,7 @@ static void i2c_hid_request(struct hid_device *hid, struct hid_report *rep, break; case HID_REQ_SET_REPORT: hid_output_report(rep, buf); - i2c_hid_output_raw_report(hid, buf, ihid->bufsize, rep->type); + i2c_hid_output_raw_report(hid, buf, len, rep->type); break; } From d991938a807a63c58c9c0fa6cd05cd2490aa6993 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Fri, 26 Apr 2013 19:29:54 -0600 Subject: [PATCH 17/19] HID: hid-lg4ff add support for new version of DFGT wheel It has been reported that there is a new version (different USB rev) of the Logitech DFGT in the 'wild'. This patch allows the kernel to recognise this wheel and send it the command to enter native mode. Reported-by: "Denis Jovic" Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-lg4ff.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 65a6ec8d3742..2dd73604c68f 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -34,6 +34,7 @@ #define DFGT_REV_MAJ 0x13 #define DFGT_REV_MIN 0x22 +#define DFGT2_REV_MIN 0x26 #define DFP_REV_MAJ 0x11 #define DFP_REV_MIN 0x06 #define FFEX_REV_MAJ 0x21 @@ -125,6 +126,7 @@ static const struct lg4ff_native_cmd native_g27 = { static const struct lg4ff_usb_revision lg4ff_revs[] = { {DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt}, /* Driving Force GT */ + {DFGT_REV_MAJ, DFGT2_REV_MIN, &native_dfgt}, /* Driving Force GT v2 */ {DFP_REV_MAJ, DFP_REV_MIN, &native_dfp}, /* Driving Force Pro */ {G25_REV_MAJ, G25_REV_MIN, &native_g25}, /* G25 */ {G27_REV_MAJ, G27_REV_MIN, &native_g27}, /* G27 */ From a5f04b9df1113e0c16271afe5e43028f0d763f13 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Wed, 17 Apr 2013 19:38:13 +0200 Subject: [PATCH 18/19] HID: debug: break out hid_dump_report() into hid-debug No semantic changes, but hid_dump_report should be in hid-debug.c, not in hid-core.c Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 25 ++----------------------- drivers/hid/hid-debug.c | 30 ++++++++++++++++++++++++++++++ include/linux/hid-debug.h | 6 ++++-- 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index aa341d135867..f86dd9708ca5 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1260,8 +1260,6 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i struct hid_report_enum *report_enum; struct hid_driver *hdrv; struct hid_report *report; - char *buf; - unsigned int i; int ret = 0; if (!hid) @@ -1284,28 +1282,9 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i } /* Avoid unnecessary overhead if debugfs is disabled */ - if (list_empty(&hid->debug_list)) - goto nomem; + if (!list_empty(&hid->debug_list)) + hid_dump_report(hid, type, data, size); - buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); - - if (!buf) - goto nomem; - - /* dump the report */ - snprintf(buf, HID_DEBUG_BUFSIZE - 1, - "\nreport (size %u) (%snumbered) = ", size, report_enum->numbered ? "" : "un"); - hid_debug_event(hid, buf); - - for (i = 0; i < size; i++) { - snprintf(buf, HID_DEBUG_BUFSIZE - 1, - " %02x", data[i]); - hid_debug_event(hid, buf); - } - hid_debug_event(hid, "\n"); - kfree(buf); - -nomem: report = hid_get_report(report_enum, data); if (!report) { diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 933fff0fff1f..094cbcfe1e1a 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -591,6 +591,36 @@ void hid_debug_event(struct hid_device *hdev, char *buf) } EXPORT_SYMBOL_GPL(hid_debug_event); +void hid_dump_report(struct hid_device *hid, int type, u8 *data, + int size) +{ + struct hid_report_enum *report_enum; + char *buf; + unsigned int i; + + buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC); + + if (!buf) + return; + + report_enum = hid->report_enum + type; + + /* dump the report */ + snprintf(buf, HID_DEBUG_BUFSIZE - 1, + "\nreport (size %u) (%snumbered) = ", size, + report_enum->numbered ? "" : "un"); + hid_debug_event(hid, buf); + + for (i = 0; i < size; i++) { + snprintf(buf, HID_DEBUG_BUFSIZE - 1, + " %02x", data[i]); + hid_debug_event(hid, buf); + } + hid_debug_event(hid, "\n"); + kfree(buf); +} +EXPORT_SYMBOL_GPL(hid_dump_report); + void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 value) { char *buf; diff --git a/include/linux/hid-debug.h b/include/linux/hid-debug.h index 53744fa1c8b7..8663f216c563 100644 --- a/include/linux/hid-debug.h +++ b/include/linux/hid-debug.h @@ -22,11 +22,12 @@ * */ -#define HID_DEBUG_BUFSIZE 512 - #ifdef CONFIG_DEBUG_FS +#define HID_DEBUG_BUFSIZE 512 + void hid_dump_input(struct hid_device *, struct hid_usage *, __s32); +void hid_dump_report(struct hid_device *, int , u8 *, int); void hid_dump_device(struct hid_device *, struct seq_file *); void hid_dump_field(struct hid_field *, int, struct seq_file *); char *hid_resolv_usage(unsigned, struct seq_file *); @@ -50,6 +51,7 @@ struct hid_debug_list { #else #define hid_dump_input(a,b,c) do { } while (0) +#define hid_dump_report(a,b,c,d) do { } while (0) #define hid_dump_device(a,b) do { } while (0) #define hid_dump_field(a,b,c) do { } while (0) #define hid_resolv_usage(a,b) do { } while (0) From 2353f2bea307390e015493118e425152b8a5a431 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Tue, 16 Apr 2013 15:40:09 -0700 Subject: [PATCH 19/19] HID: protect hid_debug_list Accesses to hid_device->hid_debug_list are not serialized properly, which could result in SMP concurrency issues when HID debugfs events are accessesed by multiple userspace processess. Serialize all the list operations by a mutex. Spotted by Al Viro. Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-debug.c | 6 ++++++ include/linux/hid.h | 1 + 3 files changed, 8 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index f86dd9708ca5..e7765ede339e 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2319,6 +2319,7 @@ struct hid_device *hid_allocate_device(void) init_waitqueue_head(&hdev->debug_wait); INIT_LIST_HEAD(&hdev->debug_list); + mutex_init(&hdev->debug_list_lock); sema_init(&hdev->driver_lock, 1); return hdev; diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 094cbcfe1e1a..7e56cb3855e3 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -580,12 +580,14 @@ void hid_debug_event(struct hid_device *hdev, char *buf) int i; struct hid_debug_list *list; + mutex_lock(&hdev->debug_list_lock); list_for_each_entry(list, &hdev->debug_list, node) { for (i = 0; i < strlen(buf); i++) list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] = buf[i]; list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE; } + mutex_unlock(&hdev->debug_list_lock); wake_up_interruptible(&hdev->debug_wait); } @@ -990,7 +992,9 @@ static int hid_debug_events_open(struct inode *inode, struct file *file) file->private_data = list; mutex_init(&list->read_mutex); + mutex_lock(&list->hdev->debug_list_lock); list_add_tail(&list->node, &list->hdev->debug_list); + mutex_unlock(&list->hdev->debug_list_lock); out: return err; @@ -1085,7 +1089,9 @@ static int hid_debug_events_release(struct inode *inode, struct file *file) { struct hid_debug_list *list = file->private_data; + mutex_lock(&list->hdev->debug_list_lock); list_del(&list->node); + mutex_unlock(&list->hdev->debug_list_lock); kfree(list->hid_debug_buf); kfree(list); diff --git a/include/linux/hid.h b/include/linux/hid.h index e14b465b1146..06579c72d195 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -512,6 +512,7 @@ struct hid_device { /* device report descriptor */ struct dentry *debug_rdesc; struct dentry *debug_events; struct list_head debug_list; + struct mutex debug_list_lock; wait_queue_head_t debug_wait; };