diff options
32 files changed, 1697 insertions, 550 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd b/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd new file mode 100644 index 000000000000..57b92cbdceae --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-lenovo-tpkbd | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/press_to_select | ||
| 2 | Date: July 2011 | ||
| 3 | Contact: linux-input@vger.kernel.org | ||
| 4 | Description: This controls if mouse clicks should be generated if the trackpoint is quickly pressed. How fast this press has to be | ||
| 5 | is being controlled by press_speed. | ||
| 6 | Values are 0 or 1. | ||
| 7 | |||
| 8 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/dragging | ||
| 9 | Date: July 2011 | ||
| 10 | Contact: linux-input@vger.kernel.org | ||
| 11 | Description: If this setting is enabled, it is possible to do dragging by pressing the trackpoint. This requires press_to_select to be enabled. | ||
| 12 | Values are 0 or 1. | ||
| 13 | |||
| 14 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/release_to_select | ||
| 15 | Date: July 2011 | ||
| 16 | Contact: linux-input@vger.kernel.org | ||
| 17 | Description: For details regarding this setting please refer to http://www.pc.ibm.com/ww/healthycomputing/trkpntb.html | ||
| 18 | Values are 0 or 1. | ||
| 19 | |||
| 20 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/select_right | ||
| 21 | Date: July 2011 | ||
| 22 | Contact: linux-input@vger.kernel.org | ||
| 23 | Description: This setting controls if the mouse click events generated by pressing the trackpoint (if press_to_select is enabled) generate | ||
| 24 | a left or right mouse button click. | ||
| 25 | Values are 0 or 1. | ||
| 26 | |||
| 27 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/sensitivity | ||
| 28 | Date: July 2011 | ||
| 29 | Contact: linux-input@vger.kernel.org | ||
| 30 | Description: This file contains the trackpoint sensitivity. | ||
| 31 | Values are decimal integers from 1 (lowest sensitivity) to 255 (highest sensitivity). | ||
| 32 | |||
| 33 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/press_speed | ||
| 34 | Date: July 2011 | ||
| 35 | Contact: linux-input@vger.kernel.org | ||
| 36 | Description: This setting controls how fast the trackpoint needs to be pressed to generate a mouse click if press_to_select is enabled. | ||
| 37 | Values are decimal integers from 1 (slowest) to 255 (fastest). | ||
| 38 | |||
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu b/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu new file mode 100644 index 000000000000..b42922cf6b1f --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/buttons | ||
| 2 | Date: Mai 2012 | ||
| 3 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 4 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 5 | press of a button. A profile is split into general settings and | ||
| 6 | button settings. buttons holds informations about button layout. | ||
| 7 | When written, this file lets one write the respective profile | ||
| 8 | buttons to the mouse. The data has to be 47 bytes long. | ||
| 9 | The mouse will reject invalid data. | ||
| 10 | Which profile to write is determined by the profile number | ||
| 11 | contained in the data. | ||
| 12 | Before reading this file, control has to be written to select | ||
| 13 | which profile to read. | ||
| 14 | Users: http://roccat.sourceforge.net | ||
| 15 | |||
| 16 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/control | ||
| 17 | Date: Mai 2012 | ||
| 18 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 19 | Description: When written, this file lets one select which data from which | ||
| 20 | profile will be read next. The data has to be 3 bytes long. | ||
| 21 | This file is writeonly. | ||
| 22 | Users: http://roccat.sourceforge.net | ||
| 23 | |||
| 24 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/general | ||
| 25 | Date: Mai 2012 | ||
| 26 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 27 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 28 | press of a button. A profile is split into general settings and | ||
| 29 | button settings. profile holds informations like resolution, sensitivity | ||
| 30 | and light effects. | ||
| 31 | When written, this file lets one write the respective profile | ||
| 32 | settings back to the mouse. The data has to be 43 bytes long. | ||
| 33 | The mouse will reject invalid data. | ||
| 34 | Which profile to write is determined by the profile number | ||
| 35 | contained in the data. | ||
| 36 | This file is writeonly. | ||
| 37 | Users: http://roccat.sourceforge.net | ||
| 38 | |||
| 39 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/info | ||
| 40 | Date: Mai 2012 | ||
| 41 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 42 | Description: When read, this file returns general data like firmware version. | ||
| 43 | The data is 8 bytes long. | ||
| 44 | This file is readonly. | ||
| 45 | Users: http://roccat.sourceforge.net | ||
| 46 | |||
| 47 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/macro | ||
| 48 | Date: Mai 2012 | ||
| 49 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 50 | Description: When written, this file lets one store macros with max 500 | ||
| 51 | keystrokes for a specific button for a specific profile. | ||
| 52 | Button and profile numbers are included in written data. | ||
| 53 | The data has to be 2083 bytes long. | ||
| 54 | Before reading this file, control has to be written to select | ||
| 55 | which profile and key to read. | ||
| 56 | Users: http://roccat.sourceforge.net | ||
| 57 | |||
| 58 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/profile | ||
| 59 | Date: Mai 2012 | ||
| 60 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 61 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 62 | press of a button. profile holds number of actual profile. | ||
| 63 | This value is persistent, so its value determines the profile | ||
| 64 | that's active when the mouse is powered on next time. | ||
| 65 | When written, the mouse activates the set profile immediately. | ||
| 66 | The data has to be 3 bytes long. | ||
| 67 | The mouse will reject invalid data. | ||
| 68 | Users: http://roccat.sourceforge.net | ||
| 69 | |||
| 70 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/sensor | ||
| 71 | Date: July 2012 | ||
| 72 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 73 | Description: The mouse has a Avago ADNS-3090 sensor. | ||
| 74 | This file allows reading and writing of the mouse sensors registers. | ||
| 75 | The data has to be 4 bytes long. | ||
| 76 | Users: http://roccat.sourceforge.net | ||
| 77 | |||
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 3fda8c87f02c..00445bc3019c 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
| @@ -193,10 +193,12 @@ config HID_EZKEY | |||
| 193 | Support for Ezkey BTC 8193 keyboard. | 193 | Support for Ezkey BTC 8193 keyboard. |
| 194 | 194 | ||
| 195 | config HID_HOLTEK | 195 | config HID_HOLTEK |
| 196 | tristate "Holtek On Line Grip based game controller support" | 196 | tristate "Holtek HID devices" |
| 197 | depends on USB_HID | 197 | depends on USB_HID |
| 198 | ---help--- | 198 | ---help--- |
| 199 | Say Y here if you have a Holtek On Line Grip based game controller. | 199 | Support for Holtek based devices: |
| 200 | - Holtek On Line Grip based game controller | ||
| 201 | - Trust GXT 18 Gaming Keyboard | ||
| 200 | 202 | ||
| 201 | config HOLTEK_FF | 203 | config HOLTEK_FF |
| 202 | bool "Holtek On Line Grip force feedback support" | 204 | bool "Holtek On Line Grip force feedback support" |
| @@ -261,6 +263,19 @@ config HID_LCPOWER | |||
| 261 | ---help--- | 263 | ---help--- |
| 262 | Support for LC-Power RC1000MCE RF remote control. | 264 | Support for LC-Power RC1000MCE RF remote control. |
| 263 | 265 | ||
| 266 | config HID_LENOVO_TPKBD | ||
| 267 | tristate "Lenovo ThinkPad USB Keyboard with TrackPoint" | ||
| 268 | depends on USB_HID | ||
| 269 | select NEW_LEDS | ||
| 270 | select LEDS_CLASS | ||
| 271 | ---help--- | ||
| 272 | Support for the Lenovo ThinkPad USB Keyboard with TrackPoint. | ||
| 273 | |||
| 274 | Say Y here if you have a Lenovo ThinkPad USB Keyboard with TrackPoint | ||
| 275 | and would like to use device-specific features like changing the | ||
| 276 | sensitivity of the trackpoint, using the microphone mute button or | ||
| 277 | controlling the mute and microphone mute LEDs. | ||
| 278 | |||
| 264 | config HID_LOGITECH | 279 | config HID_LOGITECH |
| 265 | tristate "Logitech devices" if EXPERT | 280 | tristate "Logitech devices" if EXPERT |
| 266 | depends on USB_HID | 281 | depends on USB_HID |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index ca6cc9f0485c..02fa93896951 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
| @@ -48,12 +48,14 @@ obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o | |||
| 48 | obj-$(CONFIG_HID_ELECOM) += hid-elecom.o | 48 | obj-$(CONFIG_HID_ELECOM) += hid-elecom.o |
| 49 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o | 49 | obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o |
| 50 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o | 50 | obj-$(CONFIG_HID_GYRATION) += hid-gyration.o |
| 51 | obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o | ||
| 51 | obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o | 52 | obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o |
| 52 | obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o | 53 | obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o |
| 53 | obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o | 54 | obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o |
| 54 | obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o | 55 | obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o |
| 55 | obj-$(CONFIG_HID_KYE) += hid-kye.o | 56 | obj-$(CONFIG_HID_KYE) += hid-kye.o |
| 56 | obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o | 57 | obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o |
| 58 | obj-$(CONFIG_HID_LENOVO_TPKBD) += hid-lenovo-tpkbd.o | ||
| 57 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o | 59 | obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o |
| 58 | obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o | 60 | obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o |
| 59 | obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o | 61 | obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o |
| @@ -69,7 +71,8 @@ obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o | |||
| 69 | obj-$(CONFIG_HID_PRIMAX) += hid-primax.o | 71 | obj-$(CONFIG_HID_PRIMAX) += hid-primax.o |
| 70 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ | 72 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ |
| 71 | hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ | 73 | hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ |
| 72 | hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o | 74 | hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \ |
| 75 | hid-roccat-savu.o | ||
| 73 | obj-$(CONFIG_HID_SAITEK) += hid-saitek.o | 76 | obj-$(CONFIG_HID_SAITEK) += hid-saitek.o |
| 74 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o | 77 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o |
| 75 | obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o | 78 | obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o |
diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c index b99af346fdff..a2abb8e15727 100644 --- a/drivers/hid/hid-chicony.c +++ b/drivers/hid/hid-chicony.c | |||
| @@ -60,6 +60,7 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 60 | static const struct hid_device_id ch_devices[] = { | 60 | static const struct hid_device_id ch_devices[] = { |
| 61 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, | 61 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, |
| 62 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, | 62 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, |
| 63 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, | ||
| 63 | { } | 64 | { } |
| 64 | }; | 65 | }; |
| 65 | MODULE_DEVICE_TABLE(hid, ch_devices); | 66 | MODULE_DEVICE_TABLE(hid, ch_devices); |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 71f87b1d71de..500844f04f93 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -1379,8 +1379,10 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) | |||
| 1379 | if ((connect_mask & HID_CONNECT_HIDRAW) && !hidraw_connect(hdev)) | 1379 | if ((connect_mask & HID_CONNECT_HIDRAW) && !hidraw_connect(hdev)) |
| 1380 | hdev->claimed |= HID_CLAIMED_HIDRAW; | 1380 | hdev->claimed |= HID_CLAIMED_HIDRAW; |
| 1381 | 1381 | ||
| 1382 | if (!hdev->claimed) { | 1382 | /* Drivers with the ->raw_event callback set are not required to connect |
| 1383 | hid_err(hdev, "claimed by neither input, hiddev nor hidraw\n"); | 1383 | * to any other listener. */ |
| 1384 | if (!hdev->claimed && !hdev->driver->raw_event) { | ||
| 1385 | hid_err(hdev, "device has no listeners, quitting\n"); | ||
| 1384 | return -ENODEV; | 1386 | return -ENODEV; |
| 1385 | } | 1387 | } |
| 1386 | 1388 | ||
| @@ -1527,10 +1529,12 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1527 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, | 1529 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, |
| 1528 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, | 1530 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, |
| 1529 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, | 1531 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, |
| 1532 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, | ||
| 1530 | { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, | 1533 | { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, |
| 1531 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, | 1534 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, |
| 1532 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, | 1535 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, |
| 1533 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, | 1536 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, |
| 1537 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4) }, | ||
| 1534 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, | 1538 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, |
| 1535 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, | 1539 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, |
| 1536 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, | 1540 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, |
| @@ -1545,6 +1549,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1545 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1549 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
| 1546 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, | 1550 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, |
| 1547 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, | 1551 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, |
| 1552 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, | ||
| 1548 | { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, | 1553 | { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, |
| 1549 | { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, | 1554 | { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, |
| 1550 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, | 1555 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, |
| @@ -1553,6 +1558,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1553 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, | 1558 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, |
| 1554 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, | 1559 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, |
| 1555 | { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, | 1560 | { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) }, |
| 1561 | { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, | ||
| 1556 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, | 1562 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, |
| 1557 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, | 1563 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, |
| 1558 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, | 1564 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) }, |
| @@ -1626,6 +1632,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1626 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, | 1632 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, |
| 1627 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, | 1633 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, |
| 1628 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, | 1634 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, |
| 1635 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) }, | ||
| 1629 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, | 1636 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, |
| 1630 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, | 1637 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, |
| 1631 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, | 1638 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, |
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index 2f0be4c66af7..9e43aaca9774 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c | |||
| @@ -129,6 +129,8 @@ static const struct hid_device_id cp_devices[] = { | |||
| 129 | .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, | 129 | .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, |
| 130 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3), | 130 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3), |
| 131 | .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, | 131 | .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, |
| 132 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4), | ||
| 133 | .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, | ||
| 132 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE), | 134 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE), |
| 133 | .driver_data = CP_2WHEEL_MOUSE_HACK }, | 135 | .driver_data = CP_2WHEEL_MOUSE_HACK }, |
| 134 | { } | 136 | { } |
diff --git a/drivers/hid/hid-holtek-kbd.c b/drivers/hid/hid-holtek-kbd.c new file mode 100644 index 000000000000..e0a5d1739fc3 --- /dev/null +++ b/drivers/hid/hid-holtek-kbd.c | |||
| @@ -0,0 +1,183 @@ | |||
| 1 | /* | ||
| 2 | * HID driver for Holtek keyboard | ||
| 3 | * Copyright (c) 2012 Tom Harwood | ||
| 4 | */ | ||
| 5 | |||
| 6 | /* | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the Free | ||
| 9 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/device.h> | ||
| 14 | #include <linux/hid.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/usb.h> | ||
| 17 | |||
| 18 | #include "hid-ids.h" | ||
| 19 | #include "usbhid/usbhid.h" | ||
| 20 | |||
| 21 | /* Holtek based keyboards (USB ID 04d9:a055) have the following issues: | ||
| 22 | * - The report descriptor specifies an excessively large number of consumer | ||
| 23 | * usages (2^15), which is more than HID_MAX_USAGES. This prevents proper | ||
| 24 | * parsing of the report descriptor. | ||
| 25 | * - The report descriptor reports on caps/scroll/num lock key presses, but | ||
| 26 | * doesn't have an LED output usage block. | ||
| 27 | * | ||
| 28 | * The replacement descriptor below fixes the number of consumer usages, | ||
| 29 | * and provides an LED output usage block. LED output events are redirected | ||
| 30 | * to the boot interface. | ||
| 31 | */ | ||
| 32 | |||
| 33 | static __u8 holtek_kbd_rdesc_fixed[] = { | ||
| 34 | /* Original report descriptor, with reduced number of consumer usages */ | ||
| 35 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 36 | 0x09, 0x80, /* Usage (Sys Control), */ | ||
| 37 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 38 | 0x85, 0x01, /* Report ID (1), */ | ||
| 39 | 0x19, 0x81, /* Usage Minimum (Sys Power Down), */ | ||
| 40 | 0x29, 0x83, /* Usage Maximum (Sys Wake Up), */ | ||
| 41 | 0x15, 0x00, /* Logical Minimum (0), */ | ||
| 42 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 43 | 0x95, 0x03, /* Report Count (3), */ | ||
| 44 | 0x75, 0x01, /* Report Size (1), */ | ||
| 45 | 0x81, 0x02, /* Input (Variable), */ | ||
| 46 | 0x95, 0x01, /* Report Count (1), */ | ||
| 47 | 0x75, 0x05, /* Report Size (5), */ | ||
| 48 | 0x81, 0x01, /* Input (Constant), */ | ||
| 49 | 0xC0, /* End Collection, */ | ||
| 50 | 0x05, 0x0C, /* Usage Page (Consumer), */ | ||
| 51 | 0x09, 0x01, /* Usage (Consumer Control), */ | ||
| 52 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 53 | 0x85, 0x02, /* Report ID (2), */ | ||
| 54 | 0x19, 0x00, /* Usage Minimum (00h), */ | ||
| 55 | 0x2A, 0xFF, 0x2F, /* Usage Maximum (0x2FFF), previously 0x7FFF */ | ||
| 56 | 0x15, 0x00, /* Logical Minimum (0), */ | ||
| 57 | 0x26, 0xFF, 0x2F, /* Logical Maximum (0x2FFF),previously 0x7FFF*/ | ||
| 58 | 0x95, 0x01, /* Report Count (1), */ | ||
| 59 | 0x75, 0x10, /* Report Size (16), */ | ||
| 60 | 0x81, 0x00, /* Input, */ | ||
| 61 | 0xC0, /* End Collection, */ | ||
| 62 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 63 | 0x09, 0x06, /* Usage (Keyboard), */ | ||
| 64 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 65 | 0x85, 0x03, /* Report ID (3), */ | ||
| 66 | 0x95, 0x38, /* Report Count (56), */ | ||
| 67 | 0x75, 0x01, /* Report Size (1), */ | ||
| 68 | 0x15, 0x00, /* Logical Minimum (0), */ | ||
| 69 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 70 | 0x05, 0x07, /* Usage Page (Keyboard), */ | ||
| 71 | 0x19, 0xE0, /* Usage Minimum (KB Leftcontrol), */ | ||
| 72 | 0x29, 0xE7, /* Usage Maximum (KB Right GUI), */ | ||
| 73 | 0x19, 0x00, /* Usage Minimum (None), */ | ||
| 74 | 0x29, 0x2F, /* Usage Maximum (KB Lboxbracket And Lbrace),*/ | ||
| 75 | 0x81, 0x02, /* Input (Variable), */ | ||
| 76 | 0xC0, /* End Collection, */ | ||
| 77 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 78 | 0x09, 0x06, /* Usage (Keyboard), */ | ||
| 79 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 80 | 0x85, 0x04, /* Report ID (4), */ | ||
| 81 | 0x95, 0x38, /* Report Count (56), */ | ||
| 82 | 0x75, 0x01, /* Report Size (1), */ | ||
| 83 | 0x15, 0x00, /* Logical Minimum (0), */ | ||
| 84 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 85 | 0x05, 0x07, /* Usage Page (Keyboard), */ | ||
| 86 | 0x19, 0x30, /* Usage Minimum (KB Rboxbracket And Rbrace),*/ | ||
| 87 | 0x29, 0x67, /* Usage Maximum (KP Equals), */ | ||
| 88 | 0x81, 0x02, /* Input (Variable), */ | ||
| 89 | 0xC0, /* End Collection */ | ||
| 90 | |||
| 91 | /* LED usage for the boot protocol interface */ | ||
| 92 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 93 | 0x09, 0x06, /* Usage (Keyboard), */ | ||
| 94 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 95 | 0x05, 0x08, /* Usage Page (LED), */ | ||
| 96 | 0x19, 0x01, /* Usage Minimum (01h), */ | ||
| 97 | 0x29, 0x03, /* Usage Maximum (03h), */ | ||
| 98 | 0x15, 0x00, /* Logical Minimum (0), */ | ||
| 99 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 100 | 0x75, 0x01, /* Report Size (1), */ | ||
| 101 | 0x95, 0x03, /* Report Count (3), */ | ||
| 102 | 0x91, 0x02, /* Output (Variable), */ | ||
| 103 | 0x95, 0x05, /* Report Count (5), */ | ||
| 104 | 0x91, 0x01, /* Output (Constant), */ | ||
| 105 | 0xC0, /* End Collection */ | ||
| 106 | }; | ||
| 107 | |||
| 108 | static __u8 *holtek_kbd_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
| 109 | unsigned int *rsize) | ||
| 110 | { | ||
| 111 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
| 112 | |||
| 113 | if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { | ||
| 114 | rdesc = holtek_kbd_rdesc_fixed; | ||
| 115 | *rsize = sizeof(holtek_kbd_rdesc_fixed); | ||
| 116 | } | ||
| 117 | return rdesc; | ||
| 118 | } | ||
| 119 | |||
| 120 | static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type, | ||
| 121 | unsigned int code, | ||
| 122 | int value) | ||
| 123 | { | ||
| 124 | struct hid_device *hid = input_get_drvdata(dev); | ||
| 125 | struct usb_device *usb_dev = hid_to_usb_dev(hid); | ||
| 126 | |||
| 127 | /* Locate the boot interface, to receive the LED change events */ | ||
| 128 | struct usb_interface *boot_interface = usb_ifnum_to_if(usb_dev, 0); | ||
| 129 | |||
| 130 | struct hid_device *boot_hid = usb_get_intfdata(boot_interface); | ||
| 131 | struct hid_input *boot_hid_input = list_first_entry(&boot_hid->inputs, | ||
| 132 | struct hid_input, list); | ||
| 133 | |||
| 134 | return boot_hid_input->input->event(boot_hid_input->input, type, code, | ||
| 135 | value); | ||
| 136 | } | ||
| 137 | |||
| 138 | static int holtek_kbd_probe(struct hid_device *hdev, | ||
| 139 | const struct hid_device_id *id) | ||
| 140 | { | ||
| 141 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
| 142 | int ret = hid_parse(hdev); | ||
| 143 | |||
| 144 | if (!ret) | ||
| 145 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
| 146 | |||
| 147 | if (!ret && intf->cur_altsetting->desc.bInterfaceNumber == 1) { | ||
| 148 | struct hid_input *hidinput; | ||
| 149 | list_for_each_entry(hidinput, &hdev->inputs, list) { | ||
| 150 | hidinput->input->event = holtek_kbd_input_event; | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | return ret; | ||
| 155 | } | ||
| 156 | |||
| 157 | static const struct hid_device_id holtek_kbd_devices[] = { | ||
| 158 | { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, | ||
| 159 | USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, | ||
| 160 | { } | ||
| 161 | }; | ||
| 162 | MODULE_DEVICE_TABLE(hid, holtek_kbd_devices); | ||
| 163 | |||
| 164 | static struct hid_driver holtek_kbd_driver = { | ||
| 165 | .name = "holtek_kbd", | ||
| 166 | .id_table = holtek_kbd_devices, | ||
| 167 | .report_fixup = holtek_kbd_report_fixup, | ||
| 168 | .probe = holtek_kbd_probe | ||
| 169 | }; | ||
| 170 | |||
| 171 | static int __init holtek_kbd_init(void) | ||
| 172 | { | ||
| 173 | return hid_register_driver(&holtek_kbd_driver); | ||
| 174 | } | ||
| 175 | |||
| 176 | static void __exit holtek_kbd_exit(void) | ||
| 177 | { | ||
| 178 | hid_unregister_driver(&holtek_kbd_driver); | ||
| 179 | } | ||
| 180 | |||
| 181 | module_exit(holtek_kbd_exit); | ||
| 182 | module_init(holtek_kbd_init); | ||
| 183 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 32039235cfee..41c34f21bd00 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -208,6 +208,7 @@ | |||
| 208 | #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d | 208 | #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d |
| 209 | #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 | 209 | #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 |
| 210 | #define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123 | 210 | #define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123 |
| 211 | #define USB_DEVICE_ID_CHICONY_AK1D 0x1125 | ||
| 211 | 212 | ||
| 212 | #define USB_VENDOR_ID_CHUNGHWAT 0x2247 | 213 | #define USB_VENDOR_ID_CHUNGHWAT 0x2247 |
| 213 | #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 | 214 | #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 |
| @@ -237,6 +238,7 @@ | |||
| 237 | #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 | 238 | #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 |
| 238 | #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 | 239 | #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 |
| 239 | #define USB_DEVICE_ID_CYPRESS_BARCODE_3 0xbca1 | 240 | #define USB_DEVICE_ID_CYPRESS_BARCODE_3 0xbca1 |
| 241 | #define USB_DEVICE_ID_CYPRESS_BARCODE_4 0xed81 | ||
| 240 | #define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 | 242 | #define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 |
| 241 | 243 | ||
| 242 | #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 | 244 | #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 |
| @@ -410,6 +412,9 @@ | |||
| 410 | #define USB_VENDOR_ID_HOLTEK 0x1241 | 412 | #define USB_VENDOR_ID_HOLTEK 0x1241 |
| 411 | #define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015 | 413 | #define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015 |
| 412 | 414 | ||
| 415 | #define USB_VENDOR_ID_HOLTEK_ALT 0x04d9 | ||
| 416 | #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD 0xa055 | ||
| 417 | |||
| 413 | #define USB_VENDOR_ID_IMATION 0x0718 | 418 | #define USB_VENDOR_ID_IMATION 0x0718 |
| 414 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 | 419 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 |
| 415 | 420 | ||
| @@ -479,6 +484,9 @@ | |||
| 479 | #define USB_DEVICE_ID_LD_HYBRID 0x2090 | 484 | #define USB_DEVICE_ID_LD_HYBRID 0x2090 |
| 480 | #define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0 | 485 | #define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0 |
| 481 | 486 | ||
| 487 | #define USB_VENDOR_ID_LENOVO 0x17ef | ||
| 488 | #define USB_DEVICE_ID_LENOVO_TPKBD 0x6009 | ||
| 489 | |||
| 482 | #define USB_VENDOR_ID_LG 0x1fd2 | 490 | #define USB_VENDOR_ID_LG 0x1fd2 |
| 483 | #define USB_DEVICE_ID_LG_MULTITOUCH 0x0064 | 491 | #define USB_DEVICE_ID_LG_MULTITOUCH 0x0064 |
| 484 | 492 | ||
| @@ -573,6 +581,9 @@ | |||
| 573 | #define USB_VENDOR_ID_NINTENDO 0x057e | 581 | #define USB_VENDOR_ID_NINTENDO 0x057e |
| 574 | #define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306 | 582 | #define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306 |
| 575 | 583 | ||
| 584 | #define USB_VENDOR_ID_NOVATEK 0x0603 | ||
| 585 | #define USB_DEVICE_ID_NOVATEK_PCT 0x0600 | ||
| 586 | |||
| 576 | #define USB_VENDOR_ID_NTRIG 0x1b96 | 587 | #define USB_VENDOR_ID_NTRIG 0x1b96 |
| 577 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 | 588 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 |
| 578 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003 | 589 | #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003 |
| @@ -650,6 +661,7 @@ | |||
| 650 | #define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 | 661 | #define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 |
| 651 | #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24 | 662 | #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24 |
| 652 | #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6 | 663 | #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6 |
| 664 | #define USB_DEVICE_ID_ROCCAT_SAVU 0x2d5a | ||
| 653 | 665 | ||
| 654 | #define USB_VENDOR_ID_SAITEK 0x06a3 | 666 | #define USB_VENDOR_ID_SAITEK 0x06a3 |
| 655 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 | 667 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 5301006f6c15..811bfad64609 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
| @@ -837,6 +837,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 837 | } | 837 | } |
| 838 | break; | 838 | break; |
| 839 | 839 | ||
| 840 | case HID_UP_HPVENDOR2: | ||
| 841 | set_bit(EV_REP, input->evbit); | ||
| 842 | switch (usage->hid & HID_USAGE) { | ||
| 843 | case 0x003: map_key_clear(KEY_BRIGHTNESSDOWN); break; | ||
| 844 | case 0x004: map_key_clear(KEY_BRIGHTNESSUP); break; | ||
| 845 | default: goto ignore; | ||
| 846 | } | ||
| 847 | break; | ||
| 848 | |||
| 840 | case HID_UP_MSVENDOR: | 849 | case HID_UP_MSVENDOR: |
| 841 | goto ignore; | 850 | goto ignore; |
| 842 | 851 | ||
diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c new file mode 100644 index 000000000000..77d2df04c97b --- /dev/null +++ b/drivers/hid/hid-lenovo-tpkbd.c | |||
| @@ -0,0 +1,564 @@ | |||
| 1 | /* | ||
| 2 | * HID driver for Lenovo ThinkPad USB Keyboard with TrackPoint | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012 Bernhard Seibold | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 11 | * any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/sysfs.h> | ||
| 16 | #include <linux/device.h> | ||
| 17 | #include <linux/usb.h> | ||
| 18 | #include <linux/hid.h> | ||
| 19 | #include <linux/input.h> | ||
| 20 | #include <linux/leds.h> | ||
| 21 | #include "usbhid/usbhid.h" | ||
| 22 | |||
| 23 | #include "hid-ids.h" | ||
| 24 | |||
| 25 | /* This is only used for the trackpoint part of the driver, hence _tp */ | ||
| 26 | struct tpkbd_data_pointer { | ||
| 27 | int led_state; | ||
| 28 | struct led_classdev led_mute; | ||
| 29 | struct led_classdev led_micmute; | ||
| 30 | int press_to_select; | ||
| 31 | int dragging; | ||
| 32 | int release_to_select; | ||
| 33 | int select_right; | ||
| 34 | int sensitivity; | ||
| 35 | int press_speed; | ||
| 36 | }; | ||
| 37 | |||
| 38 | #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) | ||
| 39 | |||
| 40 | static int tpkbd_input_mapping(struct hid_device *hdev, | ||
| 41 | struct hid_input *hi, struct hid_field *field, | ||
| 42 | struct hid_usage *usage, unsigned long **bit, int *max) | ||
| 43 | { | ||
| 44 | struct usbhid_device *uhdev; | ||
| 45 | |||
| 46 | uhdev = (struct usbhid_device *) hdev->driver_data; | ||
| 47 | if (uhdev->ifnum == 1 && usage->hid == (HID_UP_BUTTON | 0x0010)) { | ||
| 48 | map_key_clear(KEY_MICMUTE); | ||
| 49 | return 1; | ||
| 50 | } | ||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | |||
| 54 | #undef map_key_clear | ||
| 55 | |||
| 56 | static int tpkbd_features_set(struct hid_device *hdev) | ||
| 57 | { | ||
| 58 | struct hid_report *report; | ||
| 59 | struct tpkbd_data_pointer *data_pointer; | ||
| 60 | |||
| 61 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 62 | report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4]; | ||
| 63 | |||
| 64 | report->field[0]->value[0] = data_pointer->press_to_select ? 0x01 : 0x02; | ||
| 65 | report->field[0]->value[0] |= data_pointer->dragging ? 0x04 : 0x08; | ||
| 66 | report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20; | ||
| 67 | report->field[0]->value[0] |= data_pointer->select_right ? 0x80 : 0x40; | ||
| 68 | report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver | ||
| 69 | report->field[2]->value[0] = data_pointer->sensitivity; | ||
| 70 | report->field[3]->value[0] = data_pointer->press_speed; | ||
| 71 | |||
| 72 | usbhid_submit_report(hdev, report, USB_DIR_OUT); | ||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | static ssize_t pointer_press_to_select_show(struct device *dev, | ||
| 77 | struct device_attribute *attr, | ||
| 78 | char *buf) | ||
| 79 | { | ||
| 80 | struct hid_device *hdev; | ||
| 81 | struct tpkbd_data_pointer *data_pointer; | ||
| 82 | |||
| 83 | hdev = container_of(dev, struct hid_device, dev); | ||
| 84 | if (hdev == NULL) | ||
| 85 | return -ENODEV; | ||
| 86 | |||
| 87 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 88 | |||
| 89 | return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select); | ||
| 90 | } | ||
| 91 | |||
| 92 | static ssize_t pointer_press_to_select_store(struct device *dev, | ||
| 93 | struct device_attribute *attr, | ||
| 94 | const char *buf, | ||
| 95 | size_t count) | ||
| 96 | { | ||
| 97 | struct hid_device *hdev; | ||
| 98 | struct tpkbd_data_pointer *data_pointer; | ||
| 99 | int value; | ||
| 100 | |||
| 101 | hdev = container_of(dev, struct hid_device, dev); | ||
| 102 | if (hdev == NULL) | ||
| 103 | return -ENODEV; | ||
| 104 | |||
| 105 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 106 | |||
| 107 | if (kstrtoint(buf, 10, &value)) | ||
| 108 | return -EINVAL; | ||
| 109 | if (value < 0 || value > 1) | ||
| 110 | return -EINVAL; | ||
| 111 | |||
| 112 | data_pointer->press_to_select = value; | ||
| 113 | tpkbd_features_set(hdev); | ||
| 114 | |||
| 115 | return count; | ||
| 116 | } | ||
| 117 | |||
| 118 | static ssize_t pointer_dragging_show(struct device *dev, | ||
| 119 | struct device_attribute *attr, | ||
| 120 | char *buf) | ||
| 121 | { | ||
| 122 | struct hid_device *hdev; | ||
| 123 | struct tpkbd_data_pointer *data_pointer; | ||
| 124 | |||
| 125 | hdev = container_of(dev, struct hid_device, dev); | ||
| 126 | if (hdev == NULL) | ||
| 127 | return -ENODEV; | ||
| 128 | |||
| 129 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 130 | |||
| 131 | return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging); | ||
| 132 | } | ||
| 133 | |||
| 134 | static ssize_t pointer_dragging_store(struct device *dev, | ||
| 135 | struct device_attribute *attr, | ||
| 136 | const char *buf, | ||
| 137 | size_t count) | ||
| 138 | { | ||
| 139 | struct hid_device *hdev; | ||
| 140 | struct tpkbd_data_pointer *data_pointer; | ||
| 141 | int value; | ||
| 142 | |||
| 143 | hdev = container_of(dev, struct hid_device, dev); | ||
| 144 | if (hdev == NULL) | ||
| 145 | return -ENODEV; | ||
| 146 | |||
| 147 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 148 | |||
| 149 | if (kstrtoint(buf, 10, &value)) | ||
| 150 | return -EINVAL; | ||
| 151 | if (value < 0 || value > 1) | ||
| 152 | return -EINVAL; | ||
| 153 | |||
| 154 | data_pointer->dragging = value; | ||
| 155 | tpkbd_features_set(hdev); | ||
| 156 | |||
| 157 | return count; | ||
| 158 | } | ||
| 159 | |||
| 160 | static ssize_t pointer_release_to_select_show(struct device *dev, | ||
| 161 | struct device_attribute *attr, | ||
| 162 | char *buf) | ||
| 163 | { | ||
| 164 | struct hid_device *hdev; | ||
| 165 | struct tpkbd_data_pointer *data_pointer; | ||
| 166 | |||
| 167 | hdev = container_of(dev, struct hid_device, dev); | ||
| 168 | if (hdev == NULL) | ||
| 169 | return -ENODEV; | ||
| 170 | |||
| 171 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 172 | |||
| 173 | return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select); | ||
| 174 | } | ||
| 175 | |||
| 176 | static ssize_t pointer_release_to_select_store(struct device *dev, | ||
| 177 | struct device_attribute *attr, | ||
| 178 | const char *buf, | ||
| 179 | size_t count) | ||
| 180 | { | ||
| 181 | struct hid_device *hdev; | ||
| 182 | struct tpkbd_data_pointer *data_pointer; | ||
| 183 | int value; | ||
| 184 | |||
| 185 | hdev = container_of(dev, struct hid_device, dev); | ||
| 186 | if (hdev == NULL) | ||
| 187 | return -ENODEV; | ||
| 188 | |||
| 189 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 190 | |||
| 191 | if (kstrtoint(buf, 10, &value)) | ||
| 192 | return -EINVAL; | ||
| 193 | if (value < 0 || value > 1) | ||
| 194 | return -EINVAL; | ||
| 195 | |||
| 196 | data_pointer->release_to_select = value; | ||
| 197 | tpkbd_features_set(hdev); | ||
| 198 | |||
| 199 | return count; | ||
| 200 | } | ||
| 201 | |||
| 202 | static ssize_t pointer_select_right_show(struct device *dev, | ||
| 203 | struct device_attribute *attr, | ||
| 204 | char *buf) | ||
| 205 | { | ||
| 206 | struct hid_device *hdev; | ||
| 207 | struct tpkbd_data_pointer *data_pointer; | ||
| 208 | |||
| 209 | hdev = container_of(dev, struct hid_device, dev); | ||
| 210 | if (hdev == NULL) | ||
| 211 | return -ENODEV; | ||
| 212 | |||
| 213 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 214 | |||
| 215 | return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right); | ||
| 216 | } | ||
| 217 | |||
| 218 | static ssize_t pointer_select_right_store(struct device *dev, | ||
| 219 | struct device_attribute *attr, | ||
| 220 | const char *buf, | ||
| 221 | size_t count) | ||
| 222 | { | ||
| 223 | struct hid_device *hdev; | ||
| 224 | struct tpkbd_data_pointer *data_pointer; | ||
| 225 | int value; | ||
| 226 | |||
| 227 | hdev = container_of(dev, struct hid_device, dev); | ||
| 228 | if (hdev == NULL) | ||
| 229 | return -ENODEV; | ||
| 230 | |||
| 231 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 232 | |||
| 233 | if (kstrtoint(buf, 10, &value)) | ||
| 234 | return -EINVAL; | ||
| 235 | if (value < 0 || value > 1) | ||
| 236 | return -EINVAL; | ||
| 237 | |||
| 238 | data_pointer->select_right = value; | ||
| 239 | tpkbd_features_set(hdev); | ||
| 240 | |||
| 241 | return count; | ||
| 242 | } | ||
| 243 | |||
| 244 | static ssize_t pointer_sensitivity_show(struct device *dev, | ||
| 245 | struct device_attribute *attr, | ||
| 246 | char *buf) | ||
| 247 | { | ||
| 248 | struct hid_device *hdev; | ||
| 249 | struct tpkbd_data_pointer *data_pointer; | ||
| 250 | |||
| 251 | hdev = container_of(dev, struct hid_device, dev); | ||
| 252 | if (hdev == NULL) | ||
| 253 | return -ENODEV; | ||
| 254 | |||
| 255 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 256 | |||
| 257 | return snprintf(buf, PAGE_SIZE, "%u\n", | ||
| 258 | data_pointer->sensitivity); | ||
| 259 | } | ||
| 260 | |||
| 261 | static ssize_t pointer_sensitivity_store(struct device *dev, | ||
| 262 | struct device_attribute *attr, | ||
| 263 | const char *buf, | ||
| 264 | size_t count) | ||
| 265 | { | ||
| 266 | struct hid_device *hdev; | ||
| 267 | struct tpkbd_data_pointer *data_pointer; | ||
| 268 | int value; | ||
| 269 | |||
| 270 | hdev = container_of(dev, struct hid_device, dev); | ||
| 271 | if (hdev == NULL) | ||
| 272 | return -ENODEV; | ||
| 273 | |||
| 274 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 275 | |||
| 276 | if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) | ||
| 277 | return -EINVAL; | ||
| 278 | |||
| 279 | data_pointer->sensitivity = value; | ||
| 280 | tpkbd_features_set(hdev); | ||
| 281 | |||
| 282 | return count; | ||
| 283 | } | ||
| 284 | |||
| 285 | static ssize_t pointer_press_speed_show(struct device *dev, | ||
| 286 | struct device_attribute *attr, | ||
| 287 | char *buf) | ||
| 288 | { | ||
| 289 | struct hid_device *hdev; | ||
| 290 | struct tpkbd_data_pointer *data_pointer; | ||
| 291 | |||
| 292 | hdev = container_of(dev, struct hid_device, dev); | ||
| 293 | if (hdev == NULL) | ||
| 294 | return -ENODEV; | ||
| 295 | |||
| 296 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 297 | |||
| 298 | return snprintf(buf, PAGE_SIZE, "%u\n", | ||
| 299 | data_pointer->press_speed); | ||
| 300 | } | ||
| 301 | |||
| 302 | static ssize_t pointer_press_speed_store(struct device *dev, | ||
| 303 | struct device_attribute *attr, | ||
| 304 | const char *buf, | ||
| 305 | size_t count) | ||
| 306 | { | ||
| 307 | struct hid_device *hdev; | ||
| 308 | struct tpkbd_data_pointer *data_pointer; | ||
| 309 | int value; | ||
| 310 | |||
| 311 | hdev = container_of(dev, struct hid_device, dev); | ||
| 312 | if (hdev == NULL) | ||
| 313 | return -ENODEV; | ||
| 314 | |||
| 315 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 316 | |||
| 317 | if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) | ||
| 318 | return -EINVAL; | ||
| 319 | |||
| 320 | data_pointer->press_speed = value; | ||
| 321 | tpkbd_features_set(hdev); | ||
| 322 | |||
| 323 | return count; | ||
| 324 | } | ||
| 325 | |||
| 326 | static struct device_attribute dev_attr_pointer_press_to_select = | ||
| 327 | __ATTR(press_to_select, S_IWUSR | S_IRUGO, | ||
| 328 | pointer_press_to_select_show, | ||
| 329 | pointer_press_to_select_store); | ||
| 330 | |||
| 331 | static struct device_attribute dev_attr_pointer_dragging = | ||
| 332 | __ATTR(dragging, S_IWUSR | S_IRUGO, | ||
| 333 | pointer_dragging_show, | ||
| 334 | pointer_dragging_store); | ||
| 335 | |||
| 336 | static struct device_attribute dev_attr_pointer_release_to_select = | ||
| 337 | __ATTR(release_to_select, S_IWUSR | S_IRUGO, | ||
| 338 | pointer_release_to_select_show, | ||
| 339 | pointer_release_to_select_store); | ||
| 340 | |||
| 341 | static struct device_attribute dev_attr_pointer_select_right = | ||
| 342 | __ATTR(select_right, S_IWUSR | S_IRUGO, | ||
| 343 | pointer_select_right_show, | ||
| 344 | pointer_select_right_store); | ||
| 345 | |||
| 346 | static struct device_attribute dev_attr_pointer_sensitivity = | ||
| 347 | __ATTR(sensitivity, S_IWUSR | S_IRUGO, | ||
| 348 | pointer_sensitivity_show, | ||
| 349 | pointer_sensitivity_store); | ||
| 350 | |||
| 351 | static struct device_attribute dev_attr_pointer_press_speed = | ||
| 352 | __ATTR(press_speed, S_IWUSR | S_IRUGO, | ||
| 353 | pointer_press_speed_show, | ||
| 354 | pointer_press_speed_store); | ||
| 355 | |||
| 356 | static struct attribute *tpkbd_attributes_pointer[] = { | ||
| 357 | &dev_attr_pointer_press_to_select.attr, | ||
| 358 | &dev_attr_pointer_dragging.attr, | ||
| 359 | &dev_attr_pointer_release_to_select.attr, | ||
| 360 | &dev_attr_pointer_select_right.attr, | ||
| 361 | &dev_attr_pointer_sensitivity.attr, | ||
| 362 | &dev_attr_pointer_press_speed.attr, | ||
| 363 | NULL | ||
| 364 | }; | ||
| 365 | |||
| 366 | static const struct attribute_group tpkbd_attr_group_pointer = { | ||
| 367 | .attrs = tpkbd_attributes_pointer, | ||
| 368 | }; | ||
| 369 | |||
| 370 | static enum led_brightness tpkbd_led_brightness_get( | ||
| 371 | struct led_classdev *led_cdev) | ||
| 372 | { | ||
| 373 | struct device *dev; | ||
| 374 | struct hid_device *hdev; | ||
| 375 | struct tpkbd_data_pointer *data_pointer; | ||
| 376 | int led_nr = 0; | ||
| 377 | |||
| 378 | dev = led_cdev->dev->parent; | ||
| 379 | hdev = container_of(dev, struct hid_device, dev); | ||
| 380 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 381 | |||
| 382 | if (led_cdev == &data_pointer->led_micmute) | ||
| 383 | led_nr = 1; | ||
| 384 | |||
| 385 | return data_pointer->led_state & (1 << led_nr) | ||
| 386 | ? LED_FULL | ||
| 387 | : LED_OFF; | ||
| 388 | } | ||
| 389 | |||
| 390 | static void tpkbd_led_brightness_set(struct led_classdev *led_cdev, | ||
| 391 | enum led_brightness value) | ||
| 392 | { | ||
| 393 | struct device *dev; | ||
| 394 | struct hid_device *hdev; | ||
| 395 | struct hid_report *report; | ||
| 396 | struct tpkbd_data_pointer *data_pointer; | ||
| 397 | int led_nr = 0; | ||
| 398 | |||
| 399 | dev = led_cdev->dev->parent; | ||
| 400 | hdev = container_of(dev, struct hid_device, dev); | ||
| 401 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 402 | |||
| 403 | if (led_cdev == &data_pointer->led_micmute) | ||
| 404 | led_nr = 1; | ||
| 405 | |||
| 406 | if (value == LED_OFF) | ||
| 407 | data_pointer->led_state &= ~(1 << led_nr); | ||
| 408 | else | ||
| 409 | data_pointer->led_state |= 1 << led_nr; | ||
| 410 | |||
| 411 | report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3]; | ||
| 412 | report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1; | ||
| 413 | report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1; | ||
| 414 | usbhid_submit_report(hdev, report, USB_DIR_OUT); | ||
| 415 | } | ||
| 416 | |||
| 417 | static int tpkbd_probe_tp(struct hid_device *hdev) | ||
| 418 | { | ||
| 419 | struct device *dev = &hdev->dev; | ||
| 420 | struct tpkbd_data_pointer *data_pointer; | ||
| 421 | size_t name_sz = strlen(dev_name(dev)) + 16; | ||
| 422 | char *name_mute, *name_micmute; | ||
| 423 | int ret; | ||
| 424 | |||
| 425 | if (sysfs_create_group(&hdev->dev.kobj, | ||
| 426 | &tpkbd_attr_group_pointer)) { | ||
| 427 | hid_warn(hdev, "Could not create sysfs group\n"); | ||
| 428 | } | ||
| 429 | |||
| 430 | data_pointer = kzalloc(sizeof(struct tpkbd_data_pointer), GFP_KERNEL); | ||
| 431 | if (data_pointer == NULL) { | ||
| 432 | hid_err(hdev, "Could not allocate memory for driver data\n"); | ||
| 433 | return -ENOMEM; | ||
| 434 | } | ||
| 435 | |||
| 436 | // set same default values as windows driver | ||
| 437 | data_pointer->sensitivity = 0xa0; | ||
| 438 | data_pointer->press_speed = 0x38; | ||
| 439 | |||
| 440 | name_mute = kzalloc(name_sz, GFP_KERNEL); | ||
| 441 | if (name_mute == NULL) { | ||
| 442 | hid_err(hdev, "Could not allocate memory for led data\n"); | ||
| 443 | ret = -ENOMEM; | ||
| 444 | goto err; | ||
| 445 | } | ||
| 446 | snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev)); | ||
| 447 | |||
| 448 | name_micmute = kzalloc(name_sz, GFP_KERNEL); | ||
| 449 | if (name_micmute == NULL) { | ||
| 450 | hid_err(hdev, "Could not allocate memory for led data\n"); | ||
| 451 | ret = -ENOMEM; | ||
| 452 | goto err2; | ||
| 453 | } | ||
| 454 | snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev)); | ||
| 455 | |||
| 456 | hid_set_drvdata(hdev, data_pointer); | ||
| 457 | |||
| 458 | data_pointer->led_mute.name = name_mute; | ||
| 459 | data_pointer->led_mute.brightness_get = tpkbd_led_brightness_get; | ||
| 460 | data_pointer->led_mute.brightness_set = tpkbd_led_brightness_set; | ||
| 461 | data_pointer->led_mute.dev = dev; | ||
| 462 | led_classdev_register(dev, &data_pointer->led_mute); | ||
| 463 | |||
| 464 | data_pointer->led_micmute.name = name_micmute; | ||
| 465 | data_pointer->led_micmute.brightness_get = tpkbd_led_brightness_get; | ||
| 466 | data_pointer->led_micmute.brightness_set = tpkbd_led_brightness_set; | ||
| 467 | data_pointer->led_micmute.dev = dev; | ||
| 468 | led_classdev_register(dev, &data_pointer->led_micmute); | ||
| 469 | |||
| 470 | tpkbd_features_set(hdev); | ||
| 471 | |||
| 472 | return 0; | ||
| 473 | |||
| 474 | err2: | ||
| 475 | kfree(name_mute); | ||
| 476 | err: | ||
| 477 | kfree(data_pointer); | ||
| 478 | return ret; | ||
| 479 | } | ||
| 480 | |||
| 481 | static int tpkbd_probe(struct hid_device *hdev, | ||
| 482 | const struct hid_device_id *id) | ||
| 483 | { | ||
| 484 | int ret; | ||
| 485 | struct usbhid_device *uhdev; | ||
| 486 | |||
| 487 | ret = hid_parse(hdev); | ||
| 488 | if (ret) { | ||
| 489 | hid_err(hdev, "hid_parse failed\n"); | ||
| 490 | goto err_free; | ||
| 491 | } | ||
| 492 | |||
| 493 | ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
| 494 | if (ret) { | ||
| 495 | hid_err(hdev, "hid_hw_start failed\n"); | ||
| 496 | goto err_free; | ||
| 497 | } | ||
| 498 | |||
| 499 | uhdev = (struct usbhid_device *) hdev->driver_data; | ||
| 500 | |||
| 501 | if (uhdev->ifnum == 1) | ||
| 502 | return tpkbd_probe_tp(hdev); | ||
| 503 | |||
| 504 | return 0; | ||
| 505 | err_free: | ||
| 506 | return ret; | ||
| 507 | } | ||
| 508 | |||
| 509 | static void tpkbd_remove_tp(struct hid_device *hdev) | ||
| 510 | { | ||
| 511 | struct tpkbd_data_pointer *data_pointer; | ||
| 512 | |||
| 513 | sysfs_remove_group(&hdev->dev.kobj, | ||
| 514 | &tpkbd_attr_group_pointer); | ||
| 515 | |||
| 516 | data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev); | ||
| 517 | |||
| 518 | led_classdev_unregister(&data_pointer->led_micmute); | ||
| 519 | led_classdev_unregister(&data_pointer->led_mute); | ||
| 520 | |||
| 521 | hid_set_drvdata(hdev, NULL); | ||
| 522 | kfree(data_pointer); | ||
| 523 | } | ||
| 524 | |||
| 525 | static void tpkbd_remove(struct hid_device *hdev) | ||
| 526 | { | ||
| 527 | struct usbhid_device *uhdev; | ||
| 528 | |||
| 529 | uhdev = (struct usbhid_device *) hdev->driver_data; | ||
| 530 | if (uhdev->ifnum == 1) | ||
| 531 | tpkbd_remove_tp(hdev); | ||
| 532 | |||
| 533 | hid_hw_stop(hdev); | ||
| 534 | } | ||
| 535 | |||
| 536 | static const struct hid_device_id tpkbd_devices[] = { | ||
| 537 | { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, | ||
| 538 | { } | ||
| 539 | }; | ||
| 540 | |||
| 541 | MODULE_DEVICE_TABLE(hid, tpkbd_devices); | ||
| 542 | |||
| 543 | static struct hid_driver tpkbd_driver = { | ||
| 544 | .name = "lenovo_tpkbd", | ||
| 545 | .id_table = tpkbd_devices, | ||
| 546 | .input_mapping = tpkbd_input_mapping, | ||
| 547 | .probe = tpkbd_probe, | ||
| 548 | .remove = tpkbd_remove, | ||
| 549 | }; | ||
| 550 | |||
| 551 | static int __init tpkbd_init(void) | ||
| 552 | { | ||
| 553 | return hid_register_driver(&tpkbd_driver); | ||
| 554 | } | ||
| 555 | |||
| 556 | static void __exit tpkbd_exit(void) | ||
| 557 | { | ||
| 558 | hid_unregister_driver(&tpkbd_driver); | ||
| 559 | } | ||
| 560 | |||
| 561 | module_init(tpkbd_init); | ||
| 562 | module_exit(tpkbd_exit); | ||
| 563 | |||
| 564 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 40ac6654f1d1..73647266daad 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
| 18 | #include <linux/hid.h> | 18 | #include <linux/hid.h> |
| 19 | #include <linux/input/mt.h> | ||
| 19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 21 | #include <linux/usb.h> | 22 | #include <linux/usb.h> |
| @@ -48,10 +49,6 @@ static bool scroll_acceleration = false; | |||
| 48 | module_param(scroll_acceleration, bool, 0644); | 49 | module_param(scroll_acceleration, bool, 0644); |
| 49 | MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events"); | 50 | MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events"); |
| 50 | 51 | ||
| 51 | static bool report_touches = true; | ||
| 52 | module_param(report_touches, bool, 0644); | ||
| 53 | MODULE_PARM_DESC(report_touches, "Emit touch records (otherwise, only use them for emulation)"); | ||
| 54 | |||
| 55 | static bool report_undeciphered; | 52 | static bool report_undeciphered; |
| 56 | module_param(report_undeciphered, bool, 0644); | 53 | module_param(report_undeciphered, bool, 0644); |
| 57 | MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event"); | 54 | MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event"); |
| @@ -72,15 +69,6 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie | |||
| 72 | 69 | ||
| 73 | #define SCROLL_ACCEL_DEFAULT 7 | 70 | #define SCROLL_ACCEL_DEFAULT 7 |
| 74 | 71 | ||
| 75 | /* Single touch emulation should only begin when no touches are currently down. | ||
| 76 | * This is true when single_touch_id is equal to NO_TOUCHES. If multiple touches | ||
| 77 | * are down and the touch providing for single touch emulation is lifted, | ||
| 78 | * single_touch_id is equal to SINGLE_TOUCH_UP. While single touch emulation is | ||
| 79 | * occurring, single_touch_id corresponds with the tracking id of the touch used. | ||
| 80 | */ | ||
| 81 | #define NO_TOUCHES -1 | ||
| 82 | #define SINGLE_TOUCH_UP -2 | ||
| 83 | |||
| 84 | /* Touch surface information. Dimension is in hundredths of a mm, min and max | 72 | /* Touch surface information. Dimension is in hundredths of a mm, min and max |
| 85 | * are in units. */ | 73 | * are in units. */ |
| 86 | #define MOUSE_DIMENSION_X (float)9056 | 74 | #define MOUSE_DIMENSION_X (float)9056 |
| @@ -129,7 +117,6 @@ struct magicmouse_sc { | |||
| 129 | u8 size; | 117 | u8 size; |
| 130 | } touches[16]; | 118 | } touches[16]; |
| 131 | int tracking_ids[16]; | 119 | int tracking_ids[16]; |
| 132 | int single_touch_id; | ||
| 133 | }; | 120 | }; |
| 134 | 121 | ||
| 135 | static int magicmouse_firm_touch(struct magicmouse_sc *msc) | 122 | static int magicmouse_firm_touch(struct magicmouse_sc *msc) |
| @@ -268,16 +255,14 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda | |||
| 268 | } | 255 | } |
| 269 | } | 256 | } |
| 270 | 257 | ||
| 271 | if (down) { | 258 | if (down) |
| 272 | msc->ntouches++; | 259 | msc->ntouches++; |
| 273 | if (msc->single_touch_id == NO_TOUCHES) | 260 | |
| 274 | msc->single_touch_id = id; | 261 | input_mt_slot(input, id); |
| 275 | } else if (msc->single_touch_id == id) | 262 | input_mt_report_slot_state(input, MT_TOOL_FINGER, down); |
| 276 | msc->single_touch_id = SINGLE_TOUCH_UP; | ||
| 277 | 263 | ||
| 278 | /* Generate the input events for this touch. */ | 264 | /* Generate the input events for this touch. */ |
| 279 | if (report_touches && down) { | 265 | if (down) { |
| 280 | input_report_abs(input, ABS_MT_TRACKING_ID, id); | ||
| 281 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2); | 266 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2); |
| 282 | input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2); | 267 | input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2); |
| 283 | input_report_abs(input, ABS_MT_ORIENTATION, -orientation); | 268 | input_report_abs(input, ABS_MT_ORIENTATION, -orientation); |
| @@ -290,8 +275,6 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda | |||
| 290 | else /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | 275 | else /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ |
| 291 | input_event(input, EV_MSC, MSC_RAW, tdata[8]); | 276 | input_event(input, EV_MSC, MSC_RAW, tdata[8]); |
| 292 | } | 277 | } |
| 293 | |||
| 294 | input_mt_sync(input); | ||
| 295 | } | 278 | } |
| 296 | } | 279 | } |
| 297 | 280 | ||
| @@ -312,12 +295,6 @@ static int magicmouse_raw_event(struct hid_device *hdev, | |||
| 312 | for (ii = 0; ii < npoints; ii++) | 295 | for (ii = 0; ii < npoints; ii++) |
| 313 | magicmouse_emit_touch(msc, ii, data + ii * 9 + 4); | 296 | magicmouse_emit_touch(msc, ii, data + ii * 9 + 4); |
| 314 | 297 | ||
| 315 | /* We don't need an MT sync here because trackpad emits a | ||
| 316 | * BTN_TOUCH event in a new frame when all touches are released. | ||
| 317 | */ | ||
| 318 | if (msc->ntouches == 0) | ||
| 319 | msc->single_touch_id = NO_TOUCHES; | ||
| 320 | |||
| 321 | clicks = data[1]; | 298 | clicks = data[1]; |
| 322 | 299 | ||
| 323 | /* The following bits provide a device specific timestamp. They | 300 | /* The following bits provide a device specific timestamp. They |
| @@ -335,9 +312,6 @@ static int magicmouse_raw_event(struct hid_device *hdev, | |||
| 335 | for (ii = 0; ii < npoints; ii++) | 312 | for (ii = 0; ii < npoints; ii++) |
| 336 | magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); | 313 | magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); |
| 337 | 314 | ||
| 338 | if (report_touches && msc->ntouches == 0) | ||
| 339 | input_mt_sync(input); | ||
| 340 | |||
| 341 | /* When emulating three-button mode, it is important | 315 | /* When emulating three-button mode, it is important |
| 342 | * to have the current touch information before | 316 | * to have the current touch information before |
| 343 | * generating a click event. | 317 | * generating a click event. |
| @@ -370,25 +344,17 @@ static int magicmouse_raw_event(struct hid_device *hdev, | |||
| 370 | input_report_rel(input, REL_Y, y); | 344 | input_report_rel(input, REL_Y, y); |
| 371 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | 345 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ |
| 372 | input_report_key(input, BTN_MOUSE, clicks & 1); | 346 | input_report_key(input, BTN_MOUSE, clicks & 1); |
| 373 | input_report_key(input, BTN_TOUCH, msc->ntouches > 0); | 347 | input_mt_report_pointer_emulation(input, true); |
| 374 | input_report_key(input, BTN_TOOL_FINGER, msc->ntouches == 1); | ||
| 375 | input_report_key(input, BTN_TOOL_DOUBLETAP, msc->ntouches == 2); | ||
| 376 | input_report_key(input, BTN_TOOL_TRIPLETAP, msc->ntouches == 3); | ||
| 377 | input_report_key(input, BTN_TOOL_QUADTAP, msc->ntouches == 4); | ||
| 378 | if (msc->single_touch_id >= 0) { | ||
| 379 | input_report_abs(input, ABS_X, | ||
| 380 | msc->touches[msc->single_touch_id].x); | ||
| 381 | input_report_abs(input, ABS_Y, | ||
| 382 | msc->touches[msc->single_touch_id].y); | ||
| 383 | } | ||
| 384 | } | 348 | } |
| 385 | 349 | ||
| 386 | input_sync(input); | 350 | input_sync(input); |
| 387 | return 1; | 351 | return 1; |
| 388 | } | 352 | } |
| 389 | 353 | ||
| 390 | static void magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev) | 354 | static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev) |
| 391 | { | 355 | { |
| 356 | int error; | ||
| 357 | |||
| 392 | __set_bit(EV_KEY, input->evbit); | 358 | __set_bit(EV_KEY, input->evbit); |
| 393 | 359 | ||
| 394 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { | 360 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { |
| @@ -417,62 +383,66 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h | |||
| 417 | __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); | 383 | __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); |
| 418 | __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); | 384 | __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); |
| 419 | __set_bit(BTN_TOOL_QUADTAP, input->keybit); | 385 | __set_bit(BTN_TOOL_QUADTAP, input->keybit); |
| 386 | __set_bit(BTN_TOOL_QUINTTAP, input->keybit); | ||
| 420 | __set_bit(BTN_TOUCH, input->keybit); | 387 | __set_bit(BTN_TOUCH, input->keybit); |
| 421 | __set_bit(INPUT_PROP_POINTER, input->propbit); | 388 | __set_bit(INPUT_PROP_POINTER, input->propbit); |
| 422 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); | 389 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); |
| 423 | } | 390 | } |
| 424 | 391 | ||
| 425 | if (report_touches) { | ||
| 426 | __set_bit(EV_ABS, input->evbit); | ||
| 427 | |||
| 428 | input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, 15, 0, 0); | ||
| 429 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255 << 2, | ||
| 430 | 4, 0); | ||
| 431 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255 << 2, | ||
| 432 | 4, 0); | ||
| 433 | input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0); | ||
| 434 | |||
| 435 | /* Note: Touch Y position from the device is inverted relative | ||
| 436 | * to how pointer motion is reported (and relative to how USB | ||
| 437 | * HID recommends the coordinates work). This driver keeps | ||
| 438 | * the origin at the same position, and just uses the additive | ||
| 439 | * inverse of the reported Y. | ||
| 440 | */ | ||
| 441 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { | ||
| 442 | input_set_abs_params(input, ABS_MT_POSITION_X, | ||
| 443 | MOUSE_MIN_X, MOUSE_MAX_X, 4, 0); | ||
| 444 | input_set_abs_params(input, ABS_MT_POSITION_Y, | ||
| 445 | MOUSE_MIN_Y, MOUSE_MAX_Y, 4, 0); | ||
| 446 | |||
| 447 | input_abs_set_res(input, ABS_MT_POSITION_X, | ||
| 448 | MOUSE_RES_X); | ||
| 449 | input_abs_set_res(input, ABS_MT_POSITION_Y, | ||
| 450 | MOUSE_RES_Y); | ||
| 451 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
| 452 | input_set_abs_params(input, ABS_X, TRACKPAD_MIN_X, | ||
| 453 | TRACKPAD_MAX_X, 4, 0); | ||
| 454 | input_set_abs_params(input, ABS_Y, TRACKPAD_MIN_Y, | ||
| 455 | TRACKPAD_MAX_Y, 4, 0); | ||
| 456 | input_set_abs_params(input, ABS_MT_POSITION_X, | ||
| 457 | TRACKPAD_MIN_X, TRACKPAD_MAX_X, 4, 0); | ||
| 458 | input_set_abs_params(input, ABS_MT_POSITION_Y, | ||
| 459 | TRACKPAD_MIN_Y, TRACKPAD_MAX_Y, 4, 0); | ||
| 460 | |||
| 461 | input_abs_set_res(input, ABS_X, TRACKPAD_RES_X); | ||
| 462 | input_abs_set_res(input, ABS_Y, TRACKPAD_RES_Y); | ||
| 463 | input_abs_set_res(input, ABS_MT_POSITION_X, | ||
| 464 | TRACKPAD_RES_X); | ||
| 465 | input_abs_set_res(input, ABS_MT_POSITION_Y, | ||
| 466 | TRACKPAD_RES_Y); | ||
| 467 | } | ||
| 468 | 392 | ||
| 469 | input_set_events_per_packet(input, 60); | 393 | __set_bit(EV_ABS, input->evbit); |
| 394 | |||
| 395 | error = input_mt_init_slots(input, 16); | ||
| 396 | if (error) | ||
| 397 | return error; | ||
| 398 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255 << 2, | ||
| 399 | 4, 0); | ||
| 400 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255 << 2, | ||
| 401 | 4, 0); | ||
| 402 | input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0); | ||
| 403 | |||
| 404 | /* Note: Touch Y position from the device is inverted relative | ||
| 405 | * to how pointer motion is reported (and relative to how USB | ||
| 406 | * HID recommends the coordinates work). This driver keeps | ||
| 407 | * the origin at the same position, and just uses the additive | ||
| 408 | * inverse of the reported Y. | ||
| 409 | */ | ||
| 410 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { | ||
| 411 | input_set_abs_params(input, ABS_MT_POSITION_X, | ||
| 412 | MOUSE_MIN_X, MOUSE_MAX_X, 4, 0); | ||
| 413 | input_set_abs_params(input, ABS_MT_POSITION_Y, | ||
| 414 | MOUSE_MIN_Y, MOUSE_MAX_Y, 4, 0); | ||
| 415 | |||
| 416 | input_abs_set_res(input, ABS_MT_POSITION_X, | ||
| 417 | MOUSE_RES_X); | ||
| 418 | input_abs_set_res(input, ABS_MT_POSITION_Y, | ||
| 419 | MOUSE_RES_Y); | ||
| 420 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
| 421 | input_set_abs_params(input, ABS_X, TRACKPAD_MIN_X, | ||
| 422 | TRACKPAD_MAX_X, 4, 0); | ||
| 423 | input_set_abs_params(input, ABS_Y, TRACKPAD_MIN_Y, | ||
| 424 | TRACKPAD_MAX_Y, 4, 0); | ||
| 425 | input_set_abs_params(input, ABS_MT_POSITION_X, | ||
| 426 | TRACKPAD_MIN_X, TRACKPAD_MAX_X, 4, 0); | ||
| 427 | input_set_abs_params(input, ABS_MT_POSITION_Y, | ||
| 428 | TRACKPAD_MIN_Y, TRACKPAD_MAX_Y, 4, 0); | ||
| 429 | |||
| 430 | input_abs_set_res(input, ABS_X, TRACKPAD_RES_X); | ||
| 431 | input_abs_set_res(input, ABS_Y, TRACKPAD_RES_Y); | ||
| 432 | input_abs_set_res(input, ABS_MT_POSITION_X, | ||
| 433 | TRACKPAD_RES_X); | ||
| 434 | input_abs_set_res(input, ABS_MT_POSITION_Y, | ||
| 435 | TRACKPAD_RES_Y); | ||
| 470 | } | 436 | } |
| 471 | 437 | ||
| 438 | input_set_events_per_packet(input, 60); | ||
| 439 | |||
| 472 | if (report_undeciphered) { | 440 | if (report_undeciphered) { |
| 473 | __set_bit(EV_MSC, input->evbit); | 441 | __set_bit(EV_MSC, input->evbit); |
| 474 | __set_bit(MSC_RAW, input->mscbit); | 442 | __set_bit(MSC_RAW, input->mscbit); |
| 475 | } | 443 | } |
| 444 | |||
| 445 | return 0; | ||
| 476 | } | 446 | } |
| 477 | 447 | ||
| 478 | static int magicmouse_input_mapping(struct hid_device *hdev, | 448 | static int magicmouse_input_mapping(struct hid_device *hdev, |
| @@ -511,8 +481,6 @@ static int magicmouse_probe(struct hid_device *hdev, | |||
| 511 | msc->quirks = id->driver_data; | 481 | msc->quirks = id->driver_data; |
| 512 | hid_set_drvdata(hdev, msc); | 482 | hid_set_drvdata(hdev, msc); |
| 513 | 483 | ||
| 514 | msc->single_touch_id = NO_TOUCHES; | ||
| 515 | |||
| 516 | ret = hid_parse(hdev); | 484 | ret = hid_parse(hdev); |
| 517 | if (ret) { | 485 | if (ret) { |
| 518 | hid_err(hdev, "magicmouse hid parse failed\n"); | 486 | hid_err(hdev, "magicmouse hid parse failed\n"); |
| @@ -528,8 +496,13 @@ static int magicmouse_probe(struct hid_device *hdev, | |||
| 528 | /* We do this after hid-input is done parsing reports so that | 496 | /* We do this after hid-input is done parsing reports so that |
| 529 | * hid-input uses the most natural button and axis IDs. | 497 | * hid-input uses the most natural button and axis IDs. |
| 530 | */ | 498 | */ |
| 531 | if (msc->input) | 499 | if (msc->input) { |
| 532 | magicmouse_setup_input(msc->input, hdev); | 500 | ret = magicmouse_setup_input(msc->input, hdev); |
| 501 | if (ret) { | ||
| 502 | hid_err(hdev, "magicmouse setup input failed (%d)\n", ret); | ||
| 503 | goto err_stop_hw; | ||
| 504 | } | ||
| 505 | } | ||
| 533 | 506 | ||
| 534 | if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) | 507 | if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) |
| 535 | report = hid_register_report(hdev, HID_INPUT_REPORT, | 508 | report = hid_register_report(hdev, HID_INPUT_REPORT, |
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 76479246d4ee..59c8b5c1d2de 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
| @@ -83,6 +83,7 @@ struct mt_device { | |||
| 83 | unsigned last_field_index; /* last field index of the report */ | 83 | unsigned last_field_index; /* last field index of the report */ |
| 84 | unsigned last_slot_field; /* the last field of a slot */ | 84 | unsigned last_slot_field; /* the last field of a slot */ |
| 85 | __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ | 85 | __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ |
| 86 | __s8 inputmode_index; /* InputMode HID feature index in the report */ | ||
| 86 | __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, | 87 | __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, |
| 87 | -1 if non-existent */ | 88 | -1 if non-existent */ |
| 88 | __u8 num_received; /* how many contacts we received */ | 89 | __u8 num_received; /* how many contacts we received */ |
| @@ -260,10 +261,20 @@ static void mt_feature_mapping(struct hid_device *hdev, | |||
| 260 | struct hid_field *field, struct hid_usage *usage) | 261 | struct hid_field *field, struct hid_usage *usage) |
| 261 | { | 262 | { |
| 262 | struct mt_device *td = hid_get_drvdata(hdev); | 263 | struct mt_device *td = hid_get_drvdata(hdev); |
| 264 | int i; | ||
| 263 | 265 | ||
| 264 | switch (usage->hid) { | 266 | switch (usage->hid) { |
| 265 | case HID_DG_INPUTMODE: | 267 | case HID_DG_INPUTMODE: |
| 266 | td->inputmode = field->report->id; | 268 | td->inputmode = field->report->id; |
| 269 | td->inputmode_index = 0; /* has to be updated below */ | ||
| 270 | |||
| 271 | for (i=0; i < field->maxusage; i++) { | ||
| 272 | if (field->usage[i].hid == usage->hid) { | ||
| 273 | td->inputmode_index = i; | ||
| 274 | break; | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 267 | break; | 278 | break; |
| 268 | case HID_DG_CONTACTMAX: | 279 | case HID_DG_CONTACTMAX: |
| 269 | td->maxcontact_report_id = field->report->id; | 280 | td->maxcontact_report_id = field->report->id; |
| @@ -618,7 +629,7 @@ static void mt_set_input_mode(struct hid_device *hdev) | |||
| 618 | re = &(hdev->report_enum[HID_FEATURE_REPORT]); | 629 | re = &(hdev->report_enum[HID_FEATURE_REPORT]); |
| 619 | r = re->report_id_hash[td->inputmode]; | 630 | r = re->report_id_hash[td->inputmode]; |
| 620 | if (r) { | 631 | if (r) { |
| 621 | r->field[0]->value[0] = 0x02; | 632 | r->field[0]->value[td->inputmode_index] = 0x02; |
| 622 | usbhid_submit_report(hdev, r, USB_DIR_OUT); | 633 | usbhid_submit_report(hdev, r, USB_DIR_OUT); |
| 623 | } | 634 | } |
| 624 | } | 635 | } |
| @@ -951,6 +962,11 @@ static const struct hid_device_id mt_devices[] = { | |||
| 951 | MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC, | 962 | MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC, |
| 952 | USB_DEVICE_ID_PANABOARD_UBT880) }, | 963 | USB_DEVICE_ID_PANABOARD_UBT880) }, |
| 953 | 964 | ||
| 965 | /* Novatek Panel */ | ||
| 966 | { .driver_data = MT_CLS_DEFAULT, | ||
| 967 | MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK, | ||
| 968 | USB_DEVICE_ID_NOVATEK_PCT) }, | ||
| 969 | |||
| 954 | /* PenMount panels */ | 970 | /* PenMount panels */ |
| 955 | { .driver_data = MT_CLS_CONFIDENCE, | 971 | { .driver_data = MT_CLS_CONFIDENCE, |
| 956 | MT_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, | 972 | MT_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, |
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index 3e0a1e5d2ad5..27c8ebdfad01 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c | |||
| @@ -2613,11 +2613,7 @@ static int picolcd_probe(struct hid_device *hdev, | |||
| 2613 | goto err_cleanup_data; | 2613 | goto err_cleanup_data; |
| 2614 | } | 2614 | } |
| 2615 | 2615 | ||
| 2616 | /* We don't use hidinput but hid_hw_start() fails if nothing is | ||
| 2617 | * claimed. So spoof claimed input. */ | ||
| 2618 | hdev->claimed = HID_CLAIMED_INPUT; | ||
| 2619 | error = hid_hw_start(hdev, 0); | 2616 | error = hid_hw_start(hdev, 0); |
| 2620 | hdev->claimed = 0; | ||
| 2621 | if (error) { | 2617 | if (error) { |
| 2622 | hid_err(hdev, "hardware start failed\n"); | 2618 | hid_err(hdev, "hardware start failed\n"); |
| 2623 | goto err_cleanup_data; | 2619 | goto err_cleanup_data; |
diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c index 093bfad00b02..327f9b8ed1f4 100644 --- a/drivers/hid/hid-roccat-arvo.c +++ b/drivers/hid/hid-roccat-arvo.c | |||
| @@ -39,7 +39,7 @@ static ssize_t arvo_sysfs_show_mode_key(struct device *dev, | |||
| 39 | int retval; | 39 | int retval; |
| 40 | 40 | ||
| 41 | mutex_lock(&arvo->arvo_lock); | 41 | mutex_lock(&arvo->arvo_lock); |
| 42 | retval = roccat_common_receive(usb_dev, ARVO_COMMAND_MODE_KEY, | 42 | retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_MODE_KEY, |
| 43 | &temp_buf, sizeof(struct arvo_mode_key)); | 43 | &temp_buf, sizeof(struct arvo_mode_key)); |
| 44 | mutex_unlock(&arvo->arvo_lock); | 44 | mutex_unlock(&arvo->arvo_lock); |
| 45 | if (retval) | 45 | if (retval) |
| @@ -67,7 +67,7 @@ static ssize_t arvo_sysfs_set_mode_key(struct device *dev, | |||
| 67 | temp_buf.state = state; | 67 | temp_buf.state = state; |
| 68 | 68 | ||
| 69 | mutex_lock(&arvo->arvo_lock); | 69 | mutex_lock(&arvo->arvo_lock); |
| 70 | retval = roccat_common_send(usb_dev, ARVO_COMMAND_MODE_KEY, | 70 | retval = roccat_common2_send(usb_dev, ARVO_COMMAND_MODE_KEY, |
| 71 | &temp_buf, sizeof(struct arvo_mode_key)); | 71 | &temp_buf, sizeof(struct arvo_mode_key)); |
| 72 | mutex_unlock(&arvo->arvo_lock); | 72 | mutex_unlock(&arvo->arvo_lock); |
| 73 | if (retval) | 73 | if (retval) |
| @@ -87,7 +87,7 @@ static ssize_t arvo_sysfs_show_key_mask(struct device *dev, | |||
| 87 | int retval; | 87 | int retval; |
| 88 | 88 | ||
| 89 | mutex_lock(&arvo->arvo_lock); | 89 | mutex_lock(&arvo->arvo_lock); |
| 90 | retval = roccat_common_receive(usb_dev, ARVO_COMMAND_KEY_MASK, | 90 | retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_KEY_MASK, |
| 91 | &temp_buf, sizeof(struct arvo_key_mask)); | 91 | &temp_buf, sizeof(struct arvo_key_mask)); |
| 92 | mutex_unlock(&arvo->arvo_lock); | 92 | mutex_unlock(&arvo->arvo_lock); |
| 93 | if (retval) | 93 | if (retval) |
| @@ -115,7 +115,7 @@ static ssize_t arvo_sysfs_set_key_mask(struct device *dev, | |||
| 115 | temp_buf.key_mask = key_mask; | 115 | temp_buf.key_mask = key_mask; |
| 116 | 116 | ||
| 117 | mutex_lock(&arvo->arvo_lock); | 117 | mutex_lock(&arvo->arvo_lock); |
| 118 | retval = roccat_common_send(usb_dev, ARVO_COMMAND_KEY_MASK, | 118 | retval = roccat_common2_send(usb_dev, ARVO_COMMAND_KEY_MASK, |
| 119 | &temp_buf, sizeof(struct arvo_key_mask)); | 119 | &temp_buf, sizeof(struct arvo_key_mask)); |
| 120 | mutex_unlock(&arvo->arvo_lock); | 120 | mutex_unlock(&arvo->arvo_lock); |
| 121 | if (retval) | 121 | if (retval) |
| @@ -130,7 +130,7 @@ static int arvo_get_actual_profile(struct usb_device *usb_dev) | |||
| 130 | struct arvo_actual_profile temp_buf; | 130 | struct arvo_actual_profile temp_buf; |
| 131 | int retval; | 131 | int retval; |
| 132 | 132 | ||
| 133 | retval = roccat_common_receive(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE, | 133 | retval = roccat_common2_receive(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE, |
| 134 | &temp_buf, sizeof(struct arvo_actual_profile)); | 134 | &temp_buf, sizeof(struct arvo_actual_profile)); |
| 135 | 135 | ||
| 136 | if (retval) | 136 | if (retval) |
| @@ -170,7 +170,7 @@ static ssize_t arvo_sysfs_set_actual_profile(struct device *dev, | |||
| 170 | temp_buf.actual_profile = profile; | 170 | temp_buf.actual_profile = profile; |
| 171 | 171 | ||
| 172 | mutex_lock(&arvo->arvo_lock); | 172 | mutex_lock(&arvo->arvo_lock); |
| 173 | retval = roccat_common_send(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE, | 173 | retval = roccat_common2_send(usb_dev, ARVO_COMMAND_ACTUAL_PROFILE, |
| 174 | &temp_buf, sizeof(struct arvo_actual_profile)); | 174 | &temp_buf, sizeof(struct arvo_actual_profile)); |
| 175 | if (!retval) { | 175 | if (!retval) { |
| 176 | arvo->actual_profile = profile; | 176 | arvo->actual_profile = profile; |
| @@ -194,7 +194,7 @@ static ssize_t arvo_sysfs_write(struct file *fp, | |||
| 194 | return -EINVAL; | 194 | return -EINVAL; |
| 195 | 195 | ||
| 196 | mutex_lock(&arvo->arvo_lock); | 196 | mutex_lock(&arvo->arvo_lock); |
| 197 | retval = roccat_common_send(usb_dev, command, buf, real_size); | 197 | retval = roccat_common2_send(usb_dev, command, buf, real_size); |
| 198 | mutex_unlock(&arvo->arvo_lock); | 198 | mutex_unlock(&arvo->arvo_lock); |
| 199 | 199 | ||
| 200 | return (retval ? retval : real_size); | 200 | return (retval ? retval : real_size); |
| @@ -217,7 +217,7 @@ static ssize_t arvo_sysfs_read(struct file *fp, | |||
| 217 | return -EINVAL; | 217 | return -EINVAL; |
| 218 | 218 | ||
| 219 | mutex_lock(&arvo->arvo_lock); | 219 | mutex_lock(&arvo->arvo_lock); |
| 220 | retval = roccat_common_receive(usb_dev, command, buf, real_size); | 220 | retval = roccat_common2_receive(usb_dev, command, buf, real_size); |
| 221 | mutex_unlock(&arvo->arvo_lock); | 221 | mutex_unlock(&arvo->arvo_lock); |
| 222 | 222 | ||
| 223 | return (retval ? retval : real_size); | 223 | return (retval ? retval : real_size); |
diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c index a6d93992c75a..74f704032627 100644 --- a/drivers/hid/hid-roccat-common.c +++ b/drivers/hid/hid-roccat-common.c | |||
| @@ -16,12 +16,12 @@ | |||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include "hid-roccat-common.h" | 17 | #include "hid-roccat-common.h" |
| 18 | 18 | ||
| 19 | static inline uint16_t roccat_common_feature_report(uint8_t report_id) | 19 | static inline uint16_t roccat_common2_feature_report(uint8_t report_id) |
| 20 | { | 20 | { |
| 21 | return 0x300 | report_id; | 21 | return 0x300 | report_id; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | int roccat_common_receive(struct usb_device *usb_dev, uint report_id, | 24 | int roccat_common2_receive(struct usb_device *usb_dev, uint report_id, |
| 25 | void *data, uint size) | 25 | void *data, uint size) |
| 26 | { | 26 | { |
| 27 | char *buf; | 27 | char *buf; |
| @@ -34,16 +34,16 @@ int roccat_common_receive(struct usb_device *usb_dev, uint report_id, | |||
| 34 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | 34 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), |
| 35 | HID_REQ_GET_REPORT, | 35 | HID_REQ_GET_REPORT, |
| 36 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | 36 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, |
| 37 | roccat_common_feature_report(report_id), | 37 | roccat_common2_feature_report(report_id), |
| 38 | 0, buf, size, USB_CTRL_SET_TIMEOUT); | 38 | 0, buf, size, USB_CTRL_SET_TIMEOUT); |
| 39 | 39 | ||
| 40 | memcpy(data, buf, size); | 40 | memcpy(data, buf, size); |
| 41 | kfree(buf); | 41 | kfree(buf); |
| 42 | return ((len < 0) ? len : ((len != size) ? -EIO : 0)); | 42 | return ((len < 0) ? len : ((len != size) ? -EIO : 0)); |
| 43 | } | 43 | } |
| 44 | EXPORT_SYMBOL_GPL(roccat_common_receive); | 44 | EXPORT_SYMBOL_GPL(roccat_common2_receive); |
| 45 | 45 | ||
| 46 | int roccat_common_send(struct usb_device *usb_dev, uint report_id, | 46 | int roccat_common2_send(struct usb_device *usb_dev, uint report_id, |
| 47 | void const *data, uint size) | 47 | void const *data, uint size) |
| 48 | { | 48 | { |
| 49 | char *buf; | 49 | char *buf; |
| @@ -56,13 +56,71 @@ int roccat_common_send(struct usb_device *usb_dev, uint report_id, | |||
| 56 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | 56 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), |
| 57 | HID_REQ_SET_REPORT, | 57 | HID_REQ_SET_REPORT, |
| 58 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | 58 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, |
| 59 | roccat_common_feature_report(report_id), | 59 | roccat_common2_feature_report(report_id), |
| 60 | 0, buf, size, USB_CTRL_SET_TIMEOUT); | 60 | 0, buf, size, USB_CTRL_SET_TIMEOUT); |
| 61 | 61 | ||
| 62 | kfree(buf); | 62 | kfree(buf); |
| 63 | return ((len < 0) ? len : ((len != size) ? -EIO : 0)); | 63 | return ((len < 0) ? len : ((len != size) ? -EIO : 0)); |
| 64 | } | 64 | } |
| 65 | EXPORT_SYMBOL_GPL(roccat_common_send); | 65 | EXPORT_SYMBOL_GPL(roccat_common2_send); |
| 66 | |||
| 67 | enum roccat_common2_control_states { | ||
| 68 | ROCCAT_COMMON_CONTROL_STATUS_OVERLOAD = 0, | ||
| 69 | ROCCAT_COMMON_CONTROL_STATUS_OK = 1, | ||
| 70 | ROCCAT_COMMON_CONTROL_STATUS_INVALID = 2, | ||
| 71 | ROCCAT_COMMON_CONTROL_STATUS_WAIT = 3, | ||
| 72 | }; | ||
| 73 | |||
| 74 | static int roccat_common2_receive_control_status(struct usb_device *usb_dev) | ||
| 75 | { | ||
| 76 | int retval; | ||
| 77 | struct roccat_common2_control control; | ||
| 78 | |||
| 79 | do { | ||
| 80 | msleep(50); | ||
| 81 | retval = roccat_common2_receive(usb_dev, | ||
| 82 | ROCCAT_COMMON_COMMAND_CONTROL, | ||
| 83 | &control, sizeof(struct roccat_common2_control)); | ||
| 84 | |||
| 85 | if (retval) | ||
| 86 | return retval; | ||
| 87 | |||
| 88 | switch (control.value) { | ||
| 89 | case ROCCAT_COMMON_CONTROL_STATUS_OK: | ||
| 90 | return 0; | ||
| 91 | case ROCCAT_COMMON_CONTROL_STATUS_WAIT: | ||
| 92 | msleep(500); | ||
| 93 | continue; | ||
| 94 | case ROCCAT_COMMON_CONTROL_STATUS_INVALID: | ||
| 95 | |||
| 96 | case ROCCAT_COMMON_CONTROL_STATUS_OVERLOAD: | ||
| 97 | /* seems to be critical - replug necessary */ | ||
| 98 | return -EINVAL; | ||
| 99 | default: | ||
| 100 | dev_err(&usb_dev->dev, | ||
| 101 | "roccat_common2_receive_control_status: " | ||
| 102 | "unknown response value 0x%x\n", | ||
| 103 | control.value); | ||
| 104 | return -EINVAL; | ||
| 105 | } | ||
| 106 | |||
| 107 | } while (1); | ||
| 108 | } | ||
| 109 | |||
| 110 | int roccat_common2_send_with_status(struct usb_device *usb_dev, | ||
| 111 | uint command, void const *buf, uint size) | ||
| 112 | { | ||
| 113 | int retval; | ||
| 114 | |||
| 115 | retval = roccat_common2_send(usb_dev, command, buf, size); | ||
| 116 | if (retval) | ||
| 117 | return retval; | ||
| 118 | |||
| 119 | msleep(100); | ||
| 120 | |||
| 121 | return roccat_common2_receive_control_status(usb_dev); | ||
| 122 | } | ||
| 123 | EXPORT_SYMBOL_GPL(roccat_common2_send_with_status); | ||
| 66 | 124 | ||
| 67 | MODULE_AUTHOR("Stefan Achatz"); | 125 | MODULE_AUTHOR("Stefan Achatz"); |
| 68 | MODULE_DESCRIPTION("USB Roccat common driver"); | 126 | MODULE_DESCRIPTION("USB Roccat common driver"); |
diff --git a/drivers/hid/hid-roccat-common.h b/drivers/hid/hid-roccat-common.h index 9a5bc61f9699..a97746a63b70 100644 --- a/drivers/hid/hid-roccat-common.h +++ b/drivers/hid/hid-roccat-common.h | |||
| @@ -15,9 +15,21 @@ | |||
| 15 | #include <linux/usb.h> | 15 | #include <linux/usb.h> |
| 16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
| 17 | 17 | ||
| 18 | int roccat_common_receive(struct usb_device *usb_dev, uint report_id, | 18 | enum roccat_common2_commands { |
| 19 | ROCCAT_COMMON_COMMAND_CONTROL = 0x4, | ||
| 20 | }; | ||
| 21 | |||
| 22 | struct roccat_common2_control { | ||
| 23 | uint8_t command; | ||
| 24 | uint8_t value; | ||
| 25 | uint8_t request; /* always 0 on requesting write check */ | ||
| 26 | } __packed; | ||
| 27 | |||
| 28 | int roccat_common2_receive(struct usb_device *usb_dev, uint report_id, | ||
| 19 | void *data, uint size); | 29 | void *data, uint size); |
| 20 | int roccat_common_send(struct usb_device *usb_dev, uint report_id, | 30 | int roccat_common2_send(struct usb_device *usb_dev, uint report_id, |
| 21 | void const *data, uint size); | 31 | void const *data, uint size); |
| 32 | int roccat_common2_send_with_status(struct usb_device *usb_dev, | ||
| 33 | uint command, void const *buf, uint size); | ||
| 22 | 34 | ||
| 23 | #endif | 35 | #endif |
diff --git a/drivers/hid/hid-roccat-isku.c b/drivers/hid/hid-roccat-isku.c index 0e4a0ab47142..5669916c2943 100644 --- a/drivers/hid/hid-roccat-isku.c +++ b/drivers/hid/hid-roccat-isku.c | |||
| @@ -36,51 +36,7 @@ static void isku_profile_activated(struct isku_device *isku, uint new_profile) | |||
| 36 | static int isku_receive(struct usb_device *usb_dev, uint command, | 36 | static int isku_receive(struct usb_device *usb_dev, uint command, |
| 37 | void *buf, uint size) | 37 | void *buf, uint size) |
| 38 | { | 38 | { |
| 39 | return roccat_common_receive(usb_dev, command, buf, size); | 39 | return roccat_common2_receive(usb_dev, command, buf, size); |
| 40 | } | ||
| 41 | |||
| 42 | static int isku_receive_control_status(struct usb_device *usb_dev) | ||
| 43 | { | ||
| 44 | int retval; | ||
| 45 | struct isku_control control; | ||
| 46 | |||
| 47 | do { | ||
| 48 | msleep(50); | ||
| 49 | retval = isku_receive(usb_dev, ISKU_COMMAND_CONTROL, | ||
| 50 | &control, sizeof(struct isku_control)); | ||
| 51 | |||
| 52 | if (retval) | ||
| 53 | return retval; | ||
| 54 | |||
| 55 | switch (control.value) { | ||
| 56 | case ISKU_CONTROL_VALUE_STATUS_OK: | ||
| 57 | return 0; | ||
| 58 | case ISKU_CONTROL_VALUE_STATUS_WAIT: | ||
| 59 | continue; | ||
| 60 | case ISKU_CONTROL_VALUE_STATUS_INVALID: | ||
| 61 | /* seems to be critical - replug necessary */ | ||
| 62 | case ISKU_CONTROL_VALUE_STATUS_OVERLOAD: | ||
| 63 | return -EINVAL; | ||
| 64 | default: | ||
| 65 | hid_err(usb_dev, "isku_receive_control_status: " | ||
| 66 | "unknown response value 0x%x\n", | ||
| 67 | control.value); | ||
| 68 | return -EINVAL; | ||
| 69 | } | ||
| 70 | |||
| 71 | } while (1); | ||
| 72 | } | ||
| 73 | |||
| 74 | static int isku_send(struct usb_device *usb_dev, uint command, | ||
| 75 | void const *buf, uint size) | ||
| 76 | { | ||
| 77 | int retval; | ||
| 78 | |||
| 79 | retval = roccat_common_send(usb_dev, command, buf, size); | ||
| 80 | if (retval) | ||
| 81 | return retval; | ||
| 82 | |||
| 83 | return isku_receive_control_status(usb_dev); | ||
| 84 | } | 40 | } |
| 85 | 41 | ||
| 86 | static int isku_get_actual_profile(struct usb_device *usb_dev) | 42 | static int isku_get_actual_profile(struct usb_device *usb_dev) |
| @@ -100,7 +56,8 @@ static int isku_set_actual_profile(struct usb_device *usb_dev, int new_profile) | |||
| 100 | buf.command = ISKU_COMMAND_ACTUAL_PROFILE; | 56 | buf.command = ISKU_COMMAND_ACTUAL_PROFILE; |
| 101 | buf.size = sizeof(struct isku_actual_profile); | 57 | buf.size = sizeof(struct isku_actual_profile); |
| 102 | buf.actual_profile = new_profile; | 58 | buf.actual_profile = new_profile; |
| 103 | return isku_send(usb_dev, ISKU_COMMAND_ACTUAL_PROFILE, &buf, | 59 | return roccat_common2_send_with_status(usb_dev, |
| 60 | ISKU_COMMAND_ACTUAL_PROFILE, &buf, | ||
| 104 | sizeof(struct isku_actual_profile)); | 61 | sizeof(struct isku_actual_profile)); |
| 105 | } | 62 | } |
| 106 | 63 | ||
| @@ -197,7 +154,8 @@ static ssize_t isku_sysfs_write(struct file *fp, struct kobject *kobj, | |||
| 197 | return -EINVAL; | 154 | return -EINVAL; |
| 198 | 155 | ||
| 199 | mutex_lock(&isku->isku_lock); | 156 | mutex_lock(&isku->isku_lock); |
| 200 | retval = isku_send(usb_dev, command, (void *)buf, real_size); | 157 | retval = roccat_common2_send_with_status(usb_dev, command, |
| 158 | (void *)buf, real_size); | ||
| 201 | mutex_unlock(&isku->isku_lock); | 159 | mutex_unlock(&isku->isku_lock); |
| 202 | 160 | ||
| 203 | return retval ? retval : real_size; | 161 | return retval ? retval : real_size; |
diff --git a/drivers/hid/hid-roccat-isku.h b/drivers/hid/hid-roccat-isku.h index 075f6efaec58..605b3ce21638 100644 --- a/drivers/hid/hid-roccat-isku.h +++ b/drivers/hid/hid-roccat-isku.h | |||
| @@ -25,13 +25,6 @@ struct isku_control { | |||
| 25 | uint8_t request; | 25 | uint8_t request; |
| 26 | } __packed; | 26 | } __packed; |
| 27 | 27 | ||
| 28 | enum isku_control_values { | ||
| 29 | ISKU_CONTROL_VALUE_STATUS_OVERLOAD = 0, | ||
| 30 | ISKU_CONTROL_VALUE_STATUS_OK = 1, | ||
| 31 | ISKU_CONTROL_VALUE_STATUS_INVALID = 2, | ||
| 32 | ISKU_CONTROL_VALUE_STATUS_WAIT = 3, | ||
| 33 | }; | ||
| 34 | |||
| 35 | struct isku_actual_profile { | 28 | struct isku_actual_profile { |
| 36 | uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */ | 29 | uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */ |
| 37 | uint8_t size; /* always 3 */ | 30 | uint8_t size; /* always 3 */ |
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 40090d602158..9ce2d0b615a4 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c | |||
| @@ -138,7 +138,7 @@ static int kone_check_write(struct usb_device *usb_dev) | |||
| 138 | return 0; | 138 | return 0; |
| 139 | 139 | ||
| 140 | /* unknown answer */ | 140 | /* unknown answer */ |
| 141 | hid_err(usb_dev, "got retval %d when checking write\n", data); | 141 | dev_err(&usb_dev->dev, "got retval %d when checking write\n", data); |
| 142 | return -EIO; | 142 | return -EIO; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| @@ -503,7 +503,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev, | |||
| 503 | 503 | ||
| 504 | retval = kone_set_settings(usb_dev, &kone->settings); | 504 | retval = kone_set_settings(usb_dev, &kone->settings); |
| 505 | if (retval) { | 505 | if (retval) { |
| 506 | hid_err(usb_dev, "couldn't set tcu state\n"); | 506 | dev_err(&usb_dev->dev, "couldn't set tcu state\n"); |
| 507 | /* | 507 | /* |
| 508 | * try to reread valid settings into buffer overwriting | 508 | * try to reread valid settings into buffer overwriting |
| 509 | * first error code | 509 | * first error code |
| @@ -519,7 +519,7 @@ static ssize_t kone_sysfs_set_tcu(struct device *dev, | |||
| 519 | 519 | ||
| 520 | retval = size; | 520 | retval = size; |
| 521 | exit_no_settings: | 521 | exit_no_settings: |
| 522 | hid_err(usb_dev, "couldn't read settings\n"); | 522 | dev_err(&usb_dev->dev, "couldn't read settings\n"); |
| 523 | exit_unlock: | 523 | exit_unlock: |
| 524 | mutex_unlock(&kone->kone_lock); | 524 | mutex_unlock(&kone->kone_lock); |
| 525 | return retval; | 525 | return retval; |
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c index 59e47770fa10..f5602fec4865 100644 --- a/drivers/hid/hid-roccat-koneplus.c +++ b/drivers/hid/hid-roccat-koneplus.c | |||
| @@ -39,88 +39,26 @@ static void koneplus_profile_activated(struct koneplus_device *koneplus, | |||
| 39 | static int koneplus_send_control(struct usb_device *usb_dev, uint value, | 39 | static int koneplus_send_control(struct usb_device *usb_dev, uint value, |
| 40 | enum koneplus_control_requests request) | 40 | enum koneplus_control_requests request) |
| 41 | { | 41 | { |
| 42 | struct koneplus_control control; | 42 | struct roccat_common2_control control; |
| 43 | 43 | ||
| 44 | if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || | 44 | if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || |
| 45 | request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && | 45 | request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && |
| 46 | value > 4) | 46 | value > 4) |
| 47 | return -EINVAL; | 47 | return -EINVAL; |
| 48 | 48 | ||
| 49 | control.command = KONEPLUS_COMMAND_CONTROL; | 49 | control.command = ROCCAT_COMMON_COMMAND_CONTROL; |
| 50 | control.value = value; | 50 | control.value = value; |
| 51 | control.request = request; | 51 | control.request = request; |
| 52 | 52 | ||
| 53 | return roccat_common_send(usb_dev, KONEPLUS_COMMAND_CONTROL, | 53 | return roccat_common2_send_with_status(usb_dev, |
| 54 | &control, sizeof(struct koneplus_control)); | 54 | ROCCAT_COMMON_COMMAND_CONTROL, |
| 55 | } | 55 | &control, sizeof(struct roccat_common2_control)); |
| 56 | |||
| 57 | static int koneplus_receive_control_status(struct usb_device *usb_dev) | ||
| 58 | { | ||
| 59 | int retval; | ||
| 60 | struct koneplus_control control; | ||
| 61 | |||
| 62 | do { | ||
| 63 | retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_CONTROL, | ||
| 64 | &control, sizeof(struct koneplus_control)); | ||
| 65 | |||
| 66 | /* check if we get a completely wrong answer */ | ||
| 67 | if (retval) | ||
| 68 | return retval; | ||
| 69 | |||
| 70 | if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) | ||
| 71 | return 0; | ||
| 72 | |||
| 73 | /* indicates that hardware needs some more time to complete action */ | ||
| 74 | if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) { | ||
| 75 | msleep(500); /* windows driver uses 1000 */ | ||
| 76 | continue; | ||
| 77 | } | ||
| 78 | |||
| 79 | /* seems to be critical - replug necessary */ | ||
| 80 | if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) | ||
| 81 | return -EINVAL; | ||
| 82 | |||
| 83 | hid_err(usb_dev, "koneplus_receive_control_status: " | ||
| 84 | "unknown response value 0x%x\n", control.value); | ||
| 85 | return -EINVAL; | ||
| 86 | } while (1); | ||
| 87 | } | ||
| 88 | |||
| 89 | static int koneplus_send(struct usb_device *usb_dev, uint command, | ||
| 90 | void const *buf, uint size) | ||
| 91 | { | ||
| 92 | int retval; | ||
| 93 | |||
| 94 | retval = roccat_common_send(usb_dev, command, buf, size); | ||
| 95 | if (retval) | ||
| 96 | return retval; | ||
| 97 | |||
| 98 | return koneplus_receive_control_status(usb_dev); | ||
| 99 | } | ||
| 100 | |||
| 101 | static int koneplus_select_profile(struct usb_device *usb_dev, uint number, | ||
| 102 | enum koneplus_control_requests request) | ||
| 103 | { | ||
| 104 | int retval; | ||
| 105 | |||
| 106 | retval = koneplus_send_control(usb_dev, number, request); | ||
| 107 | if (retval) | ||
| 108 | return retval; | ||
| 109 | |||
| 110 | /* allow time to settle things - windows driver uses 500 */ | ||
| 111 | msleep(100); | ||
| 112 | |||
| 113 | retval = koneplus_receive_control_status(usb_dev); | ||
| 114 | if (retval) | ||
| 115 | return retval; | ||
| 116 | |||
| 117 | return 0; | ||
| 118 | } | 56 | } |
| 119 | 57 | ||
| 120 | static int koneplus_get_info(struct usb_device *usb_dev, | 58 | static int koneplus_get_info(struct usb_device *usb_dev, |
| 121 | struct koneplus_info *buf) | 59 | struct koneplus_info *buf) |
| 122 | { | 60 | { |
| 123 | return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_INFO, | 61 | return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_INFO, |
| 124 | buf, sizeof(struct koneplus_info)); | 62 | buf, sizeof(struct koneplus_info)); |
| 125 | } | 63 | } |
| 126 | 64 | ||
| @@ -129,19 +67,20 @@ static int koneplus_get_profile_settings(struct usb_device *usb_dev, | |||
| 129 | { | 67 | { |
| 130 | int retval; | 68 | int retval; |
| 131 | 69 | ||
| 132 | retval = koneplus_select_profile(usb_dev, number, | 70 | retval = koneplus_send_control(usb_dev, number, |
| 133 | KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS); | 71 | KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS); |
| 134 | if (retval) | 72 | if (retval) |
| 135 | return retval; | 73 | return retval; |
| 136 | 74 | ||
| 137 | return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS, | 75 | return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS, |
| 138 | buf, sizeof(struct koneplus_profile_settings)); | 76 | buf, sizeof(struct koneplus_profile_settings)); |
| 139 | } | 77 | } |
| 140 | 78 | ||
| 141 | static int koneplus_set_profile_settings(struct usb_device *usb_dev, | 79 | static int koneplus_set_profile_settings(struct usb_device *usb_dev, |
| 142 | struct koneplus_profile_settings const *settings) | 80 | struct koneplus_profile_settings const *settings) |
| 143 | { | 81 | { |
| 144 | return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_SETTINGS, | 82 | return roccat_common2_send_with_status(usb_dev, |
| 83 | KONEPLUS_COMMAND_PROFILE_SETTINGS, | ||
| 145 | settings, sizeof(struct koneplus_profile_settings)); | 84 | settings, sizeof(struct koneplus_profile_settings)); |
| 146 | } | 85 | } |
| 147 | 86 | ||
| @@ -150,19 +89,20 @@ static int koneplus_get_profile_buttons(struct usb_device *usb_dev, | |||
| 150 | { | 89 | { |
| 151 | int retval; | 90 | int retval; |
| 152 | 91 | ||
| 153 | retval = koneplus_select_profile(usb_dev, number, | 92 | retval = koneplus_send_control(usb_dev, number, |
| 154 | KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS); | 93 | KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS); |
| 155 | if (retval) | 94 | if (retval) |
| 156 | return retval; | 95 | return retval; |
| 157 | 96 | ||
| 158 | return roccat_common_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS, | 97 | return roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS, |
| 159 | buf, sizeof(struct koneplus_profile_buttons)); | 98 | buf, sizeof(struct koneplus_profile_buttons)); |
| 160 | } | 99 | } |
| 161 | 100 | ||
| 162 | static int koneplus_set_profile_buttons(struct usb_device *usb_dev, | 101 | static int koneplus_set_profile_buttons(struct usb_device *usb_dev, |
| 163 | struct koneplus_profile_buttons const *buttons) | 102 | struct koneplus_profile_buttons const *buttons) |
| 164 | { | 103 | { |
| 165 | return koneplus_send(usb_dev, KONEPLUS_COMMAND_PROFILE_BUTTONS, | 104 | return roccat_common2_send_with_status(usb_dev, |
| 105 | KONEPLUS_COMMAND_PROFILE_BUTTONS, | ||
| 166 | buttons, sizeof(struct koneplus_profile_buttons)); | 106 | buttons, sizeof(struct koneplus_profile_buttons)); |
| 167 | } | 107 | } |
| 168 | 108 | ||
| @@ -172,7 +112,7 @@ static int koneplus_get_actual_profile(struct usb_device *usb_dev) | |||
| 172 | struct koneplus_actual_profile buf; | 112 | struct koneplus_actual_profile buf; |
| 173 | int retval; | 113 | int retval; |
| 174 | 114 | ||
| 175 | retval = roccat_common_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE, | 115 | retval = roccat_common2_receive(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE, |
| 176 | &buf, sizeof(struct koneplus_actual_profile)); | 116 | &buf, sizeof(struct koneplus_actual_profile)); |
| 177 | 117 | ||
| 178 | return retval ? retval : buf.actual_profile; | 118 | return retval ? retval : buf.actual_profile; |
| @@ -187,7 +127,8 @@ static int koneplus_set_actual_profile(struct usb_device *usb_dev, | |||
| 187 | buf.size = sizeof(struct koneplus_actual_profile); | 127 | buf.size = sizeof(struct koneplus_actual_profile); |
| 188 | buf.actual_profile = new_profile; | 128 | buf.actual_profile = new_profile; |
| 189 | 129 | ||
| 190 | return koneplus_send(usb_dev, KONEPLUS_COMMAND_ACTUAL_PROFILE, | 130 | return roccat_common2_send_with_status(usb_dev, |
| 131 | KONEPLUS_COMMAND_ACTUAL_PROFILE, | ||
| 191 | &buf, sizeof(struct koneplus_actual_profile)); | 132 | &buf, sizeof(struct koneplus_actual_profile)); |
| 192 | } | 133 | } |
| 193 | 134 | ||
| @@ -208,7 +149,7 @@ static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj, | |||
| 208 | return -EINVAL; | 149 | return -EINVAL; |
| 209 | 150 | ||
| 210 | mutex_lock(&koneplus->koneplus_lock); | 151 | mutex_lock(&koneplus->koneplus_lock); |
| 211 | retval = roccat_common_receive(usb_dev, command, buf, real_size); | 152 | retval = roccat_common2_receive(usb_dev, command, buf, real_size); |
| 212 | mutex_unlock(&koneplus->koneplus_lock); | 153 | mutex_unlock(&koneplus->koneplus_lock); |
| 213 | 154 | ||
| 214 | if (retval) | 155 | if (retval) |
| @@ -231,7 +172,8 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj, | |||
| 231 | return -EINVAL; | 172 | return -EINVAL; |
| 232 | 173 | ||
| 233 | mutex_lock(&koneplus->koneplus_lock); | 174 | mutex_lock(&koneplus->koneplus_lock); |
| 234 | retval = koneplus_send(usb_dev, command, buf, real_size); | 175 | retval = roccat_common2_send_with_status(usb_dev, command, |
| 176 | buf, real_size); | ||
| 235 | mutex_unlock(&koneplus->koneplus_lock); | 177 | mutex_unlock(&koneplus->koneplus_lock); |
| 236 | 178 | ||
| 237 | if (retval) | 179 | if (retval) |
diff --git a/drivers/hid/hid-roccat-koneplus.h b/drivers/hid/hid-roccat-koneplus.h index c03332a4fa9a..7074b2a4b94b 100644 --- a/drivers/hid/hid-roccat-koneplus.h +++ b/drivers/hid/hid-roccat-koneplus.h | |||
| @@ -20,32 +20,11 @@ struct koneplus_talk { | |||
| 20 | uint8_t data[14]; | 20 | uint8_t data[14]; |
| 21 | } __packed; | 21 | } __packed; |
| 22 | 22 | ||
| 23 | /* | ||
| 24 | * case 1: writes request 80 and reads value 1 | ||
| 25 | * | ||
| 26 | */ | ||
| 27 | struct koneplus_control { | ||
| 28 | uint8_t command; /* KONEPLUS_COMMAND_CONTROL */ | ||
| 29 | /* | ||
| 30 | * value is profile number in range 0-4 for requesting settings and buttons | ||
| 31 | * 1 if status ok for requesting status | ||
| 32 | */ | ||
| 33 | uint8_t value; | ||
| 34 | uint8_t request; | ||
| 35 | } __attribute__ ((__packed__)); | ||
| 36 | |||
| 37 | enum koneplus_control_requests { | 23 | enum koneplus_control_requests { |
| 38 | KONEPLUS_CONTROL_REQUEST_STATUS = 0x00, | ||
| 39 | KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80, | 24 | KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80, |
| 40 | KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x90, | 25 | KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x90, |
| 41 | }; | 26 | }; |
| 42 | 27 | ||
| 43 | enum koneplus_control_values { | ||
| 44 | KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0, | ||
| 45 | KONEPLUS_CONTROL_REQUEST_STATUS_OK = 1, | ||
| 46 | KONEPLUS_CONTROL_REQUEST_STATUS_WAIT = 3, | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct koneplus_actual_profile { | 28 | struct koneplus_actual_profile { |
| 50 | uint8_t command; /* KONEPLUS_COMMAND_ACTUAL_PROFILE */ | 29 | uint8_t command; /* KONEPLUS_COMMAND_ACTUAL_PROFILE */ |
| 51 | uint8_t size; /* always 3 */ | 30 | uint8_t size; /* always 3 */ |
| @@ -137,7 +116,6 @@ struct koneplus_tcu_image { | |||
| 137 | } __attribute__ ((__packed__)); | 116 | } __attribute__ ((__packed__)); |
| 138 | 117 | ||
| 139 | enum koneplus_commands { | 118 | enum koneplus_commands { |
| 140 | KONEPLUS_COMMAND_CONTROL = 0x4, | ||
| 141 | KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5, | 119 | KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5, |
| 142 | KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6, | 120 | KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6, |
| 143 | KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7, | 121 | KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7, |
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c index 112d934132c8..ca6527ac655d 100644 --- a/drivers/hid/hid-roccat-kovaplus.c +++ b/drivers/hid/hid-roccat-kovaplus.c | |||
| @@ -47,69 +47,23 @@ static int kovaplus_send_control(struct usb_device *usb_dev, uint value, | |||
| 47 | enum kovaplus_control_requests request) | 47 | enum kovaplus_control_requests request) |
| 48 | { | 48 | { |
| 49 | int retval; | 49 | int retval; |
| 50 | struct kovaplus_control control; | 50 | struct roccat_common2_control control; |
| 51 | 51 | ||
| 52 | if ((request == KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || | 52 | if ((request == KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS || |
| 53 | request == KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && | 53 | request == KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) && |
| 54 | value > 4) | 54 | value > 4) |
| 55 | return -EINVAL; | 55 | return -EINVAL; |
| 56 | 56 | ||
| 57 | control.command = KOVAPLUS_COMMAND_CONTROL; | 57 | control.command = ROCCAT_COMMON_COMMAND_CONTROL; |
| 58 | control.value = value; | 58 | control.value = value; |
| 59 | control.request = request; | 59 | control.request = request; |
| 60 | 60 | ||
| 61 | retval = roccat_common_send(usb_dev, KOVAPLUS_COMMAND_CONTROL, | 61 | retval = roccat_common2_send(usb_dev, ROCCAT_COMMON_COMMAND_CONTROL, |
| 62 | &control, sizeof(struct kovaplus_control)); | 62 | &control, sizeof(struct roccat_common2_control)); |
| 63 | 63 | ||
| 64 | return retval; | 64 | return retval; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | static int kovaplus_receive_control_status(struct usb_device *usb_dev) | ||
| 68 | { | ||
| 69 | int retval; | ||
| 70 | struct kovaplus_control control; | ||
| 71 | |||
| 72 | do { | ||
| 73 | retval = roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_CONTROL, | ||
| 74 | &control, sizeof(struct kovaplus_control)); | ||
| 75 | |||
| 76 | /* check if we get a completely wrong answer */ | ||
| 77 | if (retval) | ||
| 78 | return retval; | ||
| 79 | |||
| 80 | if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OK) | ||
| 81 | return 0; | ||
| 82 | |||
| 83 | /* indicates that hardware needs some more time to complete action */ | ||
| 84 | if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT) { | ||
| 85 | msleep(500); /* windows driver uses 1000 */ | ||
| 86 | continue; | ||
| 87 | } | ||
| 88 | |||
| 89 | /* seems to be critical - replug necessary */ | ||
| 90 | if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) | ||
| 91 | return -EINVAL; | ||
| 92 | |||
| 93 | hid_err(usb_dev, "roccat_common_receive_control_status: " | ||
| 94 | "unknown response value 0x%x\n", control.value); | ||
| 95 | return -EINVAL; | ||
| 96 | } while (1); | ||
| 97 | } | ||
| 98 | |||
| 99 | static int kovaplus_send(struct usb_device *usb_dev, uint command, | ||
| 100 | void const *buf, uint size) | ||
| 101 | { | ||
| 102 | int retval; | ||
| 103 | |||
| 104 | retval = roccat_common_send(usb_dev, command, buf, size); | ||
| 105 | if (retval) | ||
| 106 | return retval; | ||
| 107 | |||
| 108 | msleep(100); | ||
| 109 | |||
| 110 | return kovaplus_receive_control_status(usb_dev); | ||
| 111 | } | ||
| 112 | |||
| 113 | static int kovaplus_select_profile(struct usb_device *usb_dev, uint number, | 67 | static int kovaplus_select_profile(struct usb_device *usb_dev, uint number, |
| 114 | enum kovaplus_control_requests request) | 68 | enum kovaplus_control_requests request) |
| 115 | { | 69 | { |
| @@ -119,7 +73,7 @@ static int kovaplus_select_profile(struct usb_device *usb_dev, uint number, | |||
| 119 | static int kovaplus_get_info(struct usb_device *usb_dev, | 73 | static int kovaplus_get_info(struct usb_device *usb_dev, |
| 120 | struct kovaplus_info *buf) | 74 | struct kovaplus_info *buf) |
| 121 | { | 75 | { |
| 122 | return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_INFO, | 76 | return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_INFO, |
| 123 | buf, sizeof(struct kovaplus_info)); | 77 | buf, sizeof(struct kovaplus_info)); |
| 124 | } | 78 | } |
| 125 | 79 | ||
| @@ -133,14 +87,15 @@ static int kovaplus_get_profile_settings(struct usb_device *usb_dev, | |||
| 133 | if (retval) | 87 | if (retval) |
| 134 | return retval; | 88 | return retval; |
| 135 | 89 | ||
| 136 | return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS, | 90 | return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS, |
| 137 | buf, sizeof(struct kovaplus_profile_settings)); | 91 | buf, sizeof(struct kovaplus_profile_settings)); |
| 138 | } | 92 | } |
| 139 | 93 | ||
| 140 | static int kovaplus_set_profile_settings(struct usb_device *usb_dev, | 94 | static int kovaplus_set_profile_settings(struct usb_device *usb_dev, |
| 141 | struct kovaplus_profile_settings const *settings) | 95 | struct kovaplus_profile_settings const *settings) |
| 142 | { | 96 | { |
| 143 | return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_PROFILE_SETTINGS, | 97 | return roccat_common2_send_with_status(usb_dev, |
| 98 | KOVAPLUS_COMMAND_PROFILE_SETTINGS, | ||
| 144 | settings, sizeof(struct kovaplus_profile_settings)); | 99 | settings, sizeof(struct kovaplus_profile_settings)); |
| 145 | } | 100 | } |
| 146 | 101 | ||
| @@ -154,14 +109,15 @@ static int kovaplus_get_profile_buttons(struct usb_device *usb_dev, | |||
| 154 | if (retval) | 109 | if (retval) |
| 155 | return retval; | 110 | return retval; |
| 156 | 111 | ||
| 157 | return roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS, | 112 | return roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS, |
| 158 | buf, sizeof(struct kovaplus_profile_buttons)); | 113 | buf, sizeof(struct kovaplus_profile_buttons)); |
| 159 | } | 114 | } |
| 160 | 115 | ||
| 161 | static int kovaplus_set_profile_buttons(struct usb_device *usb_dev, | 116 | static int kovaplus_set_profile_buttons(struct usb_device *usb_dev, |
| 162 | struct kovaplus_profile_buttons const *buttons) | 117 | struct kovaplus_profile_buttons const *buttons) |
| 163 | { | 118 | { |
| 164 | return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_PROFILE_BUTTONS, | 119 | return roccat_common2_send_with_status(usb_dev, |
| 120 | KOVAPLUS_COMMAND_PROFILE_BUTTONS, | ||
| 165 | buttons, sizeof(struct kovaplus_profile_buttons)); | 121 | buttons, sizeof(struct kovaplus_profile_buttons)); |
| 166 | } | 122 | } |
| 167 | 123 | ||
| @@ -171,7 +127,7 @@ static int kovaplus_get_actual_profile(struct usb_device *usb_dev) | |||
| 171 | struct kovaplus_actual_profile buf; | 127 | struct kovaplus_actual_profile buf; |
| 172 | int retval; | 128 | int retval; |
| 173 | 129 | ||
| 174 | retval = roccat_common_receive(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE, | 130 | retval = roccat_common2_receive(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE, |
| 175 | &buf, sizeof(struct kovaplus_actual_profile)); | 131 | &buf, sizeof(struct kovaplus_actual_profile)); |
| 176 | 132 | ||
| 177 | return retval ? retval : buf.actual_profile; | 133 | return retval ? retval : buf.actual_profile; |
| @@ -186,7 +142,8 @@ static int kovaplus_set_actual_profile(struct usb_device *usb_dev, | |||
| 186 | buf.size = sizeof(struct kovaplus_actual_profile); | 142 | buf.size = sizeof(struct kovaplus_actual_profile); |
| 187 | buf.actual_profile = new_profile; | 143 | buf.actual_profile = new_profile; |
| 188 | 144 | ||
| 189 | return kovaplus_send(usb_dev, KOVAPLUS_COMMAND_ACTUAL_PROFILE, | 145 | return roccat_common2_send_with_status(usb_dev, |
| 146 | KOVAPLUS_COMMAND_ACTUAL_PROFILE, | ||
| 190 | &buf, sizeof(struct kovaplus_actual_profile)); | 147 | &buf, sizeof(struct kovaplus_actual_profile)); |
| 191 | } | 148 | } |
| 192 | 149 | ||
diff --git a/drivers/hid/hid-roccat-kovaplus.h b/drivers/hid/hid-roccat-kovaplus.h index fb2aed44a8e0..f82daa1cdcb9 100644 --- a/drivers/hid/hid-roccat-kovaplus.h +++ b/drivers/hid/hid-roccat-kovaplus.h | |||
| @@ -14,27 +14,13 @@ | |||
| 14 | 14 | ||
| 15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
| 16 | 16 | ||
| 17 | struct kovaplus_control { | ||
| 18 | uint8_t command; /* KOVAPLUS_COMMAND_CONTROL */ | ||
| 19 | uint8_t value; | ||
| 20 | uint8_t request; | ||
| 21 | } __packed; | ||
| 22 | |||
| 23 | enum kovaplus_control_requests { | 17 | enum kovaplus_control_requests { |
| 24 | /* read after write; value = 1 */ | ||
| 25 | KOVAPLUS_CONTROL_REQUEST_STATUS = 0x0, | ||
| 26 | /* write; value = profile number range 0-4 */ | 18 | /* write; value = profile number range 0-4 */ |
| 27 | KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, | 19 | KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, |
| 28 | /* write; value = profile number range 0-4 */ | 20 | /* write; value = profile number range 0-4 */ |
| 29 | KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20, | 21 | KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20, |
| 30 | }; | 22 | }; |
| 31 | 23 | ||
| 32 | enum kovaplus_control_values { | ||
| 33 | KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0, /* supposed */ | ||
| 34 | KOVAPLUS_CONTROL_REQUEST_STATUS_OK = 1, | ||
| 35 | KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT = 3, /* supposed */ | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct kovaplus_actual_profile { | 24 | struct kovaplus_actual_profile { |
| 39 | uint8_t command; /* KOVAPLUS_COMMAND_ACTUAL_PROFILE */ | 25 | uint8_t command; /* KOVAPLUS_COMMAND_ACTUAL_PROFILE */ |
| 40 | uint8_t size; /* always 3 */ | 26 | uint8_t size; /* always 3 */ |
| @@ -75,7 +61,6 @@ struct kovaplus_a { | |||
| 75 | } __packed; | 61 | } __packed; |
| 76 | 62 | ||
| 77 | enum kovaplus_commands { | 63 | enum kovaplus_commands { |
| 78 | KOVAPLUS_COMMAND_CONTROL = 0x4, | ||
| 79 | KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5, | 64 | KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5, |
| 80 | KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6, | 65 | KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6, |
| 81 | KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7, | 66 | KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7, |
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c index df05c1b1064f..1317c177a3e2 100644 --- a/drivers/hid/hid-roccat-pyra.c +++ b/drivers/hid/hid-roccat-pyra.c | |||
| @@ -42,43 +42,19 @@ static void profile_activated(struct pyra_device *pyra, | |||
| 42 | static int pyra_send_control(struct usb_device *usb_dev, int value, | 42 | static int pyra_send_control(struct usb_device *usb_dev, int value, |
| 43 | enum pyra_control_requests request) | 43 | enum pyra_control_requests request) |
| 44 | { | 44 | { |
| 45 | struct pyra_control control; | 45 | struct roccat_common2_control control; |
| 46 | 46 | ||
| 47 | if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS || | 47 | if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS || |
| 48 | request == PYRA_CONTROL_REQUEST_PROFILE_BUTTONS) && | 48 | request == PYRA_CONTROL_REQUEST_PROFILE_BUTTONS) && |
| 49 | (value < 0 || value > 4)) | 49 | (value < 0 || value > 4)) |
| 50 | return -EINVAL; | 50 | return -EINVAL; |
| 51 | 51 | ||
| 52 | control.command = PYRA_COMMAND_CONTROL; | 52 | control.command = ROCCAT_COMMON_COMMAND_CONTROL; |
| 53 | control.value = value; | 53 | control.value = value; |
| 54 | control.request = request; | 54 | control.request = request; |
| 55 | 55 | ||
| 56 | return roccat_common_send(usb_dev, PYRA_COMMAND_CONTROL, | 56 | return roccat_common2_send(usb_dev, ROCCAT_COMMON_COMMAND_CONTROL, |
| 57 | &control, sizeof(struct pyra_control)); | 57 | &control, sizeof(struct roccat_common2_control)); |
| 58 | } | ||
| 59 | |||
| 60 | static int pyra_receive_control_status(struct usb_device *usb_dev) | ||
| 61 | { | ||
| 62 | int retval; | ||
| 63 | struct pyra_control control; | ||
| 64 | |||
| 65 | do { | ||
| 66 | msleep(10); | ||
| 67 | retval = roccat_common_receive(usb_dev, PYRA_COMMAND_CONTROL, | ||
| 68 | &control, sizeof(struct pyra_control)); | ||
| 69 | |||
| 70 | /* requested too early, try again */ | ||
| 71 | } while (retval == -EPROTO); | ||
| 72 | |||
| 73 | if (!retval && control.command == PYRA_COMMAND_CONTROL && | ||
| 74 | control.request == PYRA_CONTROL_REQUEST_STATUS && | ||
| 75 | control.value == 1) | ||
| 76 | return 0; | ||
| 77 | else { | ||
| 78 | hid_err(usb_dev, "receive control status: unknown response 0x%x 0x%x\n", | ||
| 79 | control.request, control.value); | ||
| 80 | return retval ? retval : -EINVAL; | ||
| 81 | } | ||
| 82 | } | 58 | } |
| 83 | 59 | ||
| 84 | static int pyra_get_profile_settings(struct usb_device *usb_dev, | 60 | static int pyra_get_profile_settings(struct usb_device *usb_dev, |
| @@ -89,7 +65,7 @@ static int pyra_get_profile_settings(struct usb_device *usb_dev, | |||
| 89 | PYRA_CONTROL_REQUEST_PROFILE_SETTINGS); | 65 | PYRA_CONTROL_REQUEST_PROFILE_SETTINGS); |
| 90 | if (retval) | 66 | if (retval) |
| 91 | return retval; | 67 | return retval; |
| 92 | return roccat_common_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS, | 68 | return roccat_common2_receive(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS, |
| 93 | buf, sizeof(struct pyra_profile_settings)); | 69 | buf, sizeof(struct pyra_profile_settings)); |
| 94 | } | 70 | } |
| 95 | 71 | ||
| @@ -101,51 +77,44 @@ static int pyra_get_profile_buttons(struct usb_device *usb_dev, | |||
| 101 | PYRA_CONTROL_REQUEST_PROFILE_BUTTONS); | 77 | PYRA_CONTROL_REQUEST_PROFILE_BUTTONS); |
| 102 | if (retval) | 78 | if (retval) |
| 103 | return retval; | 79 | return retval; |
| 104 | return roccat_common_receive(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS, | 80 | return roccat_common2_receive(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS, |
| 105 | buf, sizeof(struct pyra_profile_buttons)); | 81 | buf, sizeof(struct pyra_profile_buttons)); |
| 106 | } | 82 | } |
| 107 | 83 | ||
| 108 | static int pyra_get_settings(struct usb_device *usb_dev, | 84 | static int pyra_get_settings(struct usb_device *usb_dev, |
| 109 | struct pyra_settings *buf) | 85 | struct pyra_settings *buf) |
| 110 | { | 86 | { |
| 111 | return roccat_common_receive(usb_dev, PYRA_COMMAND_SETTINGS, | 87 | return roccat_common2_receive(usb_dev, PYRA_COMMAND_SETTINGS, |
| 112 | buf, sizeof(struct pyra_settings)); | 88 | buf, sizeof(struct pyra_settings)); |
| 113 | } | 89 | } |
| 114 | 90 | ||
| 115 | static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf) | 91 | static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf) |
| 116 | { | 92 | { |
| 117 | return roccat_common_receive(usb_dev, PYRA_COMMAND_INFO, | 93 | return roccat_common2_receive(usb_dev, PYRA_COMMAND_INFO, |
| 118 | buf, sizeof(struct pyra_info)); | 94 | buf, sizeof(struct pyra_info)); |
| 119 | } | 95 | } |
| 120 | 96 | ||
| 121 | static int pyra_send(struct usb_device *usb_dev, uint command, | ||
| 122 | void const *buf, uint size) | ||
| 123 | { | ||
| 124 | int retval; | ||
| 125 | retval = roccat_common_send(usb_dev, command, buf, size); | ||
| 126 | if (retval) | ||
| 127 | return retval; | ||
| 128 | return pyra_receive_control_status(usb_dev); | ||
| 129 | } | ||
| 130 | |||
| 131 | static int pyra_set_profile_settings(struct usb_device *usb_dev, | 97 | static int pyra_set_profile_settings(struct usb_device *usb_dev, |
| 132 | struct pyra_profile_settings const *settings) | 98 | struct pyra_profile_settings const *settings) |
| 133 | { | 99 | { |
| 134 | return pyra_send(usb_dev, PYRA_COMMAND_PROFILE_SETTINGS, settings, | 100 | return roccat_common2_send_with_status(usb_dev, |
| 101 | PYRA_COMMAND_PROFILE_SETTINGS, settings, | ||
| 135 | sizeof(struct pyra_profile_settings)); | 102 | sizeof(struct pyra_profile_settings)); |
| 136 | } | 103 | } |
| 137 | 104 | ||
| 138 | static int pyra_set_profile_buttons(struct usb_device *usb_dev, | 105 | static int pyra_set_profile_buttons(struct usb_device *usb_dev, |
| 139 | struct pyra_profile_buttons const *buttons) | 106 | struct pyra_profile_buttons const *buttons) |
| 140 | { | 107 | { |
| 141 | return pyra_send(usb_dev, PYRA_COMMAND_PROFILE_BUTTONS, buttons, | 108 | return roccat_common2_send_with_status(usb_dev, |
| 109 | PYRA_COMMAND_PROFILE_BUTTONS, buttons, | ||
| 142 | sizeof(struct pyra_profile_buttons)); | 110 | sizeof(struct pyra_profile_buttons)); |
| 143 | } | 111 | } |
| 144 | 112 | ||
| 145 | static int pyra_set_settings(struct usb_device *usb_dev, | 113 | static int pyra_set_settings(struct usb_device *usb_dev, |
| 146 | struct pyra_settings const *settings) | 114 | struct pyra_settings const *settings) |
| 147 | { | 115 | { |
| 148 | return pyra_send(usb_dev, PYRA_COMMAND_SETTINGS, settings, | 116 | return roccat_common2_send_with_status(usb_dev, |
| 117 | PYRA_COMMAND_SETTINGS, settings, | ||
| 149 | sizeof(struct pyra_settings)); | 118 | sizeof(struct pyra_settings)); |
| 150 | } | 119 | } |
| 151 | 120 | ||
diff --git a/drivers/hid/hid-roccat-pyra.h b/drivers/hid/hid-roccat-pyra.h index 0442d7fa2dcf..eada7830fa99 100644 --- a/drivers/hid/hid-roccat-pyra.h +++ b/drivers/hid/hid-roccat-pyra.h | |||
| @@ -20,18 +20,7 @@ struct pyra_b { | |||
| 20 | uint8_t unknown; /* 1 */ | 20 | uint8_t unknown; /* 1 */ |
| 21 | } __attribute__ ((__packed__)); | 21 | } __attribute__ ((__packed__)); |
| 22 | 22 | ||
| 23 | struct pyra_control { | ||
| 24 | uint8_t command; /* PYRA_COMMAND_CONTROL */ | ||
| 25 | /* | ||
| 26 | * value is profile number for request_settings and request_buttons | ||
| 27 | * 1 if status ok for request_status | ||
| 28 | */ | ||
| 29 | uint8_t value; /* Range 0-4 */ | ||
| 30 | uint8_t request; | ||
| 31 | } __attribute__ ((__packed__)); | ||
| 32 | |||
| 33 | enum pyra_control_requests { | 23 | enum pyra_control_requests { |
| 34 | PYRA_CONTROL_REQUEST_STATUS = 0x00, | ||
| 35 | PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, | 24 | PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, |
| 36 | PYRA_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20 | 25 | PYRA_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20 |
| 37 | }; | 26 | }; |
| @@ -75,7 +64,6 @@ struct pyra_info { | |||
| 75 | } __attribute__ ((__packed__)); | 64 | } __attribute__ ((__packed__)); |
| 76 | 65 | ||
| 77 | enum pyra_commands { | 66 | enum pyra_commands { |
| 78 | PYRA_COMMAND_CONTROL = 0x4, | ||
| 79 | PYRA_COMMAND_SETTINGS = 0x5, | 67 | PYRA_COMMAND_SETTINGS = 0x5, |
| 80 | PYRA_COMMAND_PROFILE_SETTINGS = 0x6, | 68 | PYRA_COMMAND_PROFILE_SETTINGS = 0x6, |
| 81 | PYRA_COMMAND_PROFILE_BUTTONS = 0x7, | 69 | PYRA_COMMAND_PROFILE_BUTTONS = 0x7, |
diff --git a/drivers/hid/hid-roccat-savu.c b/drivers/hid/hid-roccat-savu.c new file mode 100644 index 000000000000..014afba407e0 --- /dev/null +++ b/drivers/hid/hid-roccat-savu.c | |||
| @@ -0,0 +1,316 @@ | |||
| 1 | /* | ||
| 2 | * Roccat Savu driver for Linux | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 11 | * any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | /* Roccat Savu is a gamer mouse with macro keys that can be configured in | ||
| 15 | * 5 profiles. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/device.h> | ||
| 19 | #include <linux/input.h> | ||
| 20 | #include <linux/hid.h> | ||
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/slab.h> | ||
| 23 | #include <linux/hid-roccat.h> | ||
| 24 | #include "hid-ids.h" | ||
| 25 | #include "hid-roccat-common.h" | ||
| 26 | #include "hid-roccat-savu.h" | ||
| 27 | |||
| 28 | static struct class *savu_class; | ||
| 29 | |||
| 30 | static ssize_t savu_sysfs_read(struct file *fp, struct kobject *kobj, | ||
| 31 | char *buf, loff_t off, size_t count, | ||
| 32 | size_t real_size, uint command) | ||
| 33 | { | ||
| 34 | struct device *dev = | ||
| 35 | container_of(kobj, struct device, kobj)->parent->parent; | ||
| 36 | struct savu_device *savu = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 37 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
| 38 | int retval; | ||
| 39 | |||
| 40 | if (off >= real_size) | ||
| 41 | return 0; | ||
| 42 | |||
| 43 | if (off != 0 || count != real_size) | ||
| 44 | return -EINVAL; | ||
| 45 | |||
| 46 | mutex_lock(&savu->savu_lock); | ||
| 47 | retval = roccat_common2_receive(usb_dev, command, buf, real_size); | ||
| 48 | mutex_unlock(&savu->savu_lock); | ||
| 49 | |||
| 50 | return retval ? retval : real_size; | ||
| 51 | } | ||
| 52 | |||
| 53 | static ssize_t savu_sysfs_write(struct file *fp, struct kobject *kobj, | ||
| 54 | void const *buf, loff_t off, size_t count, | ||
| 55 | size_t real_size, uint command) | ||
| 56 | { | ||
| 57 | struct device *dev = | ||
| 58 | container_of(kobj, struct device, kobj)->parent->parent; | ||
| 59 | struct savu_device *savu = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 60 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
| 61 | int retval; | ||
| 62 | |||
| 63 | if (off != 0 || count != real_size) | ||
| 64 | return -EINVAL; | ||
| 65 | |||
| 66 | mutex_lock(&savu->savu_lock); | ||
| 67 | retval = roccat_common2_send_with_status(usb_dev, command, | ||
| 68 | (void *)buf, real_size); | ||
| 69 | mutex_unlock(&savu->savu_lock); | ||
| 70 | |||
| 71 | return retval ? retval : real_size; | ||
| 72 | } | ||
| 73 | |||
| 74 | #define SAVU_SYSFS_W(thingy, THINGY) \ | ||
| 75 | static ssize_t savu_sysfs_write_ ## thingy(struct file *fp, \ | ||
| 76 | struct kobject *kobj, struct bin_attribute *attr, char *buf, \ | ||
| 77 | loff_t off, size_t count) \ | ||
| 78 | { \ | ||
| 79 | return savu_sysfs_write(fp, kobj, buf, off, count, \ | ||
| 80 | SAVU_SIZE_ ## THINGY, SAVU_COMMAND_ ## THINGY); \ | ||
| 81 | } | ||
| 82 | |||
| 83 | #define SAVU_SYSFS_R(thingy, THINGY) \ | ||
| 84 | static ssize_t savu_sysfs_read_ ## thingy(struct file *fp, \ | ||
| 85 | struct kobject *kobj, struct bin_attribute *attr, char *buf, \ | ||
| 86 | loff_t off, size_t count) \ | ||
| 87 | { \ | ||
| 88 | return savu_sysfs_read(fp, kobj, buf, off, count, \ | ||
| 89 | SAVU_SIZE_ ## THINGY, SAVU_COMMAND_ ## THINGY); \ | ||
| 90 | } | ||
| 91 | |||
| 92 | #define SAVU_SYSFS_RW(thingy, THINGY) \ | ||
| 93 | SAVU_SYSFS_W(thingy, THINGY) \ | ||
| 94 | SAVU_SYSFS_R(thingy, THINGY) | ||
| 95 | |||
| 96 | #define SAVU_BIN_ATTRIBUTE_RW(thingy, THINGY) \ | ||
| 97 | { \ | ||
| 98 | .attr = { .name = #thingy, .mode = 0660 }, \ | ||
| 99 | .size = SAVU_SIZE_ ## THINGY, \ | ||
| 100 | .read = savu_sysfs_read_ ## thingy, \ | ||
| 101 | .write = savu_sysfs_write_ ## thingy \ | ||
| 102 | } | ||
| 103 | |||
| 104 | #define SAVU_BIN_ATTRIBUTE_R(thingy, THINGY) \ | ||
| 105 | { \ | ||
| 106 | .attr = { .name = #thingy, .mode = 0440 }, \ | ||
| 107 | .size = SAVU_SIZE_ ## THINGY, \ | ||
| 108 | .read = savu_sysfs_read_ ## thingy, \ | ||
| 109 | } | ||
| 110 | |||
| 111 | #define SAVU_BIN_ATTRIBUTE_W(thingy, THINGY) \ | ||
| 112 | { \ | ||
| 113 | .attr = { .name = #thingy, .mode = 0220 }, \ | ||
| 114 | .size = SAVU_SIZE_ ## THINGY, \ | ||
| 115 | .write = savu_sysfs_write_ ## thingy \ | ||
| 116 | } | ||
| 117 | |||
| 118 | SAVU_SYSFS_W(control, CONTROL) | ||
| 119 | SAVU_SYSFS_RW(profile, PROFILE) | ||
| 120 | SAVU_SYSFS_RW(general, GENERAL) | ||
| 121 | SAVU_SYSFS_RW(buttons, BUTTONS) | ||
| 122 | SAVU_SYSFS_RW(macro, MACRO) | ||
| 123 | SAVU_SYSFS_R(info, INFO) | ||
| 124 | SAVU_SYSFS_RW(sensor, SENSOR) | ||
| 125 | |||
| 126 | static struct bin_attribute savu_bin_attributes[] = { | ||
| 127 | SAVU_BIN_ATTRIBUTE_W(control, CONTROL), | ||
| 128 | SAVU_BIN_ATTRIBUTE_RW(profile, PROFILE), | ||
| 129 | SAVU_BIN_ATTRIBUTE_RW(general, GENERAL), | ||
| 130 | SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS), | ||
| 131 | SAVU_BIN_ATTRIBUTE_RW(macro, MACRO), | ||
| 132 | SAVU_BIN_ATTRIBUTE_R(info, INFO), | ||
| 133 | SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR), | ||
| 134 | __ATTR_NULL | ||
| 135 | }; | ||
| 136 | |||
| 137 | static int savu_init_savu_device_struct(struct usb_device *usb_dev, | ||
| 138 | struct savu_device *savu) | ||
| 139 | { | ||
| 140 | mutex_init(&savu->savu_lock); | ||
| 141 | |||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int savu_init_specials(struct hid_device *hdev) | ||
| 146 | { | ||
| 147 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
| 148 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
| 149 | struct savu_device *savu; | ||
| 150 | int retval; | ||
| 151 | |||
| 152 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
| 153 | != USB_INTERFACE_PROTOCOL_MOUSE) { | ||
| 154 | hid_set_drvdata(hdev, NULL); | ||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | savu = kzalloc(sizeof(*savu), GFP_KERNEL); | ||
| 159 | if (!savu) { | ||
| 160 | hid_err(hdev, "can't alloc device descriptor\n"); | ||
| 161 | return -ENOMEM; | ||
| 162 | } | ||
| 163 | hid_set_drvdata(hdev, savu); | ||
| 164 | |||
| 165 | retval = savu_init_savu_device_struct(usb_dev, savu); | ||
| 166 | if (retval) { | ||
| 167 | hid_err(hdev, "couldn't init struct savu_device\n"); | ||
| 168 | goto exit_free; | ||
| 169 | } | ||
| 170 | |||
| 171 | retval = roccat_connect(savu_class, hdev, | ||
| 172 | sizeof(struct savu_roccat_report)); | ||
| 173 | if (retval < 0) { | ||
| 174 | hid_err(hdev, "couldn't init char dev\n"); | ||
| 175 | } else { | ||
| 176 | savu->chrdev_minor = retval; | ||
| 177 | savu->roccat_claimed = 1; | ||
| 178 | } | ||
| 179 | |||
| 180 | return 0; | ||
| 181 | exit_free: | ||
| 182 | kfree(savu); | ||
| 183 | return retval; | ||
| 184 | } | ||
| 185 | |||
| 186 | static void savu_remove_specials(struct hid_device *hdev) | ||
| 187 | { | ||
| 188 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
| 189 | struct savu_device *savu; | ||
| 190 | |||
| 191 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
| 192 | != USB_INTERFACE_PROTOCOL_MOUSE) | ||
| 193 | return; | ||
| 194 | |||
| 195 | savu = hid_get_drvdata(hdev); | ||
| 196 | if (savu->roccat_claimed) | ||
| 197 | roccat_disconnect(savu->chrdev_minor); | ||
| 198 | kfree(savu); | ||
| 199 | } | ||
| 200 | |||
| 201 | static int savu_probe(struct hid_device *hdev, | ||
| 202 | const struct hid_device_id *id) | ||
| 203 | { | ||
| 204 | int retval; | ||
| 205 | |||
| 206 | retval = hid_parse(hdev); | ||
| 207 | if (retval) { | ||
| 208 | hid_err(hdev, "parse failed\n"); | ||
| 209 | goto exit; | ||
| 210 | } | ||
| 211 | |||
| 212 | retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
| 213 | if (retval) { | ||
| 214 | hid_err(hdev, "hw start failed\n"); | ||
| 215 | goto exit; | ||
| 216 | } | ||
| 217 | |||
| 218 | retval = savu_init_specials(hdev); | ||
| 219 | if (retval) { | ||
| 220 | hid_err(hdev, "couldn't install mouse\n"); | ||
| 221 | goto exit_stop; | ||
| 222 | } | ||
| 223 | |||
| 224 | return 0; | ||
| 225 | |||
| 226 | exit_stop: | ||
| 227 | hid_hw_stop(hdev); | ||
| 228 | exit: | ||
| 229 | return retval; | ||
| 230 | } | ||
| 231 | |||
| 232 | static void savu_remove(struct hid_device *hdev) | ||
| 233 | { | ||
| 234 | savu_remove_specials(hdev); | ||
| 235 | hid_hw_stop(hdev); | ||
| 236 | } | ||
| 237 | |||
| 238 | static void savu_report_to_chrdev(struct savu_device const *savu, | ||
| 239 | u8 const *data) | ||
| 240 | { | ||
| 241 | struct savu_roccat_report roccat_report; | ||
| 242 | struct savu_mouse_report_special const *special_report; | ||
| 243 | |||
| 244 | if (data[0] != SAVU_MOUSE_REPORT_NUMBER_SPECIAL) | ||
| 245 | return; | ||
| 246 | |||
| 247 | special_report = (struct savu_mouse_report_special const *)data; | ||
| 248 | |||
| 249 | roccat_report.type = special_report->type; | ||
| 250 | roccat_report.data[0] = special_report->data[0]; | ||
| 251 | roccat_report.data[1] = special_report->data[1]; | ||
| 252 | roccat_report_event(savu->chrdev_minor, | ||
| 253 | (uint8_t const *)&roccat_report); | ||
| 254 | } | ||
| 255 | |||
| 256 | static int savu_raw_event(struct hid_device *hdev, | ||
| 257 | struct hid_report *report, u8 *data, int size) | ||
| 258 | { | ||
| 259 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
| 260 | struct savu_device *savu = hid_get_drvdata(hdev); | ||
| 261 | |||
| 262 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
| 263 | != USB_INTERFACE_PROTOCOL_MOUSE) | ||
| 264 | return 0; | ||
| 265 | |||
| 266 | if (savu == NULL) | ||
| 267 | return 0; | ||
| 268 | |||
| 269 | if (savu->roccat_claimed) | ||
| 270 | savu_report_to_chrdev(savu, data); | ||
| 271 | |||
| 272 | return 0; | ||
| 273 | } | ||
| 274 | |||
| 275 | static const struct hid_device_id savu_devices[] = { | ||
| 276 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) }, | ||
| 277 | { } | ||
| 278 | }; | ||
| 279 | |||
| 280 | MODULE_DEVICE_TABLE(hid, savu_devices); | ||
| 281 | |||
| 282 | static struct hid_driver savu_driver = { | ||
| 283 | .name = "savu", | ||
| 284 | .id_table = savu_devices, | ||
| 285 | .probe = savu_probe, | ||
| 286 | .remove = savu_remove, | ||
| 287 | .raw_event = savu_raw_event | ||
| 288 | }; | ||
| 289 | |||
| 290 | static int __init savu_init(void) | ||
| 291 | { | ||
| 292 | int retval; | ||
| 293 | |||
| 294 | savu_class = class_create(THIS_MODULE, "savu"); | ||
| 295 | if (IS_ERR(savu_class)) | ||
| 296 | return PTR_ERR(savu_class); | ||
| 297 | savu_class->dev_bin_attrs = savu_bin_attributes; | ||
| 298 | |||
| 299 | retval = hid_register_driver(&savu_driver); | ||
| 300 | if (retval) | ||
| 301 | class_destroy(savu_class); | ||
| 302 | return retval; | ||
| 303 | } | ||
| 304 | |||
| 305 | static void __exit savu_exit(void) | ||
| 306 | { | ||
| 307 | hid_unregister_driver(&savu_driver); | ||
| 308 | class_destroy(savu_class); | ||
| 309 | } | ||
| 310 | |||
| 311 | module_init(savu_init); | ||
| 312 | module_exit(savu_exit); | ||
| 313 | |||
| 314 | MODULE_AUTHOR("Stefan Achatz"); | ||
| 315 | MODULE_DESCRIPTION("USB Roccat Savu driver"); | ||
| 316 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hid/hid-roccat-savu.h b/drivers/hid/hid-roccat-savu.h new file mode 100644 index 000000000000..9120ba72087f --- /dev/null +++ b/drivers/hid/hid-roccat-savu.h | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | #ifndef __HID_ROCCAT_SAVU_H | ||
| 2 | #define __HID_ROCCAT_SAVU_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 6 | */ | ||
| 7 | |||
| 8 | /* | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the Free | ||
| 11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 12 | * any later version. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/types.h> | ||
| 16 | |||
| 17 | enum { | ||
| 18 | SAVU_SIZE_CONTROL = 0x03, | ||
| 19 | SAVU_SIZE_PROFILE = 0x03, | ||
| 20 | SAVU_SIZE_GENERAL = 0x10, | ||
| 21 | SAVU_SIZE_BUTTONS = 0x2f, | ||
| 22 | SAVU_SIZE_MACRO = 0x0823, | ||
| 23 | SAVU_SIZE_INFO = 0x08, | ||
| 24 | SAVU_SIZE_SENSOR = 0x04, | ||
| 25 | }; | ||
| 26 | |||
| 27 | enum savu_control_requests { | ||
| 28 | SAVU_CONTROL_REQUEST_GENERAL = 0x80, | ||
| 29 | SAVU_CONTROL_REQUEST_BUTTONS = 0x90, | ||
| 30 | }; | ||
| 31 | |||
| 32 | enum savu_commands { | ||
| 33 | SAVU_COMMAND_CONTROL = 0x4, | ||
| 34 | SAVU_COMMAND_PROFILE = 0x5, | ||
| 35 | SAVU_COMMAND_GENERAL = 0x6, | ||
| 36 | SAVU_COMMAND_BUTTONS = 0x7, | ||
| 37 | SAVU_COMMAND_MACRO = 0x8, | ||
| 38 | SAVU_COMMAND_INFO = 0x9, | ||
| 39 | SAVU_COMMAND_SENSOR = 0xc, | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct savu_mouse_report_special { | ||
| 43 | uint8_t report_number; /* always 3 */ | ||
| 44 | uint8_t zero; | ||
| 45 | uint8_t type; | ||
| 46 | uint8_t data[2]; | ||
| 47 | } __packed; | ||
| 48 | |||
| 49 | enum { | ||
| 50 | SAVU_MOUSE_REPORT_NUMBER_SPECIAL = 3, | ||
| 51 | }; | ||
| 52 | |||
| 53 | enum savu_mouse_report_button_types { | ||
| 54 | /* data1 = new profile range 1-5 */ | ||
| 55 | SAVU_MOUSE_REPORT_BUTTON_TYPE_PROFILE = 0x20, | ||
| 56 | |||
| 57 | /* data1 = button number range 1-24; data2 = action */ | ||
| 58 | SAVU_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60, | ||
| 59 | |||
| 60 | /* data1 = button number range 1-24; data2 = action */ | ||
| 61 | SAVU_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80, | ||
| 62 | |||
| 63 | /* data1 = setting number range 1-5 */ | ||
| 64 | SAVU_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0, | ||
| 65 | |||
| 66 | /* data1 and data2 = range 0x1-0xb */ | ||
| 67 | SAVU_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0, | ||
| 68 | |||
| 69 | /* data1 = 22 = next track... | ||
| 70 | * data2 = action | ||
| 71 | */ | ||
| 72 | SAVU_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0, | ||
| 73 | }; | ||
| 74 | |||
| 75 | struct savu_roccat_report { | ||
| 76 | uint8_t type; | ||
| 77 | uint8_t data[2]; | ||
| 78 | } __packed; | ||
| 79 | |||
| 80 | struct savu_device { | ||
| 81 | int roccat_claimed; | ||
| 82 | int chrdev_minor; | ||
| 83 | |||
| 84 | struct mutex savu_lock; | ||
| 85 | }; | ||
| 86 | |||
| 87 | #endif | ||
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c index aa958706c0e5..0a1805c9b0e5 100644 --- a/drivers/hid/hid-wiimote-ext.c +++ b/drivers/hid/hid-wiimote-ext.c | |||
| @@ -77,7 +77,7 @@ static __u16 wiiext_keymap[] = { | |||
| 77 | BTN_TR, /* WIIEXT_KEY_RT */ | 77 | BTN_TR, /* WIIEXT_KEY_RT */ |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | /* diable all extensions */ | 80 | /* disable all extensions */ |
| 81 | static void ext_disable(struct wiimote_ext *ext) | 81 | static void ext_disable(struct wiimote_ext *ext) |
| 82 | { | 82 | { |
| 83 | unsigned long flags; | 83 | unsigned long flags; |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 482f936fc29b..dedd8e4e5c6d 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -84,7 +84,7 @@ static int hid_start_in(struct hid_device *hid) | |||
| 84 | spin_lock_irqsave(&usbhid->lock, flags); | 84 | spin_lock_irqsave(&usbhid->lock, flags); |
| 85 | if (hid->open > 0 && | 85 | if (hid->open > 0 && |
| 86 | !test_bit(HID_DISCONNECTED, &usbhid->iofl) && | 86 | !test_bit(HID_DISCONNECTED, &usbhid->iofl) && |
| 87 | !test_bit(HID_REPORTED_IDLE, &usbhid->iofl) && | 87 | !test_bit(HID_SUSPENDED, &usbhid->iofl) && |
| 88 | !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { | 88 | !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) { |
| 89 | rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); | 89 | rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC); |
| 90 | if (rc != 0) { | 90 | if (rc != 0) { |
| @@ -207,15 +207,27 @@ static int usbhid_restart_out_queue(struct usbhid_device *usbhid) | |||
| 207 | int kicked; | 207 | int kicked; |
| 208 | int r; | 208 | int r; |
| 209 | 209 | ||
| 210 | if (!hid) | 210 | if (!hid || test_bit(HID_RESET_PENDING, &usbhid->iofl) || |
| 211 | test_bit(HID_SUSPENDED, &usbhid->iofl)) | ||
| 211 | return 0; | 212 | return 0; |
| 212 | 213 | ||
| 213 | if ((kicked = (usbhid->outhead != usbhid->outtail))) { | 214 | if ((kicked = (usbhid->outhead != usbhid->outtail))) { |
| 214 | hid_dbg(hid, "Kicking head %d tail %d", usbhid->outhead, usbhid->outtail); | 215 | hid_dbg(hid, "Kicking head %d tail %d", usbhid->outhead, usbhid->outtail); |
| 215 | 216 | ||
| 217 | /* Try to wake up from autosuspend... */ | ||
| 216 | r = usb_autopm_get_interface_async(usbhid->intf); | 218 | r = usb_autopm_get_interface_async(usbhid->intf); |
| 217 | if (r < 0) | 219 | if (r < 0) |
| 218 | return r; | 220 | return r; |
| 221 | |||
| 222 | /* | ||
| 223 | * If still suspended, don't submit. Submission will | ||
| 224 | * occur if/when resume drains the queue. | ||
| 225 | */ | ||
| 226 | if (test_bit(HID_SUSPENDED, &usbhid->iofl)) { | ||
| 227 | usb_autopm_put_interface_no_suspend(usbhid->intf); | ||
| 228 | return r; | ||
| 229 | } | ||
| 230 | |||
| 219 | /* Asynchronously flush queue. */ | 231 | /* Asynchronously flush queue. */ |
| 220 | set_bit(HID_OUT_RUNNING, &usbhid->iofl); | 232 | set_bit(HID_OUT_RUNNING, &usbhid->iofl); |
| 221 | if (hid_submit_out(hid)) { | 233 | if (hid_submit_out(hid)) { |
| @@ -234,15 +246,27 @@ static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid) | |||
| 234 | int r; | 246 | int r; |
| 235 | 247 | ||
| 236 | WARN_ON(hid == NULL); | 248 | WARN_ON(hid == NULL); |
| 237 | if (!hid) | 249 | if (!hid || test_bit(HID_RESET_PENDING, &usbhid->iofl) || |
| 250 | test_bit(HID_SUSPENDED, &usbhid->iofl)) | ||
| 238 | return 0; | 251 | return 0; |
| 239 | 252 | ||
| 240 | if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) { | 253 | if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) { |
| 241 | hid_dbg(hid, "Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail); | 254 | hid_dbg(hid, "Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail); |
| 242 | 255 | ||
| 256 | /* Try to wake up from autosuspend... */ | ||
| 243 | r = usb_autopm_get_interface_async(usbhid->intf); | 257 | r = usb_autopm_get_interface_async(usbhid->intf); |
| 244 | if (r < 0) | 258 | if (r < 0) |
| 245 | return r; | 259 | return r; |
| 260 | |||
| 261 | /* | ||
| 262 | * If still suspended, don't submit. Submission will | ||
| 263 | * occur if/when resume drains the queue. | ||
| 264 | */ | ||
| 265 | if (test_bit(HID_SUSPENDED, &usbhid->iofl)) { | ||
| 266 | usb_autopm_put_interface_no_suspend(usbhid->intf); | ||
| 267 | return r; | ||
| 268 | } | ||
| 269 | |||
| 246 | /* Asynchronously flush queue. */ | 270 | /* Asynchronously flush queue. */ |
| 247 | set_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 271 | set_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
| 248 | if (hid_submit_ctrl(hid)) { | 272 | if (hid_submit_ctrl(hid)) { |
| @@ -331,9 +355,12 @@ static int hid_submit_out(struct hid_device *hid) | |||
| 331 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + | 355 | usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + |
| 332 | 1 + (report->id > 0); | 356 | 1 + (report->id > 0); |
| 333 | usbhid->urbout->dev = hid_to_usb_dev(hid); | 357 | usbhid->urbout->dev = hid_to_usb_dev(hid); |
| 334 | memcpy(usbhid->outbuf, raw_report, | 358 | if (raw_report) { |
| 335 | usbhid->urbout->transfer_buffer_length); | 359 | memcpy(usbhid->outbuf, raw_report, |
| 336 | kfree(raw_report); | 360 | usbhid->urbout->transfer_buffer_length); |
| 361 | kfree(raw_report); | ||
| 362 | usbhid->out[usbhid->outtail].raw_report = NULL; | ||
| 363 | } | ||
| 337 | 364 | ||
| 338 | dbg_hid("submitting out urb\n"); | 365 | dbg_hid("submitting out urb\n"); |
| 339 | 366 | ||
| @@ -362,8 +389,11 @@ static int hid_submit_ctrl(struct hid_device *hid) | |||
| 362 | if (dir == USB_DIR_OUT) { | 389 | if (dir == USB_DIR_OUT) { |
| 363 | usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); | 390 | usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0); |
| 364 | usbhid->urbctrl->transfer_buffer_length = len; | 391 | usbhid->urbctrl->transfer_buffer_length = len; |
| 365 | memcpy(usbhid->ctrlbuf, raw_report, len); | 392 | if (raw_report) { |
| 366 | kfree(raw_report); | 393 | memcpy(usbhid->ctrlbuf, raw_report, len); |
| 394 | kfree(raw_report); | ||
| 395 | usbhid->ctrl[usbhid->ctrltail].raw_report = NULL; | ||
| 396 | } | ||
| 367 | } else { | 397 | } else { |
| 368 | int maxpacket, padlen; | 398 | int maxpacket, padlen; |
| 369 | 399 | ||
| @@ -407,16 +437,6 @@ static int hid_submit_ctrl(struct hid_device *hid) | |||
| 407 | * Output interrupt completion handler. | 437 | * Output interrupt completion handler. |
| 408 | */ | 438 | */ |
| 409 | 439 | ||
| 410 | static int irq_out_pump_restart(struct hid_device *hid) | ||
| 411 | { | ||
| 412 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 413 | |||
| 414 | if (usbhid->outhead != usbhid->outtail) | ||
| 415 | return hid_submit_out(hid); | ||
| 416 | else | ||
| 417 | return -1; | ||
| 418 | } | ||
| 419 | |||
| 420 | static void hid_irq_out(struct urb *urb) | 440 | static void hid_irq_out(struct urb *urb) |
| 421 | { | 441 | { |
| 422 | struct hid_device *hid = urb->context; | 442 | struct hid_device *hid = urb->context; |
| @@ -441,15 +461,17 @@ static void hid_irq_out(struct urb *urb) | |||
| 441 | 461 | ||
| 442 | spin_lock_irqsave(&usbhid->lock, flags); | 462 | spin_lock_irqsave(&usbhid->lock, flags); |
| 443 | 463 | ||
| 444 | if (unplug) | 464 | if (unplug) { |
| 445 | usbhid->outtail = usbhid->outhead; | 465 | usbhid->outtail = usbhid->outhead; |
| 446 | else | 466 | } else { |
| 447 | usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); | 467 | usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); |
| 448 | 468 | ||
| 449 | if (!irq_out_pump_restart(hid)) { | 469 | if (usbhid->outhead != usbhid->outtail && |
| 450 | /* Successfully submitted next urb in queue */ | 470 | hid_submit_out(hid) == 0) { |
| 451 | spin_unlock_irqrestore(&usbhid->lock, flags); | 471 | /* Successfully submitted next urb in queue */ |
| 452 | return; | 472 | spin_unlock_irqrestore(&usbhid->lock, flags); |
| 473 | return; | ||
| 474 | } | ||
| 453 | } | 475 | } |
| 454 | 476 | ||
| 455 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | 477 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); |
| @@ -461,15 +483,6 @@ static void hid_irq_out(struct urb *urb) | |||
| 461 | /* | 483 | /* |
| 462 | * Control pipe completion handler. | 484 | * Control pipe completion handler. |
| 463 | */ | 485 | */ |
| 464 | static int ctrl_pump_restart(struct hid_device *hid) | ||
| 465 | { | ||
| 466 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 467 | |||
| 468 | if (usbhid->ctrlhead != usbhid->ctrltail) | ||
| 469 | return hid_submit_ctrl(hid); | ||
| 470 | else | ||
| 471 | return -1; | ||
| 472 | } | ||
| 473 | 486 | ||
| 474 | static void hid_ctrl(struct urb *urb) | 487 | static void hid_ctrl(struct urb *urb) |
| 475 | { | 488 | { |
| @@ -498,15 +511,17 @@ static void hid_ctrl(struct urb *urb) | |||
| 498 | hid_warn(urb->dev, "ctrl urb status %d received\n", status); | 511 | hid_warn(urb->dev, "ctrl urb status %d received\n", status); |
| 499 | } | 512 | } |
| 500 | 513 | ||
| 501 | if (unplug) | 514 | if (unplug) { |
| 502 | usbhid->ctrltail = usbhid->ctrlhead; | 515 | usbhid->ctrltail = usbhid->ctrlhead; |
| 503 | else | 516 | } else { |
| 504 | usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); | 517 | usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); |
| 505 | 518 | ||
| 506 | if (!ctrl_pump_restart(hid)) { | 519 | if (usbhid->ctrlhead != usbhid->ctrltail && |
| 507 | /* Successfully submitted next urb in queue */ | 520 | hid_submit_ctrl(hid) == 0) { |
| 508 | spin_unlock(&usbhid->lock); | 521 | /* Successfully submitted next urb in queue */ |
| 509 | return; | 522 | spin_unlock(&usbhid->lock); |
| 523 | return; | ||
| 524 | } | ||
| 510 | } | 525 | } |
| 511 | 526 | ||
| 512 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 527 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); |
| @@ -540,49 +555,36 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re | |||
| 540 | usbhid->out[usbhid->outhead].report = report; | 555 | usbhid->out[usbhid->outhead].report = report; |
| 541 | usbhid->outhead = head; | 556 | usbhid->outhead = head; |
| 542 | 557 | ||
| 543 | /* Try to awake from autosuspend... */ | 558 | /* If the queue isn't running, restart it */ |
| 544 | if (usb_autopm_get_interface_async(usbhid->intf) < 0) | 559 | if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl)) { |
| 545 | return; | 560 | usbhid_restart_out_queue(usbhid); |
| 546 | 561 | ||
| 547 | /* | 562 | /* Otherwise see if an earlier request has timed out */ |
| 548 | * But if still suspended, leave urb enqueued, don't submit. | 563 | } else if (time_after(jiffies, usbhid->last_out + HZ * 5)) { |
| 549 | * Submission will occur if/when resume() drains the queue. | 564 | |
| 550 | */ | 565 | /* Prevent autosuspend following the unlink */ |
| 551 | if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) | 566 | usb_autopm_get_interface_no_resume(usbhid->intf); |
| 552 | return; | ||
| 553 | 567 | ||
| 554 | if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl)) { | ||
| 555 | if (hid_submit_out(hid)) { | ||
| 556 | clear_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
| 557 | usb_autopm_put_interface_async(usbhid->intf); | ||
| 558 | } | ||
| 559 | wake_up(&usbhid->wait); | ||
| 560 | } else { | ||
| 561 | /* | 568 | /* |
| 562 | * the queue is known to run | 569 | * Prevent resubmission in case the URB completes |
| 563 | * but an earlier request may be stuck | 570 | * before we can unlink it. We don't want to cancel |
| 564 | * we may need to time out | 571 | * the wrong transfer! |
| 565 | * no race because the URB is blocked under | ||
| 566 | * spinlock | ||
| 567 | */ | 572 | */ |
| 568 | if (time_after(jiffies, usbhid->last_out + HZ * 5)) { | 573 | usb_block_urb(usbhid->urbout); |
| 569 | usb_block_urb(usbhid->urbout); | ||
| 570 | /* drop lock to not deadlock if the callback is called */ | ||
| 571 | spin_unlock(&usbhid->lock); | ||
| 572 | usb_unlink_urb(usbhid->urbout); | ||
| 573 | spin_lock(&usbhid->lock); | ||
| 574 | usb_unblock_urb(usbhid->urbout); | ||
| 575 | /* | ||
| 576 | * if the unlinking has already completed | ||
| 577 | * the pump will have been stopped | ||
| 578 | * it must be restarted now | ||
| 579 | */ | ||
| 580 | if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl)) | ||
| 581 | if (!irq_out_pump_restart(hid)) | ||
| 582 | set_bit(HID_OUT_RUNNING, &usbhid->iofl); | ||
| 583 | 574 | ||
| 575 | /* Drop lock to avoid deadlock if the callback runs */ | ||
| 576 | spin_unlock(&usbhid->lock); | ||
| 584 | 577 | ||
| 585 | } | 578 | usb_unlink_urb(usbhid->urbout); |
| 579 | spin_lock(&usbhid->lock); | ||
| 580 | usb_unblock_urb(usbhid->urbout); | ||
| 581 | |||
| 582 | /* Unlink might have stopped the queue */ | ||
| 583 | if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl)) | ||
| 584 | usbhid_restart_out_queue(usbhid); | ||
| 585 | |||
| 586 | /* Now we can allow autosuspend again */ | ||
| 587 | usb_autopm_put_interface_async(usbhid->intf); | ||
| 586 | } | 588 | } |
| 587 | return; | 589 | return; |
| 588 | } | 590 | } |
| @@ -604,47 +606,36 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re | |||
| 604 | usbhid->ctrl[usbhid->ctrlhead].dir = dir; | 606 | usbhid->ctrl[usbhid->ctrlhead].dir = dir; |
| 605 | usbhid->ctrlhead = head; | 607 | usbhid->ctrlhead = head; |
| 606 | 608 | ||
| 607 | /* Try to awake from autosuspend... */ | 609 | /* If the queue isn't running, restart it */ |
| 608 | if (usb_autopm_get_interface_async(usbhid->intf) < 0) | 610 | if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) { |
| 609 | return; | 611 | usbhid_restart_ctrl_queue(usbhid); |
| 610 | 612 | ||
| 611 | /* | 613 | /* Otherwise see if an earlier request has timed out */ |
| 612 | * If already suspended, leave urb enqueued, but don't submit. | 614 | } else if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) { |
| 613 | * Submission will occur if/when resume() drains the queue. | 615 | |
| 614 | */ | 616 | /* Prevent autosuspend following the unlink */ |
| 615 | if (test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) | 617 | usb_autopm_get_interface_no_resume(usbhid->intf); |
| 616 | return; | ||
| 617 | 618 | ||
| 618 | if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl)) { | ||
| 619 | if (hid_submit_ctrl(hid)) { | ||
| 620 | clear_bit(HID_CTRL_RUNNING, &usbhid->iofl); | ||
| 621 | usb_autopm_put_interface_async(usbhid->intf); | ||
| 622 | } | ||
| 623 | wake_up(&usbhid->wait); | ||
| 624 | } else { | ||
| 625 | /* | 619 | /* |
| 626 | * the queue is known to run | 620 | * Prevent resubmission in case the URB completes |
| 627 | * but an earlier request may be stuck | 621 | * before we can unlink it. We don't want to cancel |
| 628 | * we may need to time out | 622 | * the wrong transfer! |
| 629 | * no race because the URB is blocked under | ||
| 630 | * spinlock | ||
| 631 | */ | 623 | */ |
| 632 | if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) { | 624 | usb_block_urb(usbhid->urbctrl); |
| 633 | usb_block_urb(usbhid->urbctrl); | 625 | |
| 634 | /* drop lock to not deadlock if the callback is called */ | 626 | /* Drop lock to avoid deadlock if the callback runs */ |
| 635 | spin_unlock(&usbhid->lock); | 627 | spin_unlock(&usbhid->lock); |
| 636 | usb_unlink_urb(usbhid->urbctrl); | 628 | |
| 637 | spin_lock(&usbhid->lock); | 629 | usb_unlink_urb(usbhid->urbctrl); |
| 638 | usb_unblock_urb(usbhid->urbctrl); | 630 | spin_lock(&usbhid->lock); |
| 639 | /* | 631 | usb_unblock_urb(usbhid->urbctrl); |
| 640 | * if the unlinking has already completed | 632 | |
| 641 | * the pump will have been stopped | 633 | /* Unlink might have stopped the queue */ |
| 642 | * it must be restarted now | 634 | if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) |
| 643 | */ | 635 | usbhid_restart_ctrl_queue(usbhid); |
| 644 | if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) | 636 | |
| 645 | if (!ctrl_pump_restart(hid)) | 637 | /* Now we can allow autosuspend again */ |
| 646 | set_bit(HID_CTRL_RUNNING, &usbhid->iofl); | 638 | usb_autopm_put_interface_async(usbhid->intf); |
| 647 | } | ||
| 648 | } | 639 | } |
| 649 | } | 640 | } |
| 650 | 641 | ||
| @@ -1002,9 +993,10 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
| 1002 | 993 | ||
| 1003 | static void usbhid_restart_queues(struct usbhid_device *usbhid) | 994 | static void usbhid_restart_queues(struct usbhid_device *usbhid) |
| 1004 | { | 995 | { |
| 1005 | if (usbhid->urbout) | 996 | if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl)) |
| 1006 | usbhid_restart_out_queue(usbhid); | 997 | usbhid_restart_out_queue(usbhid); |
| 1007 | usbhid_restart_ctrl_queue(usbhid); | 998 | if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) |
| 999 | usbhid_restart_ctrl_queue(usbhid); | ||
| 1008 | } | 1000 | } |
| 1009 | 1001 | ||
| 1010 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | 1002 | static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) |
| @@ -1471,11 +1463,38 @@ void usbhid_put_power(struct hid_device *hid) | |||
| 1471 | 1463 | ||
| 1472 | 1464 | ||
| 1473 | #ifdef CONFIG_PM | 1465 | #ifdef CONFIG_PM |
| 1466 | static int hid_resume_common(struct hid_device *hid, bool driver_suspended) | ||
| 1467 | { | ||
| 1468 | struct usbhid_device *usbhid = hid->driver_data; | ||
| 1469 | int status; | ||
| 1470 | |||
| 1471 | spin_lock_irq(&usbhid->lock); | ||
| 1472 | clear_bit(HID_SUSPENDED, &usbhid->iofl); | ||
| 1473 | usbhid_mark_busy(usbhid); | ||
| 1474 | |||
| 1475 | if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) || | ||
| 1476 | test_bit(HID_RESET_PENDING, &usbhid->iofl)) | ||
| 1477 | schedule_work(&usbhid->reset_work); | ||
| 1478 | usbhid->retry_delay = 0; | ||
| 1479 | |||
| 1480 | usbhid_restart_queues(usbhid); | ||
| 1481 | spin_unlock_irq(&usbhid->lock); | ||
| 1482 | |||
| 1483 | status = hid_start_in(hid); | ||
| 1484 | if (status < 0) | ||
| 1485 | hid_io_error(hid); | ||
| 1486 | |||
| 1487 | if (driver_suspended && hid->driver && hid->driver->resume) | ||
| 1488 | status = hid->driver->resume(hid); | ||
| 1489 | return status; | ||
| 1490 | } | ||
| 1491 | |||
| 1474 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) | 1492 | static int hid_suspend(struct usb_interface *intf, pm_message_t message) |
| 1475 | { | 1493 | { |
| 1476 | struct hid_device *hid = usb_get_intfdata(intf); | 1494 | struct hid_device *hid = usb_get_intfdata(intf); |
| 1477 | struct usbhid_device *usbhid = hid->driver_data; | 1495 | struct usbhid_device *usbhid = hid->driver_data; |
| 1478 | int status; | 1496 | int status; |
| 1497 | bool driver_suspended = false; | ||
| 1479 | 1498 | ||
| 1480 | if (PMSG_IS_AUTO(message)) { | 1499 | if (PMSG_IS_AUTO(message)) { |
| 1481 | spin_lock_irq(&usbhid->lock); /* Sync with error handler */ | 1500 | spin_lock_irq(&usbhid->lock); /* Sync with error handler */ |
| @@ -1486,13 +1505,14 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 1486 | && !test_bit(HID_KEYS_PRESSED, &usbhid->iofl) | 1505 | && !test_bit(HID_KEYS_PRESSED, &usbhid->iofl) |
| 1487 | && (!usbhid->ledcount || ignoreled)) | 1506 | && (!usbhid->ledcount || ignoreled)) |
| 1488 | { | 1507 | { |
| 1489 | set_bit(HID_REPORTED_IDLE, &usbhid->iofl); | 1508 | set_bit(HID_SUSPENDED, &usbhid->iofl); |
| 1490 | spin_unlock_irq(&usbhid->lock); | 1509 | spin_unlock_irq(&usbhid->lock); |
| 1491 | if (hid->driver && hid->driver->suspend) { | 1510 | if (hid->driver && hid->driver->suspend) { |
| 1492 | status = hid->driver->suspend(hid, message); | 1511 | status = hid->driver->suspend(hid, message); |
| 1493 | if (status < 0) | 1512 | if (status < 0) |
| 1494 | return status; | 1513 | goto failed; |
| 1495 | } | 1514 | } |
| 1515 | driver_suspended = true; | ||
| 1496 | } else { | 1516 | } else { |
| 1497 | usbhid_mark_busy(usbhid); | 1517 | usbhid_mark_busy(usbhid); |
| 1498 | spin_unlock_irq(&usbhid->lock); | 1518 | spin_unlock_irq(&usbhid->lock); |
| @@ -1505,11 +1525,14 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 1505 | if (status < 0) | 1525 | if (status < 0) |
| 1506 | return status; | 1526 | return status; |
| 1507 | } | 1527 | } |
| 1528 | driver_suspended = true; | ||
| 1508 | spin_lock_irq(&usbhid->lock); | 1529 | spin_lock_irq(&usbhid->lock); |
| 1509 | set_bit(HID_REPORTED_IDLE, &usbhid->iofl); | 1530 | set_bit(HID_SUSPENDED, &usbhid->iofl); |
| 1510 | spin_unlock_irq(&usbhid->lock); | 1531 | spin_unlock_irq(&usbhid->lock); |
| 1511 | if (usbhid_wait_io(hid) < 0) | 1532 | if (usbhid_wait_io(hid) < 0) { |
| 1512 | return -EIO; | 1533 | status = -EIO; |
| 1534 | goto failed; | ||
| 1535 | } | ||
| 1513 | } | 1536 | } |
| 1514 | 1537 | ||
| 1515 | hid_cancel_delayed_stuff(usbhid); | 1538 | hid_cancel_delayed_stuff(usbhid); |
| @@ -1517,14 +1540,15 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 1517 | 1540 | ||
| 1518 | if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { | 1541 | if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) { |
| 1519 | /* lost race against keypresses */ | 1542 | /* lost race against keypresses */ |
| 1520 | status = hid_start_in(hid); | 1543 | status = -EBUSY; |
| 1521 | if (status < 0) | 1544 | goto failed; |
| 1522 | hid_io_error(hid); | ||
| 1523 | usbhid_mark_busy(usbhid); | ||
| 1524 | return -EBUSY; | ||
| 1525 | } | 1545 | } |
| 1526 | dev_dbg(&intf->dev, "suspend\n"); | 1546 | dev_dbg(&intf->dev, "suspend\n"); |
| 1527 | return 0; | 1547 | return 0; |
| 1548 | |||
| 1549 | failed: | ||
| 1550 | hid_resume_common(hid, driver_suspended); | ||
| 1551 | return status; | ||
| 1528 | } | 1552 | } |
| 1529 | 1553 | ||
| 1530 | static int hid_resume(struct usb_interface *intf) | 1554 | static int hid_resume(struct usb_interface *intf) |
| @@ -1536,23 +1560,7 @@ static int hid_resume(struct usb_interface *intf) | |||
| 1536 | if (!test_bit(HID_STARTED, &usbhid->iofl)) | 1560 | if (!test_bit(HID_STARTED, &usbhid->iofl)) |
| 1537 | return 0; | 1561 | return 0; |
| 1538 | 1562 | ||
| 1539 | clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); | 1563 | status = hid_resume_common(hid, true); |
| 1540 | usbhid_mark_busy(usbhid); | ||
| 1541 | |||
| 1542 | if (test_bit(HID_CLEAR_HALT, &usbhid->iofl) || | ||
| 1543 | test_bit(HID_RESET_PENDING, &usbhid->iofl)) | ||
| 1544 | schedule_work(&usbhid->reset_work); | ||
| 1545 | usbhid->retry_delay = 0; | ||
| 1546 | status = hid_start_in(hid); | ||
| 1547 | if (status < 0) | ||
| 1548 | hid_io_error(hid); | ||
| 1549 | usbhid_restart_queues(usbhid); | ||
| 1550 | |||
| 1551 | if (status >= 0 && hid->driver && hid->driver->resume) { | ||
| 1552 | int ret = hid->driver->resume(hid); | ||
| 1553 | if (ret < 0) | ||
| 1554 | status = ret; | ||
| 1555 | } | ||
| 1556 | dev_dbg(&intf->dev, "resume status %d\n", status); | 1564 | dev_dbg(&intf->dev, "resume status %d\n", status); |
| 1557 | return 0; | 1565 | return 0; |
| 1558 | } | 1566 | } |
| @@ -1563,7 +1571,7 @@ static int hid_reset_resume(struct usb_interface *intf) | |||
| 1563 | struct usbhid_device *usbhid = hid->driver_data; | 1571 | struct usbhid_device *usbhid = hid->driver_data; |
| 1564 | int status; | 1572 | int status; |
| 1565 | 1573 | ||
| 1566 | clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); | 1574 | clear_bit(HID_SUSPENDED, &usbhid->iofl); |
| 1567 | status = hid_post_reset(intf); | 1575 | status = hid_post_reset(intf); |
| 1568 | if (status >= 0 && hid->driver && hid->driver->reset_resume) { | 1576 | if (status >= 0 && hid->driver && hid->driver->reset_resume) { |
| 1569 | int ret = hid->driver->reset_resume(hid); | 1577 | int ret = hid->driver->reset_resume(hid); |
diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index 1883d7b94870..bd87a61e5303 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h | |||
| @@ -53,7 +53,6 @@ struct usb_interface *usbhid_find_interface(int minor); | |||
| 53 | #define HID_CLEAR_HALT 6 | 53 | #define HID_CLEAR_HALT 6 |
| 54 | #define HID_DISCONNECTED 7 | 54 | #define HID_DISCONNECTED 7 |
| 55 | #define HID_STARTED 8 | 55 | #define HID_STARTED 8 |
| 56 | #define HID_REPORTED_IDLE 9 | ||
| 57 | #define HID_KEYS_PRESSED 10 | 56 | #define HID_KEYS_PRESSED 10 |
| 58 | #define HID_NO_BANDWIDTH 11 | 57 | #define HID_NO_BANDWIDTH 11 |
| 59 | 58 | ||
diff --git a/include/linux/hid.h b/include/linux/hid.h index 449fa385703d..42970de1b40c 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -200,6 +200,7 @@ struct hid_item { | |||
| 200 | #define HID_UP_DIGITIZER 0x000d0000 | 200 | #define HID_UP_DIGITIZER 0x000d0000 |
| 201 | #define HID_UP_PID 0x000f0000 | 201 | #define HID_UP_PID 0x000f0000 |
| 202 | #define HID_UP_HPVENDOR 0xff7f0000 | 202 | #define HID_UP_HPVENDOR 0xff7f0000 |
| 203 | #define HID_UP_HPVENDOR2 0xff010000 | ||
| 203 | #define HID_UP_MSVENDOR 0xff000000 | 204 | #define HID_UP_MSVENDOR 0xff000000 |
| 204 | #define HID_UP_CUSTOM 0x00ff0000 | 205 | #define HID_UP_CUSTOM 0x00ff0000 |
| 205 | #define HID_UP_LOGIVENDOR 0xffbc0000 | 206 | #define HID_UP_LOGIVENDOR 0xffbc0000 |
