Commit fd62c545 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID subsystem updates from Jiri Kosina:

 1) Support for HID over I2C bus has been added by Benjamin Tissoires.
    ACPI device discovery is still in the works.

 2) Support for Win8 Multitiouch protocol is being added, most work done
    by Benjamin Tissoires as well

 3) EIO/ERESTARTSYS is fixed in hiddev/hidraw, fixes by Andrew Duggan
    and Jiri Kosina

 4) ION iCade driver added by Bastien Nocera

 5) Support for a couple new Roccat devices has been added by Stefan
    Achatz

 6) HID sensor hubs are now auto-detected instead of having to list all
    the VID/PID combinations in the blacklist array

 7) other random fixes and support for new device IDs

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (65 commits)
  HID: i2c-hid: add mutex protecting open/close race
  Revert "HID: sensors: add to special driver list"
  HID: sensors: autodetect USB HID sensor hubs
  HID: hidp: fallback to input session properly if hid is blacklisted
  HID: i2c-hid: fix ret_count check
  HID: i2c-hid: fix i2c_hid_get_raw_report count mismatches
  HID: i2c-hid: remove extra .irq field in struct i2c_hid
  HID: i2c-hid: reorder allocation/free of buffers
  HID: i2c-hid: fix memory corruption due to missing hid declaration
  HID: i2c-hid: remove superfluous include
  HID: i2c-hid: remove unneeded test in i2c_hid_remove
  HID: i2c-hid: i2c_hid_get_report may fail
  HID: i2c-hid: also call i2c_hid_free_buffers in i2c_hid_remove
  HID: i2c-hid: fix error messages
  HID: i2c-hid: fix return paths
  HID: i2c-hid: remove unused static declarations
  HID: i2c-hid: fix i2c_hid_dbg macro
  HID: i2c-hid: fix checkpatch.pl warning
  HID: i2c-hid: enhance Kconfig
  HID: i2c-hid: change I2C name
  ...
parents a2013a13 818b930b
...@@ -8,3 +8,41 @@ Description: The integer value of this attribute ranges from 0-4. ...@@ -8,3 +8,41 @@ Description: The integer value of this attribute ranges from 0-4.
When written, this file sets the number of the startup profile When written, this file sets the number of the startup profile
and the mouse activates this profile immediately. and the mouse activates this profile immediately.
Please use actual_profile, it does the same thing. Please use actual_profile, it does the same thing.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
Date: October 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When read, this file returns the raw integer version number of the
firmware reported by the mouse. Using the integer value eases
further usage in other programs. To receive the real version
number the decimal point has to be shifted 2 positions to the
left. E.g. a returned value of 121 means 1.21
This file is readonly.
Please read binary attribute info which contains firmware version.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The mouse can store 5 profiles which can be switched by the
press of a button. A profile is split in settings and buttons.
profile_buttons holds information about button layout.
When read, these files return the respective profile buttons.
The returned data is 77 bytes in size.
This file is readonly.
Write control to select profile and read profile_buttons instead.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The mouse can store 5 profiles which can be switched by the
press of a button. A profile is split in settings and buttons.
profile_settings holds information like resolution, sensitivity
and light effects.
When read, these files return the respective profile settings.
The returned data is 43 bytes in size.
This file is readonly.
Write control to select profile and read profile_settings instead.
Users: http://roccat.sourceforge.net
\ No newline at end of file
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_cpi
Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The integer value of this attribute ranges from 1-4.
When read, this attribute returns the number of the active
cpi level.
This file is readonly.
Has never been used. If bookkeeping is done, it's done in userland tools.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x
Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The integer value of this attribute ranges from 1-10.
When read, this attribute returns the number of the actual
sensitivity in x direction.
This file is readonly.
Has never been used. If bookkeeping is done, it's done in userland tools.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_y
Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The integer value of this attribute ranges from 1-10.
When read, this attribute returns the number of the actual
sensitivity in y direction.
This file is readonly.
Has never been used. If bookkeeping is done, it's done in userland tools.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/firmware_version
Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When read, this file returns the raw integer version number of the
firmware reported by the mouse. Using the integer value eases
further usage in other programs. To receive the real version
number the decimal point has to be shifted 2 positions to the
left. E.g. a returned value of 121 means 1.21
This file is readonly.
Obsoleted by binary sysfs attribute "info".
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_buttons
Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The mouse can store 5 profiles which can be switched by the
press of a button. A profile is split in settings and buttons.
profile_buttons holds information about button layout.
When read, these files return the respective profile buttons.
The returned data is 23 bytes in size.
This file is readonly.
Write control to select profile and read profile_buttons instead.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_settings
Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The mouse can store 5 profiles which can be switched by the
press of a button. A profile is split in settings and buttons.
profile_settings holds information like resolution, sensitivity
and light effects.
When read, these files return the respective profile settings.
The returned data is 16 bytes in size.
This file is readonly.
Write control to select profile and read profile_settings instead.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_cpi
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: It is possible to switch the cpi setting of the mouse with the
press of a button.
When read, this file returns the raw number of the actual cpi
setting reported by the mouse. This number has to be further
processed to receive the real dpi value.
VALUE DPI
1 400
2 800
4 1600
This file is readonly.
Has never been used. If bookkeeping is done, it's done in userland tools.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When read, this file returns the number of the actual profile in
range 0-4.
This file is readonly.
Please use binary attribute "settings" which provides this information.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When read, this file returns the raw integer version number of the
firmware reported by the mouse. Using the integer value eases
further usage in other programs. To receive the real version
number the decimal point has to be shifted 2 positions to the
left. E.g. a returned value of 138 means 1.38
This file is readonly.
Please use binary attribute "info" which provides this information.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The mouse can store 5 profiles which can be switched by the
press of a button. A profile is split in settings and buttons.
profile_buttons holds information about button layout.
When read, these files return the respective profile buttons.
The returned data is 19 bytes in size.
This file is readonly.
Write control to select profile and read profile_buttons instead.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The mouse can store 5 profiles which can be switched by the
press of a button. A profile is split in settings and buttons.
profile_settings holds information like resolution, sensitivity
and light effects.
When read, these files return the respective profile settings.
The returned data is 13 bytes in size.
This file is readonly.
Write control to select profile and read profile_settings instead.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The integer value of this attribute ranges from 0-4.
When read, this attribute returns the number of the profile
that's active when the mouse is powered on.
This file is readonly.
Please use binary attribute "settings" which provides this information.
Users: http://roccat.sourceforge.net
...@@ -117,6 +117,14 @@ Description: When written, this file lets one store macros with max 500 ...@@ -117,6 +117,14 @@ Description: When written, this file lets one store macros with max 500
which profile and key to read. which profile and key to read.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/reset
Date: November 2012
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When written, this file lets one reset the device.
The data has to be 3 bytes long.
This file is writeonly.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/control What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/isku/roccatisku<minor>/control
Date: June 2011 Date: June 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
......
...@@ -9,15 +9,12 @@ Description: The integer value of this attribute ranges from 0-4. ...@@ -9,15 +9,12 @@ Description: The integer value of this attribute ranges from 0-4.
and the mouse activates this profile immediately. and the mouse activates this profile immediately.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/info
Date: October 2010 Date: November 2012
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When read, this file returns the raw integer version number of the Description: When read, this file returns general data like firmware version.
firmware reported by the mouse. Using the integer value eases When written, the device can be reset.
further usage in other programs. To receive the real version The data is 8 bytes long.
number the decimal point has to be shifted 2 positions to the
left. E.g. a returned value of 121 means 1.21
This file is readonly.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro
...@@ -42,18 +39,8 @@ Description: The mouse can store 5 profiles which can be switched by the ...@@ -42,18 +39,8 @@ Description: The mouse can store 5 profiles which can be switched by the
The mouse will reject invalid data. The mouse will reject invalid data.
Which profile to write is determined by the profile number Which profile to write is determined by the profile number
contained in the data. contained in the data.
This file is writeonly. Before reading this file, control has to be written to select
Users: http://roccat.sourceforge.net which profile to read.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The mouse can store 5 profiles which can be switched by the
press of a button. A profile is split in settings and buttons.
profile_buttons holds information about button layout.
When read, these files return the respective profile buttons.
The returned data is 77 bytes in size.
This file is readonly.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings
...@@ -68,19 +55,8 @@ Description: The mouse can store 5 profiles which can be switched by the ...@@ -68,19 +55,8 @@ Description: The mouse can store 5 profiles which can be switched by the
The mouse will reject invalid data. The mouse will reject invalid data.
Which profile to write is determined by the profile number Which profile to write is determined by the profile number
contained in the data. contained in the data.
This file is writeonly. Before reading this file, control has to be written to select
Users: http://roccat.sourceforge.net which profile to read.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The mouse can store 5 profiles which can be switched by the
press of a button. A profile is split in settings and buttons.
profile_settings holds information like resolution, sensitivity
and light effects.
When read, these files return the respective profile settings.
The returned data is 43 bytes in size.
This file is readonly.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor
...@@ -104,9 +80,9 @@ What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid- ...@@ -104,9 +80,9 @@ What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-
Date: October 2010 Date: October 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When written a calibration process for the tracking control unit Description: When written a calibration process for the tracking control unit
can be initiated/cancelled. can be initiated/cancelled. Also lets one read/write sensor
The data has to be 3 bytes long. registers.
This file is writeonly. The data has to be 4 bytes long.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image
......
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_cpi
Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The integer value of this attribute ranges from 1-4.
When read, this attribute returns the number of the active
cpi level.
This file is readonly.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_profile What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_profile
Date: January 2011 Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
...@@ -18,33 +9,12 @@ Description: The integer value of this attribute ranges from 0-4. ...@@ -18,33 +9,12 @@ Description: The integer value of this attribute ranges from 0-4.
active when the mouse is powered on. active when the mouse is powered on.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/info
Date: January 2011 Date: November 2012
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The integer value of this attribute ranges from 1-10. Description: When read, this file returns general data like firmware version.
When read, this attribute returns the number of the actual When written, the device can be reset.
sensitivity in x direction. The data is 6 bytes long.
This file is readonly.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_y
Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The integer value of this attribute ranges from 1-10.
When read, this attribute returns the number of the actual
sensitivity in y direction.
This file is readonly.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/firmware_version
Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When read, this file returns the raw integer version number of the
firmware reported by the mouse. Using the integer value eases
further usage in other programs. To receive the real version
number the decimal point has to be shifted 2 positions to the
left. E.g. a returned value of 121 means 1.21
This file is readonly.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_buttons What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_buttons
...@@ -58,18 +28,8 @@ Description: The mouse can store 5 profiles which can be switched by the ...@@ -58,18 +28,8 @@ Description: The mouse can store 5 profiles which can be switched by the
The mouse will reject invalid data. The mouse will reject invalid data.
Which profile to write is determined by the profile number Which profile to write is determined by the profile number
contained in the data. contained in the data.
This file is writeonly. Before reading this file, control has to be written to select
Users: http://roccat.sourceforge.net which profile to read.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_buttons
Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The mouse can store 5 profiles which can be switched by the
press of a button. A profile is split in settings and buttons.
profile_buttons holds information about button layout.
When read, these files return the respective profile buttons.
The returned data is 23 bytes in size.
This file is readonly.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_settings What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_settings
...@@ -84,17 +44,6 @@ Description: The mouse can store 5 profiles which can be switched by the ...@@ -84,17 +44,6 @@ Description: The mouse can store 5 profiles which can be switched by the
The mouse will reject invalid data. The mouse will reject invalid data.
Which profile to write is determined by the profile number Which profile to write is determined by the profile number
contained in the data. contained in the data.
This file is writeonly. Before reading this file, control has to be written to select
Users: http://roccat.sourceforge.net which profile to read.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_settings
Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The mouse can store 5 profiles which can be switched by the
press of a button. A profile is split in settings and buttons.
profile_settings holds information like resolution, sensitivity
and light effects.
When read, these files return the respective profile settings.
The returned data is 16 bytes in size.
This file is readonly.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/control
Date: October 2012
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When written, cpi, button and light settings can be configured.
When read, actual cpi setting and sensor data are returned.
The data has to be 8 bytes long.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_cpi What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/info
Date: August 2010 Date: November 2012
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: It is possible to switch the cpi setting of the mouse with the
press of a button.
When read, this file returns the raw number of the actual cpi
setting reported by the mouse. This number has to be further
processed to receive the real dpi value.
VALUE DPI
1 400
2 800
4 1600
This file is readonly.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When read, this file returns the number of the actual profile in Description: When read, this file returns general data like firmware version.
range 0-4. When written, the device can be reset.
This file is readonly. The data is 6 bytes long.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When read, this file returns the raw integer version number of the
firmware reported by the mouse. Using the integer value eases
further usage in other programs. To receive the real version
number the decimal point has to be shifted 2 positions to the
left. E.g. a returned value of 138 means 1.38
This file is readonly.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings
...@@ -46,19 +18,8 @@ Description: The mouse can store 5 profiles which can be switched by the ...@@ -46,19 +18,8 @@ Description: The mouse can store 5 profiles which can be switched by the
The mouse will reject invalid data. The mouse will reject invalid data.
Which profile to write is determined by the profile number Which profile to write is determined by the profile number
contained in the data. contained in the data.
This file is writeonly. Before reading this file, control has to be written to select
Users: http://roccat.sourceforge.net which profile to read.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The mouse can store 5 profiles which can be switched by the
press of a button. A profile is split in settings and buttons.
profile_settings holds information like resolution, sensitivity
and light effects.
When read, these files return the respective profile settings.
The returned data is 13 bytes in size.
This file is readonly.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons
...@@ -72,27 +33,8 @@ Description: The mouse can store 5 profiles which can be switched by the ...@@ -72,27 +33,8 @@ Description: The mouse can store 5 profiles which can be switched by the
The mouse will reject invalid data. The mouse will reject invalid data.
Which profile to write is determined by the profile number Which profile to write is determined by the profile number
contained in the data. contained in the data.
This file is writeonly. Before reading this file, control has to be written to select
Users: http://roccat.sourceforge.net which profile to read.
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The mouse can store 5 profiles which can be switched by the
press of a button. A profile is split in settings and buttons.
profile_buttons holds information about button layout.
When read, these files return the respective profile buttons.
The returned data is 19 bytes in size.
This file is readonly.
Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: The integer value of this attribute ranges from 0-4.
When read, this attribute returns the number of the profile
that's active when the mouse is powered on.
This file is readonly.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings
......
...@@ -40,8 +40,8 @@ What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid- ...@@ -40,8 +40,8 @@ What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-
Date: Mai 2012 Date: Mai 2012
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
Description: When read, this file returns general data like firmware version. Description: When read, this file returns general data like firmware version.
When written, the device can be reset.
The data is 8 bytes long. The data is 8 bytes long.
This file is readonly.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/macro What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/savu/roccatsavu<minor>/macro
...@@ -74,4 +74,3 @@ Description: The mouse has a Avago ADNS-3090 sensor. ...@@ -74,4 +74,3 @@ Description: The mouse has a Avago ADNS-3090 sensor.
This file allows reading and writing of the mouse sensors registers. This file allows reading and writing of the mouse sensors registers.
The data has to be 4 bytes long. The data has to be 4 bytes long.
Users: http://roccat.sourceforge.net Users: http://roccat.sourceforge.net
...@@ -196,6 +196,17 @@ EV_MSC: ...@@ -196,6 +196,17 @@ EV_MSC:
EV_MSC events are used for input and output events that do not fall under other EV_MSC events are used for input and output events that do not fall under other
categories. categories.
A few EV_MSC codes have special meaning:
* MSC_TIMESTAMP:
- Used to report the number of microseconds since the last reset. This event
should be coded as an uint32 value, which is allowed to wrap around with
no special consequence. It is assumed that the time difference between two
consecutive events is reliable on a reasonable time scale (hours).
A reset to zero can happen, in which case the time since the last event is
unknown. If the device does not provide this information, the driver must
not provide it to user space.
EV_LED: EV_LED:
---------- ----------
EV_LED events are used for input and output to set and query the state of EV_LED events are used for input and output to set and query the state of
......
...@@ -265,6 +265,15 @@ config HID_GYRATION ...@@ -265,6 +265,15 @@ config HID_GYRATION
---help--- ---help---
Support for Gyration remote control. Support for Gyration remote control.
config HID_ICADE
tristate "ION iCade arcade controller"
depends on BT_HIDP
---help---
Support for the ION iCade arcade controller to work as a joystick.
To compile this driver as a module, choose M here: the
module will be called hid-icade.
config HID_TWINHAN config HID_TWINHAN
tristate "Twinhan IR remote control" tristate "Twinhan IR remote control"
depends on USB_HID depends on USB_HID
...@@ -728,4 +737,6 @@ endif # HID ...@@ -728,4 +737,6 @@ endif # HID
source "drivers/hid/usbhid/Kconfig" source "drivers/hid/usbhid/Kconfig"
source "drivers/hid/i2c-hid/Kconfig"
endmenu endmenu
...@@ -52,6 +52,7 @@ obj-$(CONFIG_HID_GYRATION) += hid-gyration.o ...@@ -52,6 +52,7 @@ obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o obj-$(CONFIG_HID_HOLTEK) += hid-holtek-kbd.o
obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o
obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o obj-$(CONFIG_HID_HYPERV_MOUSE) += hid-hyperv.o
obj-$(CONFIG_HID_ICADE) += hid-icade.o
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
obj-$(CONFIG_HID_KYE) += hid-kye.o obj-$(CONFIG_HID_KYE) += hid-kye.o
...@@ -93,8 +94,8 @@ obj-$(CONFIG_HID_PRIMAX) += hid-primax.o ...@@ -93,8 +94,8 @@ obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o
obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \
hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-pyra.o \ hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-lua.o \
hid-roccat-savu.o hid-roccat-pyra.o hid-roccat-savu.o
obj-$(CONFIG_HID_SAITEK) += hid-saitek.o obj-$(CONFIG_HID_SAITEK) += hid-saitek.o
obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o
obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o
...@@ -118,3 +119,4 @@ obj-$(CONFIG_USB_HID) += usbhid/ ...@@ -118,3 +119,4 @@ obj-$(CONFIG_USB_HID) += usbhid/
obj-$(CONFIG_USB_MOUSE) += usbhid/ obj-$(CONFIG_USB_MOUSE) += usbhid/
obj-$(CONFIG_USB_KBD) += usbhid/ obj-$(CONFIG_USB_KBD) += usbhid/
obj-$(CONFIG_I2C_HID) += i2c-hid/
...@@ -439,7 +439,8 @@ static const struct hid_device_id apple_devices[] = { ...@@ -439,7 +439,8 @@ static const struct hid_device_id apple_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS), { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
APPLE_RDESC_JIS }, APPLE_RDESC_JIS },
......
...@@ -92,6 +92,7 @@ EXPORT_SYMBOL_GPL(hid_register_report); ...@@ -92,6 +92,7 @@ EXPORT_SYMBOL_GPL(hid_register_report);
static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
{ {
struct hid_field *field; struct hid_field *field;
int i;
if (report->maxfield == HID_MAX_FIELDS) { if (report->maxfield == HID_MAX_FIELDS) {
hid_err(report->device, "too many fields in report\n"); hid_err(report->device, "too many fields in report\n");
...@@ -110,6 +111,9 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned ...@@ -110,6 +111,9 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
field->value = (s32 *)(field->usage + usages); field->value = (s32 *)(field->usage + usages);
field->report = report; field->report = report;
for (i = 0; i < usages; i++)
field->usage[i].usage_index = i;
return field; return field;
} }
...@@ -315,6 +319,7 @@ static s32 item_sdata(struct hid_item *item) ...@@ -315,6 +319,7 @@ static s32 item_sdata(struct hid_item *item)
static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
{ {
__u32 raw_value;
switch (item->tag) { switch (item->tag) {
case HID_GLOBAL_ITEM_TAG_PUSH: case HID_GLOBAL_ITEM_TAG_PUSH:
...@@ -365,7 +370,14 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) ...@@ -365,7 +370,14 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
return 0; return 0;
case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT: case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
parser->global.unit_exponent = item_sdata(item); /* Units exponent negative numbers are given through a
* two's complement.
* See "6.2.2.7 Global Items" for more information. */
raw_value = item_udata(item);
if (!(raw_value & 0xfffffff0))
parser->global.unit_exponent = hid_snto32(raw_value, 4);
else
parser->global.unit_exponent = raw_value;
return 0; return 0;
case HID_GLOBAL_ITEM_TAG_UNIT: case HID_GLOBAL_ITEM_TAG_UNIT:
...@@ -713,7 +725,12 @@ static int hid_scan_report(struct hid_device *hid) ...@@ -713,7 +725,12 @@ static int hid_scan_report(struct hid_device *hid)
hid_scan_usage(hid, u); hid_scan_usage(hid, u);
break; break;
} }
} } else if (page == HID_UP_SENSOR &&
item.type == HID_ITEM_TYPE_MAIN &&
item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION &&
(item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL &&
hid->bus == BUS_USB)
hid->group = HID_GROUP_SENSOR_HUB;
} }
return 0; return 0;
...@@ -865,6 +882,12 @@ static s32 snto32(__u32 value, unsigned n) ...@@ -865,6 +882,12 @@ static s32 snto32(__u32 value, unsigned n)
return value & (1 << (n - 1)) ? value | (-1 << n) : value; return value & (1 << (n - 1)) ? value | (-1 << n) : value;
} }
s32 hid_snto32(__u32 value, unsigned n)
{
return snto32(value, n);
}
EXPORT_SYMBOL_GPL(hid_snto32);
/* /*
* Convert a signed 32-bit integer to a signed n-bit integer. * Convert a signed 32-bit integer to a signed n-bit integer.
*/ */
...@@ -1465,6 +1488,10 @@ EXPORT_SYMBOL_GPL(hid_disconnect); ...@@ -1465,6 +1488,10 @@ EXPORT_SYMBOL_GPL(hid_disconnect);
* there is a proper autodetection and autoloading in place (based on presence * there is a proper autodetection and autoloading in place (based on presence
* of HID_DG_CONTACTID), so those devices don't need to be added to this list, * of HID_DG_CONTACTID), so those devices don't need to be added to this list,
* as we are doing the right thing in hid_scan_usage(). * as we are doing the right thing in hid_scan_usage().
*
* Autodetection for (USB) HID sensor hubs exists too. If a collection of type
* physical is found inside a usage page of type sensor, hid-sensor-hub will be
* used as a driver. See hid_scan_report().
*/ */
static const struct hid_device_id hid_have_special_driver[] = { static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
...@@ -1538,6 +1565,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1538,6 +1565,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
...@@ -1571,10 +1599,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1571,10 +1599,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) }, { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_1020) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_09FA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_1020) },
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_09FA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) }, { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
...@@ -1658,6 +1683,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1658,6 +1683,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) }, { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
...@@ -1672,7 +1698,6 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1672,7 +1698,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_SENSOR_HUB_7014) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) },
...@@ -2150,8 +2175,13 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { ...@@ -2150,8 +2175,13 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
{ } { }
}; };
static bool hid_ignore(struct hid_device *hdev) bool hid_ignore(struct hid_device *hdev)
{ {
if (hdev->quirks & HID_QUIRK_NO_IGNORE)
return false;
if (hdev->quirks & HID_QUIRK_IGNORE)
return true;
switch (hdev->vendor) { switch (hdev->vendor) {
case USB_VENDOR_ID_CODEMERCS: case USB_VENDOR_ID_CODEMERCS:
/* ignore all Code Mercenaries IOWarrior devices */ /* ignore all Code Mercenaries IOWarrior devices */
...@@ -2188,7 +2218,16 @@ static bool hid_ignore(struct hid_device *hdev) ...@@ -2188,7 +2218,16 @@ static bool hid_ignore(struct hid_device *hdev)
if (hdev->product == USB_DEVICE_ID_JESS_YUREX && if (hdev->product == USB_DEVICE_ID_JESS_YUREX &&
hdev->type == HID_TYPE_USBNONE) hdev->type == HID_TYPE_USBNONE)
return true; return true;
break; break;
case USB_VENDOR_ID_DWAV:
/* These are handled by usbtouchscreen. hdev->type is probably
* HID_TYPE_USBNONE, but we say !HID_TYPE_USBMOUSE to match
* usbtouchscreen. */
if ((hdev->product == USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER ||
hdev->product == USB_DEVICE_ID_DWAV_TOUCHCONTROLLER) &&
hdev->type != HID_TYPE_USBMOUSE)
return true;
break;
} }
if (hdev->type == HID_TYPE_USBMOUSE && if (hdev->type == HID_TYPE_USBMOUSE &&
...@@ -2197,6 +2236,7 @@ static bool hid_ignore(struct hid_device *hdev) ...@@ -2197,6 +2236,7 @@ static bool hid_ignore(struct hid_device *hdev)
return !!hid_match_id(hdev, hid_ignore_list); return !!hid_match_id(hdev, hid_ignore_list);
} }
EXPORT_SYMBOL_GPL(hid_ignore);
int hid_add_device(struct hid_device *hdev) int hid_add_device(struct hid_device *hdev)
{ {
...@@ -2208,8 +2248,7 @@ int hid_add_device(struct hid_device *hdev) ...@@ -2208,8 +2248,7 @@ int hid_add_device(struct hid_device *hdev)
/* we need to kill them here, otherwise they will stay allocated to /* we need to kill them here, otherwise they will stay allocated to
* wait for coming driver */ * wait for coming driver */
if (!(hdev->quirks & HID_QUIRK_NO_IGNORE) if (hid_ignore(hdev))
&& (hid_ignore(hdev) || (hdev->quirks & HID_QUIRK_IGNORE)))
return -ENODEV; return -ENODEV;
/* /*
......
/*
* ION iCade input driver
*
* Copyright (c) 2012 Bastien Nocera <hadess@hadess.net>
* Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
/*
* ↑ A C Y L
* ← →
* ↓ B X Z R
*
*
* UP ON,OFF = w,e
* RT ON,OFF = d,c
* DN ON,OFF = x,z
* LT ON,OFF = a,q
* A ON,OFF = y,t
* B ON,OFF = h,r
* C ON,OFF = u,f
* X ON,OFF = j,n
* Y ON,OFF = i,m
* Z ON,OFF = k,p
* L ON,OFF = o,g
* R ON,OFF = l,v
*/
/* The translation code uses HID usage instead of input layer
* keys. This code generates a lookup table that makes
* translation quick.
*
* #include <linux/input.h>
* #include <stdio.h>
* #include <assert.h>
*
* #define unk KEY_UNKNOWN
*
* < copy of hid_keyboard[] from hid-input.c >
*
* struct icade_key_translation {
* int from;
* const char *to;
* int press;
* };
*
* static const struct icade_key_translation icade_keys[] = {
* { KEY_W, "KEY_UP", 1 },
* { KEY_E, "KEY_UP", 0 },
* { KEY_D, "KEY_RIGHT", 1 },
* { KEY_C, "KEY_RIGHT", 0 },
* { KEY_X, "KEY_DOWN", 1 },
* { KEY_Z, "KEY_DOWN", 0 },
* { KEY_A, "KEY_LEFT", 1 },
* { KEY_Q, "KEY_LEFT", 0 },
* { KEY_Y, "BTN_A", 1 },
* { KEY_T, "BTN_A", 0 },
* { KEY_H, "BTN_B", 1 },
* { KEY_R, "BTN_B", 0 },
* { KEY_U, "BTN_C", 1 },
* { KEY_F, "BTN_C", 0 },
* { KEY_J, "BTN_X", 1 },
* { KEY_N, "BTN_X", 0 },
* { KEY_I, "BTN_Y", 1 },
* { KEY_M, "BTN_Y", 0 },
* { KEY_K, "BTN_Z", 1 },
* { KEY_P, "BTN_Z", 0 },
* { KEY_O, "BTN_THUMBL", 1 },
* { KEY_G, "BTN_THUMBL", 0 },
* { KEY_L, "BTN_THUMBR", 1 },
* { KEY_V, "BTN_THUMBR", 0 },
*
* { }
* };
*
* static int
* usage_for_key (int key)
* {
* int i;
* for (i = 0; i < 256; i++) {
* if (hid_keyboard[i] == key)
* return i;
* }
* assert(0);
* }
*
* int main (int argc, char **argv)
* {
* const struct icade_key_translation *trans;
* int max_usage = 0;
*
* for (trans = icade_keys; trans->from; trans++) {
* int usage = usage_for_key (trans->from);
* max_usage = usage > max_usage ? usage : max_usage;
* }
*
* printf ("#define ICADE_MAX_USAGE %d\n\n", max_usage);
* printf ("struct icade_key {\n");
* printf ("\tu16 to;\n");
* printf ("\tu8 press:1;\n");
* printf ("};\n\n");
* printf ("static const struct icade_key "
* "icade_usage_table[%d] = {\n", max_usage + 1);
* for (trans = icade_keys; trans->from; trans++) {
* printf ("\t[%d] = { %s, %d },\n",
* usage_for_key (trans->from), trans->to, trans->press);
* }
* printf ("};\n");
*
* return 0;
* }
*/
#define ICADE_MAX_USAGE 29
struct icade_key {
u16 to;
u8 press:1;
};
static const struct icade_key icade_usage_table[30] = {
[26] = { KEY_UP, 1 },
[8] = { KEY_UP, 0 },
[7] = { KEY_RIGHT, 1 },
[6] = { KEY_RIGHT, 0 },
[27] = { KEY_DOWN, 1 },
[29] = { KEY_DOWN, 0 },
[4] = { KEY_LEFT, 1 },
[20] = { KEY_LEFT, 0 },
[28] = { BTN_A, 1 },
[23] = { BTN_A, 0 },
[11] = { BTN_B, 1 },
[21] = { BTN_B, 0 },
[24] = { BTN_C, 1 },
[9] = { BTN_C, 0 },
[13] = { BTN_X, 1 },
[17] = { BTN_X, 0 },
[12] = { BTN_Y, 1 },
[16] = { BTN_Y, 0 },
[14] = { BTN_Z, 1 },
[19] = { BTN_Z, 0 },
[18] = { BTN_THUMBL, 1 },
[10] = { BTN_THUMBL, 0 },
[15] = { BTN_THUMBR, 1 },
[25] = { BTN_THUMBR, 0 },
};
static const struct icade_key *icade_find_translation(u16 from)
{
if (from < 0 || from > ICADE_MAX_USAGE)
return NULL;
return &icade_usage_table[from];
}
static int icade_event(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
const struct icade_key *trans;
if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
!usage->type)
return 0;
/* We ignore the fake key up, and act only on key down */
if (!value)
return 1;
trans = icade_find_translation(usage->hid & HID_USAGE);
if (!trans)
return 1;
input_event(field->hidinput->input, usage->type,
trans->to, trans->press);
return 1;
}
static int icade_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
const struct icade_key *trans;
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD) {
trans = icade_find_translation(usage->hid & HID_USAGE);
if (!trans)
return -1;
hid_map_usage(hi, usage, bit, max, EV_KEY, trans->to);
set_bit(trans->to, hi->input->keybit);
return 1;
}
/* ignore others */
return -1;
}
static int icade_input_mapped(struct hid_device *hdev, struct hid_input *hi,
struct hid_field *field, struct hid_usage *usage,
unsigned long **bit, int *max)
{
if (usage->type == EV_KEY)
set_bit(usage->type, hi->input->evbit);
return -1;
}
static const struct hid_device_id icade_devices[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
{ }
};
MODULE_DEVICE_TABLE(hid, icade_devices);
static struct hid_driver icade_driver = {
.name = "icade",
.id_table = icade_devices,
.event = icade_event,
.input_mapped = icade_input_mapped,
.input_mapping = icade_input_mapping,
};
static int __init icade_init(void)
{
int ret;
ret = hid_register_driver(&icade_driver);
if (ret)
pr_err("can't register icade driver\n");
return ret;
}
static void __exit icade_exit(void)
{
hid_unregister_driver(&icade_driver);
}
module_init(icade_init);
module_exit(icade_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
MODULE_DESCRIPTION("ION iCade input driver");
...@@ -257,6 +257,7 @@ ...@@ -257,6 +257,7 @@
#define USB_VENDOR_ID_DWAV 0x0eef #define USB_VENDOR_ID_DWAV 0x0eef
#define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001
#define USB_DEVICE_ID_DWAV_TOUCHCONTROLLER 0x0002
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D 0x480d #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D 0x480d
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E 0x480e #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E 0x480e
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207 0x7207 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7207 0x7207
...@@ -423,6 +424,9 @@ ...@@ -423,6 +424,9 @@
#define USB_VENDOR_ID_ILITEK 0x222a #define USB_VENDOR_ID_ILITEK 0x222a
#define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001 #define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001
#define USB_VENDOR_ID_ION 0x15e4
#define USB_DEVICE_ID_ICADE 0x0132
#define USB_VENDOR_ID_HOLTEK 0x1241 #define USB_VENDOR_ID_HOLTEK 0x1241
#define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015 #define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015
...@@ -432,11 +436,6 @@ ...@@ -432,11 +436,6 @@
#define USB_VENDOR_ID_IMATION 0x0718 #define USB_VENDOR_ID_IMATION 0x0718
#define USB_DEVICE_ID_DISC_STAKKA 0xd000 #define USB_DEVICE_ID_DISC_STAKKA 0xd000
#define USB_VENDOR_ID_INTEL_8086 0x8086
#define USB_VENDOR_ID_INTEL_8087 0x8087
#define USB_DEVICE_ID_SENSOR_HUB_1020 0x1020
#define USB_DEVICE_ID_SENSOR_HUB_09FA 0x09FA
#define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615 #define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615
#define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070 #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070
...@@ -603,6 +602,7 @@ ...@@ -603,6 +602,7 @@
#define USB_VENDOR_ID_NOVATEK 0x0603 #define USB_VENDOR_ID_NOVATEK 0x0603
#define USB_DEVICE_ID_NOVATEK_PCT 0x0600 #define USB_DEVICE_ID_NOVATEK_PCT 0x0600
#define USB_DEVICE_ID_NOVATEK_MOUSE 0x1602
#define USB_VENDOR_ID_NTRIG 0x1b96 #define USB_VENDOR_ID_NTRIG 0x1b96
#define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001
...@@ -677,7 +677,9 @@ ...@@ -677,7 +677,9 @@
#define USB_DEVICE_ID_ROCCAT_ISKU 0x319c #define USB_DEVICE_ID_ROCCAT_ISKU 0x319c
#define USB_DEVICE_ID_ROCCAT_KONE 0x2ced #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced
#define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51 #define USB_DEVICE_ID_ROCCAT_KONEPLUS 0x2d51
#define USB_DEVICE_ID_ROCCAT_KONEXTD 0x2e22
#define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50 #define USB_DEVICE_ID_ROCCAT_KOVAPLUS 0x2d50
#define USB_DEVICE_ID_ROCCAT_LUA 0x2c2e
#define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24
#define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6
#define USB_DEVICE_ID_ROCCAT_SAVU 0x2d5a #define USB_DEVICE_ID_ROCCAT_SAVU 0x2d5a
...@@ -696,6 +698,9 @@ ...@@ -696,6 +698,9 @@
#define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f #define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f
#define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002 #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002
#define USB_VENDOR_ID_SIGMATEL 0x066F
#define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780
#define USB_VENDOR_ID_SKYCABLE 0x1223 #define USB_VENDOR_ID_SKYCABLE 0x1223
#define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07
...@@ -714,7 +719,6 @@ ...@@ -714,7 +719,6 @@
#define USB_VENDOR_ID_STANTUM_STM 0x0483 #define USB_VENDOR_ID_STANTUM_STM 0x0483
#define USB_DEVICE_ID_MTP_STM 0x3261 #define USB_DEVICE_ID_MTP_STM 0x3261
#define USB_DEVICE_ID_SENSOR_HUB_7014 0x7014
#define USB_VENDOR_ID_STANTUM_SITRONIX 0x1403 #define USB_VENDOR_ID_STANTUM_SITRONIX 0x1403
#define USB_DEVICE_ID_MTP_SITRONIX 0x5001 #define USB_DEVICE_ID_MTP_SITRONIX 0x5001
...@@ -762,6 +766,9 @@ ...@@ -762,6 +766,9 @@
#define USB_VENDOR_ID_TOUCHPACK 0x1bfd #define USB_VENDOR_ID_TOUCHPACK 0x1bfd
#define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688 #define USB_DEVICE_ID_TOUCHPACK_RTS 0x1688
#define USB_VENDOR_ID_TPV 0x25aa
#define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN 0x8883
#define USB_VENDOR_ID_TURBOX 0x062a #define USB_VENDOR_ID_TURBOX 0x062a
#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 #define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201
#define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100 #define USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART 0x7100
......
...@@ -192,7 +192,6 @@ static int hidinput_setkeycode(struct input_dev *dev, ...@@ -192,7 +192,6 @@ static int hidinput_setkeycode(struct input_dev *dev,
return -EINVAL; return -EINVAL;
} }
/** /**
* hidinput_calc_abs_res - calculate an absolute axis resolution * hidinput_calc_abs_res - calculate an absolute axis resolution
* @field: the HID report field to calculate resolution for * @field: the HID report field to calculate resolution for
...@@ -208,7 +207,7 @@ static int hidinput_setkeycode(struct input_dev *dev, ...@@ -208,7 +207,7 @@ static int hidinput_setkeycode(struct input_dev *dev,
* Only exponent 1 length units are processed. Centimeters and inches are * Only exponent 1 length units are processed. Centimeters and inches are
* converted to millimeters. Degrees are converted to radians. * converted to millimeters. Degrees are converted to radians.
*/ */
static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
{ {
__s32 unit_exponent = field->unit_exponent; __s32 unit_exponent = field->unit_exponent;
__s32 logical_extents = field->logical_maximum - __s32 logical_extents = field->logical_maximum -
...@@ -229,17 +228,29 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) ...@@ -229,17 +228,29 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
case ABS_X: case ABS_X:
case ABS_Y: case ABS_Y:
case ABS_Z: case ABS_Z:
if (field->unit == 0x11) { /* If centimeters */ case ABS_MT_POSITION_X:
case ABS_MT_POSITION_Y:
case ABS_MT_TOOL_X:
case ABS_MT_TOOL_Y:
case ABS_MT_TOUCH_MAJOR:
case ABS_MT_TOUCH_MINOR:
if (field->unit & 0xffffff00) /* Not a length */
return 0;
unit_exponent += hid_snto32(field->unit >> 4, 4) - 1;
switch (field->unit & 0xf) {
case 0x1: /* If centimeters */
/* Convert to millimeters */ /* Convert to millimeters */
unit_exponent += 1; unit_exponent += 1;
} else if (field->unit == 0x13) { /* If inches */ break;
case 0x3: /* If inches */
/* Convert to millimeters */ /* Convert to millimeters */
prev = physical_extents; prev = physical_extents;
physical_extents *= 254; physical_extents *= 254;
if (physical_extents < prev) if (physical_extents < prev)
return 0; return 0;
unit_exponent -= 1; unit_exponent -= 1;
} else { break;
default:
return 0; return 0;
} }
break; break;
...@@ -281,8 +292,9 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) ...@@ -281,8 +292,9 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
} }
/* Calculate resolution */ /* Calculate resolution */
return logical_extents / physical_extents; return DIV_ROUND_CLOSEST(logical_extents, physical_extents);
} }
EXPORT_SYMBOL_GPL(hidinput_calc_abs_res);
#ifdef CONFIG_HID_BATTERY_STRENGTH #ifdef CONFIG_HID_BATTERY_STRENGTH
static enum power_supply_property hidinput_battery_props[] = { static enum power_supply_property hidinput_battery_props[] = {
...@@ -298,6 +310,9 @@ static enum power_supply_property hidinput_battery_props[] = { ...@@ -298,6 +310,9 @@ static enum power_supply_property hidinput_battery_props[] = {
#define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */ #define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */
static const struct hid_device_id hid_battery_quirks[] = { static const struct hid_device_id hid_battery_quirks[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI), USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
...@@ -502,9 +517,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel ...@@ -502,9 +517,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
if (code <= 0xf) if (code <= 0xf)
code += BTN_JOYSTICK; code += BTN_JOYSTICK;
else else
code += BTN_TRIGGER_HAPPY; code += BTN_TRIGGER_HAPPY - 0x10;
break;
case HID_GD_GAMEPAD:
if (code <= 0xf)
code += BTN_GAMEPAD;
else
code += BTN_TRIGGER_HAPPY - 0x10;
break; break;
case HID_GD_GAMEPAD: code += BTN_GAMEPAD; break;
default: default:
switch (field->physical) { switch (field->physical) {
case HID_GD_MOUSE: case HID_GD_MOUSE:
...@@ -1146,6 +1166,38 @@ static void report_features(struct hid_device *hid) ...@@ -1146,6 +1166,38 @@ static void report_features(struct hid_device *hid)
} }
} }
static struct hid_input *hidinput_allocate(struct hid_device *hid)
{
struct hid_input *hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL);
struct input_dev *input_dev = input_allocate_device();
if (!hidinput || !input_dev) {
kfree(hidinput);
input_free_device(input_dev);
hid_err(hid, "Out of memory during hid input probe\n");
return NULL;
}
input_set_drvdata(input_dev, hid);
input_dev->event = hid->ll_driver->hidinput_input_event;
input_dev->open = hidinput_open;
input_dev->close = hidinput_close;
input_dev->setkeycode = hidinput_setkeycode;
input_dev->getkeycode = hidinput_getkeycode;
input_dev->name = hid->name;
input_dev->phys = hid->phys;
input_dev->uniq = hid->uniq;
input_dev->id.bustype = hid->bus;
input_dev->id.vendor = hid->vendor;
input_dev->id.product = hid->product;
input_dev->id.version = hid->version;
input_dev->dev.parent = hid->dev.parent;
hidinput->input = input_dev;
list_add_tail(&hidinput->list, &hid->inputs);
return hidinput;
}
/* /*
* Register the input device; print a message. * Register the input device; print a message.
* Configure the input layer interface * Configure the input layer interface
...@@ -1157,7 +1209,6 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) ...@@ -1157,7 +1209,6 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
struct hid_driver *drv = hid->driver; struct hid_driver *drv = hid->driver;
struct hid_report *report; struct hid_report *report;
struct hid_input *hidinput = NULL; struct hid_input *hidinput = NULL;
struct input_dev *input_dev;
int i, j, k; int i, j, k;
INIT_LIST_HEAD(&hid->inputs); INIT_LIST_HEAD(&hid->inputs);
...@@ -1188,33 +1239,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) ...@@ -1188,33 +1239,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
continue; continue;
if (!hidinput) { if (!hidinput) {
hidinput = kzalloc(sizeof(*hidinput), GFP_KERNEL); hidinput = hidinput_allocate(hid);
input_dev = input_allocate_device(); if (!hidinput)
if (!hidinput || !input_dev) {
kfree(hidinput);
input_free_device(input_dev);
hid_err(hid, "Out of memory during hid input probe\n");
goto out_unwind; goto out_unwind;
}
input_set_drvdata(input_dev, hid);
input_dev->event =
hid->ll_driver->hidinput_input_event;
input_dev->open = hidinput_open;
input_dev->close = hidinput_close;
input_dev->setkeycode = hidinput_setkeycode;
input_dev->getkeycode = hidinput_getkeycode;
input_dev->name = hid->name;
input_dev->phys = hid->phys;
input_dev->uniq = hid->uniq;
input_dev->id.bustype = hid->bus;
input_dev->id.vendor = hid->vendor;
input_dev->id.product = hid->product;
input_dev->id.version = hid->version;
input_dev->dev.parent = hid->dev.parent;
hidinput->input = input_dev;
list_add_tail(&hidinput->list, &hid->inputs);
} }
for (i = 0; i < report->maxfield; i++) for (i = 0; i < report->maxfield; i++)
......
...@@ -52,11 +52,14 @@ MODULE_LICENSE("GPL"); ...@@ -52,11 +52,14 @@ MODULE_LICENSE("GPL");
#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6) #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6)
#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8) #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8)
#define MT_QUIRK_NO_AREA (1 << 9) #define MT_QUIRK_NO_AREA (1 << 9)
#define MT_QUIRK_IGNORE_DUPLICATES (1 << 10)
#define MT_QUIRK_HOVERING (1 << 11)
struct mt_slot { struct mt_slot {
__s32 x, y, p, w, h; __s32 x, y, cx, cy, p, w, h;
__s32 contactid; /* the device ContactID assigned to this slot */ __s32 contactid; /* the device ContactID assigned to this slot */
bool touch_state; /* is the touch valid? */ bool touch_state; /* is the touch valid? */
bool inrange_state; /* is the finger in proximity of the sensor? */
}; };
struct mt_class { struct mt_class {
...@@ -121,6 +124,7 @@ struct mt_device { ...@@ -121,6 +124,7 @@ struct mt_device {
#define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109 #define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109
#define MT_DEFAULT_MAXCONTACT 10 #define MT_DEFAULT_MAXCONTACT 10
#define MT_MAX_MAXCONTACT 250
#define MT_USB_DEVICE(v, p) HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p) #define MT_USB_DEVICE(v, p) HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p)
#define MT_BT_DEVICE(v, p) HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p) #define MT_BT_DEVICE(v, p) HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p)
...@@ -282,11 +286,26 @@ static void mt_feature_mapping(struct hid_device *hdev, ...@@ -282,11 +286,26 @@ static void mt_feature_mapping(struct hid_device *hdev,
case HID_DG_CONTACTMAX: case HID_DG_CONTACTMAX:
td->maxcontact_report_id = field->report->id; td->maxcontact_report_id = field->report->id;
td->maxcontacts = field->value[0]; td->maxcontacts = field->value[0];
if (!td->maxcontacts &&
field->logical_maximum <= MT_MAX_MAXCONTACT)
td->maxcontacts = field->logical_maximum;
if (td->mtclass.maxcontacts) if (td->mtclass.maxcontacts)
/* check if the maxcontacts is given by the class */ /* check if the maxcontacts is given by the class */
td->maxcontacts = td->mtclass.maxcontacts; td->maxcontacts = td->mtclass.maxcontacts;
break; break;
case 0xff0000c5:
if (field->report_count == 256 && field->report_size == 8) {
/* Win 8 devices need special quirks */
__s32 *quirks = &td->mtclass.quirks;
*quirks |= MT_QUIRK_ALWAYS_VALID;
*quirks |= MT_QUIRK_IGNORE_DUPLICATES;
*quirks |= MT_QUIRK_HOVERING;
*quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
*quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
*quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE;
}
break;
} }
} }
...@@ -297,6 +316,7 @@ static void set_abs(struct input_dev *input, unsigned int code, ...@@ -297,6 +316,7 @@ static void set_abs(struct input_dev *input, unsigned int code,
int fmax = field->logical_maximum; int fmax = field->logical_maximum;
int fuzz = snratio ? (fmax - fmin) / snratio : 0; int fuzz = snratio ? (fmax - fmin) / snratio : 0;
input_set_abs_params(input, code, fmin, fmax, fuzz, 0); input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
input_abs_set_res(input, code, hidinput_calc_abs_res(field, code));
} }
static void mt_store_field(struct hid_usage *usage, struct mt_device *td, static void mt_store_field(struct hid_usage *usage, struct mt_device *td,
...@@ -317,6 +337,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -317,6 +337,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
struct mt_device *td = hid_get_drvdata(hdev); struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass; struct mt_class *cls = &td->mtclass;
int code; int code;
struct hid_usage *prev_usage = NULL;
/* Only map fields from TouchScreen or TouchPad collections. /* Only map fields from TouchScreen or TouchPad collections.
* We need to ignore fields that belong to other collections * We need to ignore fields that belong to other collections
...@@ -339,23 +360,42 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -339,23 +360,42 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
if (field->physical == HID_DG_STYLUS) if (field->physical == HID_DG_STYLUS)
return -1; return -1;
if (usage->usage_index)
prev_usage = &field->usage[usage->usage_index - 1];
switch (usage->hid & HID_USAGE_PAGE) { switch (usage->hid & HID_USAGE_PAGE) {
case HID_UP_GENDESK: case HID_UP_GENDESK:
switch (usage->hid) { switch (usage->hid) {
case HID_GD_X: case HID_GD_X:
hid_map_usage(hi, usage, bit, max, if (prev_usage && (prev_usage->hid == usage->hid)) {
hid_map_usage(hi, usage, bit, max,
EV_ABS, ABS_MT_TOOL_X);
set_abs(hi->input, ABS_MT_TOOL_X, field,
cls->sn_move);
} else {
hid_map_usage(hi, usage, bit, max,
EV_ABS, ABS_MT_POSITION_X); EV_ABS, ABS_MT_POSITION_X);
set_abs(hi->input, ABS_MT_POSITION_X, field, set_abs(hi->input, ABS_MT_POSITION_X, field,
cls->sn_move); cls->sn_move);
}
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
td->last_field_index = field->index; td->last_field_index = field->index;
return 1; return 1;
case HID_GD_Y: case HID_GD_Y:
hid_map_usage(hi, usage, bit, max, if (prev_usage && (prev_usage->hid == usage->hid)) {
hid_map_usage(hi, usage, bit, max,
EV_ABS, ABS_MT_TOOL_Y);
set_abs(hi->input, ABS_MT_TOOL_Y, field,
cls->sn_move);
} else {
hid_map_usage(hi, usage, bit, max,
EV_ABS, ABS_MT_POSITION_Y); EV_ABS, ABS_MT_POSITION_Y);
set_abs(hi->input, ABS_MT_POSITION_Y, field, set_abs(hi->input, ABS_MT_POSITION_Y, field,
cls->sn_move); cls->sn_move);
}
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
td->last_field_index = field->index; td->last_field_index = field->index;
return 1; return 1;
...@@ -365,6 +405,12 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -365,6 +405,12 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case HID_UP_DIGITIZER: case HID_UP_DIGITIZER:
switch (usage->hid) { switch (usage->hid) {
case HID_DG_INRANGE: case HID_DG_INRANGE:
if (cls->quirks & MT_QUIRK_HOVERING) {
hid_map_usage(hi, usage, bit, max,
EV_ABS, ABS_MT_DISTANCE);
input_set_abs_params(hi->input,
ABS_MT_DISTANCE, 0, 1, 0, 0);
}
mt_store_field(usage, td, hi); mt_store_field(usage, td, hi);
td->last_field_index = field->index; td->last_field_index = field->index;
return 1; return 1;
...@@ -477,18 +523,26 @@ static int mt_compute_slot(struct mt_device *td, struct input_dev *input) ...@@ -477,18 +523,26 @@ static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
*/ */
static void mt_complete_slot(struct mt_device *td, struct input_dev *input) static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
{ {
if (td->curvalid) { if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
int slotnum = mt_compute_slot(td, input); int slotnum = mt_compute_slot(td, input);
struct mt_slot *s = &td->curdata; struct mt_slot *s = &td->curdata;
struct input_mt *mt = input->mt;
if (slotnum < 0 || slotnum >= td->maxcontacts) if (slotnum < 0 || slotnum >= td->maxcontacts)
return; return;
if ((td->mtclass.quirks & MT_QUIRK_IGNORE_DUPLICATES) && mt) {
struct input_mt_slot *slot = &mt->slots[slotnum];
if (input_mt_is_active(slot) &&
input_mt_is_used(mt, slot))
return;
}
input_mt_slot(input, slotnum); input_mt_slot(input, slotnum);
input_mt_report_slot_state(input, MT_TOOL_FINGER, input_mt_report_slot_state(input, MT_TOOL_FINGER,
s->touch_state); s->touch_state || s->inrange_state);
if (s->touch_state) { if (s->touch_state || s->inrange_state) {
/* this finger is on the screen */ /* this finger is in proximity of the sensor */
int wide = (s->w > s->h); int wide = (s->w > s->h);
/* divided by two to match visual scale of touch */ /* divided by two to match visual scale of touch */
int major = max(s->w, s->h) >> 1; int major = max(s->w, s->h) >> 1;
...@@ -496,6 +550,10 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input) ...@@ -496,6 +550,10 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x); input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x);
input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y);
input_event(input, EV_ABS, ABS_MT_TOOL_X, s->cx);
input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
input_event(input, EV_ABS, ABS_MT_DISTANCE,
!s->touch_state);
input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
...@@ -526,10 +584,10 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, ...@@ -526,10 +584,10 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
if (hid->claimed & HID_CLAIMED_INPUT) { if (hid->claimed & HID_CLAIMED_INPUT) {
switch (usage->hid) { switch (usage->hid) {
case HID_DG_INRANGE: case HID_DG_INRANGE:
if (quirks & MT_QUIRK_ALWAYS_VALID) if (quirks & MT_QUIRK_VALID_IS_INRANGE)
td->curvalid = true;
else if (quirks & MT_QUIRK_VALID_IS_INRANGE)
td->curvalid = value; td->curvalid = value;
if (quirks & MT_QUIRK_HOVERING)
td->curdata.inrange_state = value;
break; break;
case HID_DG_TIPSWITCH: case HID_DG_TIPSWITCH:
if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) if (quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
...@@ -547,10 +605,16 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, ...@@ -547,10 +605,16 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
td->curdata.p = value; td->curdata.p = value;
break; break;
case HID_GD_X: case HID_GD_X:
td->curdata.x = value; if (usage->code == ABS_MT_TOOL_X)
td->curdata.cx = value;
else
td->curdata.x = value;
break; break;
case HID_GD_Y: case HID_GD_Y:
td->curdata.y = value; if (usage->code == ABS_MT_TOOL_Y)
td->curdata.cy = value;
else
td->curdata.y = value;
break; break;
case HID_DG_WIDTH: case HID_DG_WIDTH:
td->curdata.w = value; td->curdata.w = value;
...@@ -575,12 +639,15 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, ...@@ -575,12 +639,15 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
return 0; return 0;
} }
if (usage->hid == td->last_slot_field) if (usage->usage_index + 1 == field->report_count) {
mt_complete_slot(td, field->hidinput->input); /* we only take into account the last report. */
if (usage->hid == td->last_slot_field)
mt_complete_slot(td, field->hidinput->input);
if (field->index == td->last_field_index if (field->index == td->last_field_index
&& td->num_received >= td->num_expected) && td->num_received >= td->num_expected)
mt_sync_frame(td, field->hidinput->input); mt_sync_frame(td, field->hidinput->input);
}
} }
......
...@@ -167,7 +167,7 @@ static ssize_t isku_sysfs_write_ ## thingy(struct file *fp, struct kobject *kobj ...@@ -167,7 +167,7 @@ static ssize_t isku_sysfs_write_ ## thingy(struct file *fp, struct kobject *kobj
loff_t off, size_t count) \ loff_t off, size_t count) \
{ \ { \
return isku_sysfs_write(fp, kobj, buf, off, count, \ return isku_sysfs_write(fp, kobj, buf, off, count, \
sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \ ISKU_SIZE_ ## THINGY, ISKU_COMMAND_ ## THINGY); \
} }
#define ISKU_SYSFS_R(thingy, THINGY) \ #define ISKU_SYSFS_R(thingy, THINGY) \
...@@ -176,32 +176,32 @@ static ssize_t isku_sysfs_read_ ## thingy(struct file *fp, struct kobject *kobj, ...@@ -176,32 +176,32 @@ static ssize_t isku_sysfs_read_ ## thingy(struct file *fp, struct kobject *kobj,
loff_t off, size_t count) \ loff_t off, size_t count) \
{ \ { \
return isku_sysfs_read(fp, kobj, buf, off, count, \ return isku_sysfs_read(fp, kobj, buf, off, count, \
sizeof(struct isku_ ## thingy), ISKU_COMMAND_ ## THINGY); \ ISKU_SIZE_ ## THINGY, ISKU_COMMAND_ ## THINGY); \
} }
#define ISKU_SYSFS_RW(thingy, THINGY) \ #define ISKU_SYSFS_RW(thingy, THINGY) \
ISKU_SYSFS_R(thingy, THINGY) \ ISKU_SYSFS_R(thingy, THINGY) \
ISKU_SYSFS_W(thingy, THINGY) ISKU_SYSFS_W(thingy, THINGY)
#define ISKU_BIN_ATTR_RW(thingy) \ #define ISKU_BIN_ATTR_RW(thingy, THINGY) \
{ \ { \
.attr = { .name = #thingy, .mode = 0660 }, \ .attr = { .name = #thingy, .mode = 0660 }, \
.size = sizeof(struct isku_ ## thingy), \ .size = ISKU_SIZE_ ## THINGY, \
.read = isku_sysfs_read_ ## thingy, \ .read = isku_sysfs_read_ ## thingy, \
.write = isku_sysfs_write_ ## thingy \ .write = isku_sysfs_write_ ## thingy \
} }
#define ISKU_BIN_ATTR_R(thingy) \ #define ISKU_BIN_ATTR_R(thingy, THINGY) \
{ \ { \
.attr = { .name = #thingy, .mode = 0440 }, \ .attr = { .name = #thingy, .mode = 0440 }, \
.size = sizeof(struct isku_ ## thingy), \ .size = ISKU_SIZE_ ## THINGY, \
.read = isku_sysfs_read_ ## thingy, \ .read = isku_sysfs_read_ ## thingy, \
} }
#define ISKU_BIN_ATTR_W(thingy) \ #define ISKU_BIN_ATTR_W(thingy, THINGY) \
{ \ { \
.attr = { .name = #thingy, .mode = 0220 }, \ .attr = { .name = #thingy, .mode = 0220 }, \
.size = sizeof(struct isku_ ## thingy), \ .size = ISKU_SIZE_ ## THINGY, \
.write = isku_sysfs_write_ ## thingy \ .write = isku_sysfs_write_ ## thingy \
} }
...@@ -218,21 +218,23 @@ ISKU_SYSFS_RW(last_set, LAST_SET) ...@@ -218,21 +218,23 @@ ISKU_SYSFS_RW(last_set, LAST_SET)
ISKU_SYSFS_W(talk, TALK) ISKU_SYSFS_W(talk, TALK)
ISKU_SYSFS_R(info, INFO) ISKU_SYSFS_R(info, INFO)
ISKU_SYSFS_W(control, CONTROL) ISKU_SYSFS_W(control, CONTROL)
ISKU_SYSFS_W(reset, RESET)
static struct bin_attribute isku_bin_attributes[] = { static struct bin_attribute isku_bin_attributes[] = {
ISKU_BIN_ATTR_RW(macro), ISKU_BIN_ATTR_RW(macro, MACRO),
ISKU_BIN_ATTR_RW(keys_function), ISKU_BIN_ATTR_RW(keys_function, KEYS_FUNCTION),
ISKU_BIN_ATTR_RW(keys_easyzone), ISKU_BIN_ATTR_RW(keys_easyzone, KEYS_EASYZONE),
ISKU_BIN_ATTR_RW(keys_media), ISKU_BIN_ATTR_RW(keys_media, KEYS_MEDIA),
ISKU_BIN_ATTR_RW(keys_thumbster), ISKU_BIN_ATTR_RW(keys_thumbster, KEYS_THUMBSTER),
ISKU_BIN_ATTR_RW(keys_macro), ISKU_BIN_ATTR_RW(keys_macro, KEYS_MACRO),
ISKU_BIN_ATTR_RW(keys_capslock), ISKU_BIN_ATTR_RW(keys_capslock, KEYS_CAPSLOCK),
ISKU_BIN_ATTR_RW(light), ISKU_BIN_ATTR_RW(light, LIGHT),
ISKU_BIN_ATTR_RW(key_mask), ISKU_BIN_ATTR_RW(key_mask, KEY_MASK),
ISKU_BIN_ATTR_RW(last_set), ISKU_BIN_ATTR_RW(last_set, LAST_SET),
ISKU_BIN_ATTR_W(talk), ISKU_BIN_ATTR_W(talk, TALK),
ISKU_BIN_ATTR_R(info), ISKU_BIN_ATTR_R(info, INFO),
ISKU_BIN_ATTR_W(control), ISKU_BIN_ATTR_W(control, CONTROL),
ISKU_BIN_ATTR_W(reset, RESET),
__ATTR_NULL __ATTR_NULL
}; };
......
...@@ -14,77 +14,34 @@ ...@@ -14,77 +14,34 @@
#include <linux/types.h> #include <linux/types.h>
enum {
ISKU_SIZE_CONTROL = 0x03,
ISKU_SIZE_INFO = 0x06,
ISKU_SIZE_KEY_MASK = 0x06,
ISKU_SIZE_KEYS_FUNCTION = 0x29,
ISKU_SIZE_KEYS_EASYZONE = 0x41,
ISKU_SIZE_KEYS_MEDIA = 0x1d,
ISKU_SIZE_KEYS_THUMBSTER = 0x17,
ISKU_SIZE_KEYS_MACRO = 0x23,
ISKU_SIZE_KEYS_CAPSLOCK = 0x06,
ISKU_SIZE_LAST_SET = 0x14,
ISKU_SIZE_LIGHT = 0x0a,
ISKU_SIZE_MACRO = 0x823,
ISKU_SIZE_RESET = 0x03,
ISKU_SIZE_TALK = 0x10,
};
enum { enum {
ISKU_PROFILE_NUM = 5, ISKU_PROFILE_NUM = 5,
ISKU_USB_INTERFACE_PROTOCOL = 0, ISKU_USB_INTERFACE_PROTOCOL = 0,
}; };
struct isku_control {
uint8_t command; /* ISKU_COMMAND_CONTROL */
uint8_t value;
uint8_t request;
} __packed;
struct isku_actual_profile { struct isku_actual_profile {
uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */ uint8_t command; /* ISKU_COMMAND_ACTUAL_PROFILE */
uint8_t size; /* always 3 */ uint8_t size; /* always 3 */
uint8_t actual_profile; uint8_t actual_profile;
} __packed; } __packed;
struct isku_key_mask {
uint8_t command; /* ISKU_COMMAND_KEY_MASK */
uint8_t size; /* 6 */
uint8_t profile_number; /* 0-4 */
uint8_t mask;
uint16_t checksum;
} __packed;
struct isku_keys_function {
uint8_t data[0x29];
} __packed;
struct isku_keys_easyzone {
uint8_t data[0x41];
} __packed;
struct isku_keys_media {
uint8_t data[0x1d];
} __packed;
struct isku_keys_thumbster {
uint8_t data[0x17];
} __packed;
struct isku_keys_macro {
uint8_t data[0x23];
} __packed;
struct isku_keys_capslock {
uint8_t data[0x6];
} __packed;
struct isku_macro {
uint8_t data[0x823];
} __packed;
struct isku_light {
uint8_t data[0xa];
} __packed;
struct isku_info {
uint8_t data[2];
uint8_t firmware_version;
uint8_t unknown[3];
} __packed;
struct isku_talk {
uint8_t data[0x10];
} __packed;
struct isku_last_set {
uint8_t data[0x14];
} __packed;
enum isku_commands { enum isku_commands {
ISKU_COMMAND_CONTROL = 0x4, ISKU_COMMAND_CONTROL = 0x4,
ISKU_COMMAND_ACTUAL_PROFILE = 0x5, ISKU_COMMAND_ACTUAL_PROFILE = 0x5,
...@@ -97,6 +54,7 @@ enum isku_commands { ...@@ -97,6 +54,7 @@ enum isku_commands {
ISKU_COMMAND_MACRO = 0xe, ISKU_COMMAND_MACRO = 0xe,
ISKU_COMMAND_INFO = 0xf, ISKU_COMMAND_INFO = 0xf,
ISKU_COMMAND_LIGHT = 0x10, ISKU_COMMAND_LIGHT = 0x10,
ISKU_COMMAND_RESET = 0x11,
ISKU_COMMAND_KEYS_CAPSLOCK = 0x13, ISKU_COMMAND_KEYS_CAPSLOCK = 0x13,
ISKU_COMMAND_LAST_SET = 0x14, ISKU_COMMAND_LAST_SET = 0x14,
ISKU_COMMAND_15 = 0x15, ISKU_COMMAND_15 = 0x15,
......
This diff is collapsed.
...@@ -14,11 +14,19 @@ ...@@ -14,11 +14,19 @@
#include <linux/types.h> #include <linux/types.h>
struct koneplus_talk { enum {
uint8_t command; /* KONEPLUS_COMMAND_TALK */ KONEPLUS_SIZE_ACTUAL_PROFILE = 0x03,
uint8_t size; /* always 0x10 */ KONEPLUS_SIZE_CONTROL = 0x03,
uint8_t data[14]; KONEPLUS_SIZE_FIRMWARE_WRITE = 0x0402,
} __packed; KONEPLUS_SIZE_INFO = 0x06,
KONEPLUS_SIZE_MACRO = 0x0822,
KONEPLUS_SIZE_PROFILE_SETTINGS = 0x2b,
KONEPLUS_SIZE_PROFILE_BUTTONS = 0x4d,
KONEPLUS_SIZE_SENSOR = 0x06,
KONEPLUS_SIZE_TALK = 0x10,
KONEPLUS_SIZE_TCU = 0x04,
KONEPLUS_SIZE_TCU_IMAGE = 0x0404,
};
enum koneplus_control_requests { enum koneplus_control_requests {
KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80, KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x80,
...@@ -31,45 +39,6 @@ struct koneplus_actual_profile { ...@@ -31,45 +39,6 @@ struct koneplus_actual_profile {
uint8_t actual_profile; /* Range 0-4! */ uint8_t actual_profile; /* Range 0-4! */
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct koneplus_profile_settings {
uint8_t command; /* KONEPLUS_COMMAND_PROFILE_SETTINGS */
uint8_t size; /* always 43 */
uint8_t number; /* range 0-4 */
uint8_t advanced_sensitivity;
uint8_t sensitivity_x;
uint8_t sensitivity_y;
uint8_t cpi_levels_enabled;
uint8_t cpi_levels_x[5];
uint8_t cpi_startup_level; /* range 0-4 */
uint8_t cpi_levels_y[5]; /* range 1-60 means 100-6000 cpi */
uint8_t unknown1;
uint8_t polling_rate;
uint8_t lights_enabled;
uint8_t light_effect_mode;
uint8_t color_flow_effect;
uint8_t light_effect_type;
uint8_t light_effect_speed;
uint8_t lights[16];
uint16_t checksum;
} __attribute__ ((__packed__));
struct koneplus_profile_buttons {
uint8_t command; /* KONEPLUS_COMMAND_PROFILE_BUTTONS */
uint8_t size; /* always 77 */
uint8_t number; /* range 0-4 */
uint8_t data[72];
uint16_t checksum;
} __attribute__ ((__packed__));
struct koneplus_macro {
uint8_t command; /* KONEPLUS_COMMAND_MACRO */
uint16_t size; /* always 0x822 little endian */
uint8_t profile; /* range 0-4 */
uint8_t button; /* range 0-23 */
uint8_t data[2075];
uint16_t checksum;
} __attribute__ ((__packed__));
struct koneplus_info { struct koneplus_info {
uint8_t command; /* KONEPLUS_COMMAND_INFO */ uint8_t command; /* KONEPLUS_COMMAND_INFO */
uint8_t size; /* always 6 */ uint8_t size; /* always 6 */
...@@ -77,51 +46,15 @@ struct koneplus_info { ...@@ -77,51 +46,15 @@ struct koneplus_info {
uint8_t unknown[3]; uint8_t unknown[3];
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct koneplus_e {
uint8_t command; /* KONEPLUS_COMMAND_E */
uint8_t size; /* always 3 */
uint8_t unknown; /* TODO 1; 0 before firmware update */
} __attribute__ ((__packed__));
struct koneplus_sensor {
uint8_t command; /* KONEPLUS_COMMAND_SENSOR */
uint8_t size; /* always 6 */
uint8_t data[4];
} __attribute__ ((__packed__));
struct koneplus_firmware_write {
uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE */
uint8_t unknown[1025];
} __attribute__ ((__packed__));
struct koneplus_firmware_write_control {
uint8_t command; /* KONEPLUS_COMMAND_FIRMWARE_WRITE_CONTROL */
/*
* value is 1 on success
* 3 means "not finished yet"
*/
uint8_t value;
uint8_t unknown; /* always 0x75 */
} __attribute__ ((__packed__));
struct koneplus_tcu {
uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */
uint8_t data[2];
} __attribute__ ((__packed__));
struct koneplus_tcu_image {
uint16_t usb_command; /* KONEPLUS_USB_COMMAND_TCU */
uint8_t data[1024];
uint16_t checksum;
} __attribute__ ((__packed__));
enum koneplus_commands { enum koneplus_commands {
KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5, KONEPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
KONEPLUS_COMMAND_CONTROL = 0x4,
KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6, KONEPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7, KONEPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
KONEPLUS_COMMAND_MACRO = 0x8, KONEPLUS_COMMAND_MACRO = 0x8,
KONEPLUS_COMMAND_INFO = 0x9, KONEPLUS_COMMAND_INFO = 0x9,
KONEPLUS_COMMAND_TCU = 0xc, KONEPLUS_COMMAND_TCU = 0xc,
KONEPLUS_COMMAND_TCU_IMAGE = 0xc,
KONEPLUS_COMMAND_E = 0xe, KONEPLUS_COMMAND_E = 0xe,
KONEPLUS_COMMAND_SENSOR = 0xf, KONEPLUS_COMMAND_SENSOR = 0xf,
KONEPLUS_COMMAND_TALK = 0x10, KONEPLUS_COMMAND_TALK = 0x10,
...@@ -187,10 +120,6 @@ struct koneplus_device { ...@@ -187,10 +120,6 @@ struct koneplus_device {
int chrdev_minor; int chrdev_minor;
struct mutex koneplus_lock; struct mutex koneplus_lock;
struct koneplus_info info;
struct koneplus_profile_settings profile_settings[5];
struct koneplus_profile_buttons profile_buttons[5];
}; };
#endif #endif
This diff is collapsed.
...@@ -14,6 +14,13 @@ ...@@ -14,6 +14,13 @@
#include <linux/types.h> #include <linux/types.h>
enum {
KOVAPLUS_SIZE_CONTROL = 0x03,
KOVAPLUS_SIZE_INFO = 0x06,
KOVAPLUS_SIZE_PROFILE_SETTINGS = 0x10,
KOVAPLUS_SIZE_PROFILE_BUTTONS = 0x17,
};
enum kovaplus_control_requests { enum kovaplus_control_requests {
/* write; value = profile number range 0-4 */ /* write; value = profile number range 0-4 */
KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
...@@ -53,15 +60,9 @@ struct kovaplus_info { ...@@ -53,15 +60,9 @@ struct kovaplus_info {
uint8_t unknown[3]; uint8_t unknown[3];
} __packed; } __packed;
/* writes 1 on plugin */
struct kovaplus_a {
uint8_t command; /* KOVAPLUS_COMMAND_A */
uint8_t size; /* 3 */
uint8_t unknown;
} __packed;
enum kovaplus_commands { enum kovaplus_commands {
KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5, KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
KOVAPLUS_COMMAND_CONTROL = 0x4,
KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6, KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7, KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
KOVAPLUS_COMMAND_INFO = 0x9, KOVAPLUS_COMMAND_INFO = 0x9,
...@@ -125,7 +126,6 @@ struct kovaplus_device { ...@@ -125,7 +126,6 @@ struct kovaplus_device {
int roccat_claimed; int roccat_claimed;
int chrdev_minor; int chrdev_minor;
struct mutex kovaplus_lock; struct mutex kovaplus_lock;
struct kovaplus_info info;
struct kovaplus_profile_settings profile_settings[5]; struct kovaplus_profile_settings profile_settings[5];
struct kovaplus_profile_buttons profile_buttons[5]; struct kovaplus_profile_buttons profile_buttons[5];
}; };
......
/*
* Roccat Lua driver for Linux
*
* Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
/*
* Roccat Lua is a gamer mouse which cpi, button and light settings can be
* configured.
*/
#include <linux/device.h>
#include <linux/input.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/hid-roccat.h>
#include "hid-ids.h"
#include "hid-roccat-common.h"
#include "hid-roccat-lua.h"
static ssize_t lua_sysfs_read(struct file *fp, struct kobject *kobj,
char *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
if (off >= real_size)
return 0;
if (off != 0 || count != real_size)
return -EINVAL;
mutex_lock(&lua->lua_lock);
retval = roccat_common2_receive(usb_dev, command, buf, real_size);
mutex_unlock(&lua->lua_lock);
return retval ? retval : real_size;
}
static ssize_t lua_sysfs_write(struct file *fp, struct kobject *kobj,
void const *buf, loff_t off, size_t count,
size_t real_size, uint command)
{
struct device *dev = container_of(kobj, struct device, kobj);
struct lua_device *lua = hid_get_drvdata(dev_get_drvdata(dev));
struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
int retval;
if (off != 0 || count != real_size)
return -EINVAL;
mutex_lock(&lua->lua_lock);
retval = roccat_common2_send(usb_dev, command, (void *)buf, real_size);
mutex_unlock(&lua->lua_lock);
return retval ? retval : real_size;
}
#define LUA_SYSFS_W(thingy, THINGY) \
static ssize_t lua_sysfs_write_ ## thingy(struct file *fp, \
struct kobject *kobj, struct bin_attribute *attr, \
char *buf, loff_t off, size_t count) \
{ \
return lua_sysfs_write(fp, kobj, buf, off, count, \
LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
}
#define LUA_SYSFS_R(thingy, THINGY) \
static ssize_t lua_sysfs_read_ ## thingy(struct file *fp, \
struct kobject *kobj, struct bin_attribute *attr, \
char *buf, loff_t off, size_t count) \
{ \
return lua_sysfs_read(fp, kobj, buf, off, count, \
LUA_SIZE_ ## THINGY, LUA_COMMAND_ ## THINGY); \
}
#define LUA_BIN_ATTRIBUTE_RW(thingy, THINGY) \
LUA_SYSFS_W(thingy, THINGY) \
LUA_SYSFS_R(thingy, THINGY) \
static struct bin_attribute lua_ ## thingy ## _attr = { \
.attr = { .name = #thingy, .mode = 0660 }, \
.size = LUA_SIZE_ ## THINGY, \
.read = lua_sysfs_read_ ## thingy, \
.write = lua_sysfs_write_ ## thingy \
};
LUA_BIN_ATTRIBUTE_RW(control, CONTROL)
static int lua_create_sysfs_attributes(struct usb_interface *intf)
{
return sysfs_create_bin_file(&intf->dev.kobj, &lua_control_attr);
}
static void lua_remove_sysfs_attributes(struct usb_interface *intf)
{
sysfs_remove_bin_file(&intf->dev.kobj, &lua_control_attr);
}
static int lua_init_lua_device_struct(struct usb_device *usb_dev,
struct lua_device *lua)
{
mutex_init(&lua->lua_lock);
return 0;
}
static int lua_init_specials(struct hid_device *hdev)
{
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
struct usb_device *usb_dev = interface_to_usbdev(intf);
struct lua_device *lua;
int retval;
lua = kzalloc(sizeof(*lua), GFP_KERNEL);
if (!lua) {
hid_err(hdev, "can't alloc device descriptor\n");
return -ENOMEM;
}
hid_set_drvdata(hdev, lua);
retval = lua_init_lua_device_struct(usb_dev, lua);
if (retval) {
hid_err(hdev, "couldn't init struct lua_device\n");
goto exit;
}
retval = lua_create_sysfs_attributes(intf);
if (retval) {
hid_err(hdev, "cannot create sysfs files\n");
goto exit;
}
return 0;
exit:
kfree(lua);
return retval;
}
static void lua_remove_specials(struct hid_device *hdev)
{
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
struct lua_device *lua;
lua_remove_sysfs_attributes(intf);
lua = hid_get_drvdata(hdev);
kfree(lua);
}
static int lua_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
int retval;
retval = hid_parse(hdev);
if (retval) {
hid_err(hdev, "parse failed\n");
goto exit;
}
retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (retval) {
hid_err(hdev, "hw start failed\n");
goto exit;
}
retval = lua_init_specials(hdev);
if (retval) {
hid_err(hdev, "couldn't install mouse\n");
goto exit_stop;
}
return 0;
exit_stop:
hid_hw_stop(hdev);
exit:
return retval;
}
static void lua_remove(struct hid_device *hdev)
{
lua_remove_specials(hdev);
hid_hw_stop(hdev);
}
static const struct hid_device_id lua_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_LUA) },
{ }
};
MODULE_DEVICE_TABLE(hid, lua_devices);
static struct hid_driver lua_driver = {
.name = "lua",
.id_table = lua_devices,
.probe = lua_probe,
.remove = lua_remove
};
static int __init lua_init(void)
{
return hid_register_driver(&lua_driver);
}
static void __exit lua_exit(void)
{
hid_unregister_driver(&lua_driver);
}
module_init(lua_init);
module_exit(lua_exit);
MODULE_AUTHOR("Stefan Achatz");
MODULE_DESCRIPTION("USB Roccat Lua driver");
MODULE_LICENSE("GPL v2");
#ifndef __HID_ROCCAT_LUA_H
#define __HID_ROCCAT_LUA_H
/*
* Copyright (c) 2012 Stefan Achatz <erazor_de@users.sourceforge.net>
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*/
#include <linux/types.h>
enum {
LUA_SIZE_CONTROL = 8,
};
enum lua_commands {
LUA_COMMAND_CONTROL = 3,
};
struct lua_device {
struct mutex lua_lock;
};
#endif
This diff is collapsed.
...@@ -14,11 +14,13 @@ ...@@ -14,11 +14,13 @@
#include <linux/types.h> #include <linux/types.h>
struct pyra_b { enum {
uint8_t command; /* PYRA_COMMAND_B */ PYRA_SIZE_CONTROL = 0x03,
uint8_t size; /* always 3 */ PYRA_SIZE_INFO = 0x06,
uint8_t unknown; /* 1 */ PYRA_SIZE_PROFILE_SETTINGS = 0x0d,
} __attribute__ ((__packed__)); PYRA_SIZE_PROFILE_BUTTONS = 0x13,
PYRA_SIZE_SETTINGS = 0x03,
};
enum pyra_control_requests { enum pyra_control_requests {
PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
...@@ -46,14 +48,6 @@ struct pyra_profile_settings { ...@@ -46,14 +48,6 @@ struct pyra_profile_settings {
uint16_t checksum; /* byte sum */ uint16_t checksum; /* byte sum */
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct pyra_profile_buttons {
uint8_t command; /* PYRA_COMMAND_PROFILE_BUTTONS */
uint8_t size; /* always 0x13 */
uint8_t number; /* Range 0-4 */
uint8_t buttons[14];
uint16_t checksum; /* byte sum */
} __attribute__ ((__packed__));
struct pyra_info { struct pyra_info {
uint8_t command; /* PYRA_COMMAND_INFO */ uint8_t command; /* PYRA_COMMAND_INFO */
uint8_t size; /* always 6 */ uint8_t size; /* always 6 */
...@@ -64,6 +58,7 @@ struct pyra_info { ...@@ -64,6 +58,7 @@ struct pyra_info {
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
enum pyra_commands { enum pyra_commands {
PYRA_COMMAND_CONTROL = 0x4,
PYRA_COMMAND_SETTINGS = 0x5, PYRA_COMMAND_SETTINGS = 0x5,
PYRA_COMMAND_PROFILE_SETTINGS = 0x6, PYRA_COMMAND_PROFILE_SETTINGS = 0x6,
PYRA_COMMAND_PROFILE_BUTTONS = 0x7, PYRA_COMMAND_PROFILE_BUTTONS = 0x7,
...@@ -148,13 +143,10 @@ struct pyra_roccat_report { ...@@ -148,13 +143,10 @@ struct pyra_roccat_report {
struct pyra_device { struct pyra_device {
int actual_profile; int actual_profile;
int actual_cpi; int actual_cpi;
int firmware_version;
int roccat_claimed; int roccat_claimed;
int chrdev_minor; int chrdev_minor;
struct mutex pyra_lock; struct mutex pyra_lock;
struct pyra_settings settings;
struct pyra_profile_settings profile_settings[5]; struct pyra_profile_settings profile_settings[5];
struct pyra_profile_buttons profile_buttons[5];
}; };
#endif #endif
...@@ -120,7 +120,7 @@ SAVU_SYSFS_RW(profile, PROFILE) ...@@ -120,7 +120,7 @@ SAVU_SYSFS_RW(profile, PROFILE)
SAVU_SYSFS_RW(general, GENERAL) SAVU_SYSFS_RW(general, GENERAL)
SAVU_SYSFS_RW(buttons, BUTTONS) SAVU_SYSFS_RW(buttons, BUTTONS)
SAVU_SYSFS_RW(macro, MACRO) SAVU_SYSFS_RW(macro, MACRO)
SAVU_SYSFS_R(info, INFO) SAVU_SYSFS_RW(info, INFO)
SAVU_SYSFS_RW(sensor, SENSOR) SAVU_SYSFS_RW(sensor, SENSOR)
static struct bin_attribute savu_bin_attributes[] = { static struct bin_attribute savu_bin_attributes[] = {
...@@ -129,7 +129,7 @@ static struct bin_attribute savu_bin_attributes[] = { ...@@ -129,7 +129,7 @@ static struct bin_attribute savu_bin_attributes[] = {
SAVU_BIN_ATTRIBUTE_RW(general, GENERAL), SAVU_BIN_ATTRIBUTE_RW(general, GENERAL),
SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS), SAVU_BIN_ATTRIBUTE_RW(buttons, BUTTONS),
SAVU_BIN_ATTRIBUTE_RW(macro, MACRO), SAVU_BIN_ATTRIBUTE_RW(macro, MACRO),
SAVU_BIN_ATTRIBUTE_R(info, INFO), SAVU_BIN_ATTRIBUTE_RW(info, INFO),
SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR), SAVU_BIN_ATTRIBUTE_RW(sensor, SENSOR),
__ATTR_NULL __ATTR_NULL
}; };
......
...@@ -82,23 +82,6 @@ struct hid_sensor_hub_callbacks_list { ...@@ -82,23 +82,6 @@ struct hid_sensor_hub_callbacks_list {
void *priv; void *priv;
}; };
static int sensor_hub_check_for_sensor_page(struct hid_device *hdev)
{
int i;
int ret = -EINVAL;
for (i = 0; i < hdev->maxcollection; i++) {
struct hid_collection *col = &hdev->collection[i];
if (col->type == HID_COLLECTION_PHYSICAL &&
(col->usage & HID_USAGE_PAGE) == HID_UP_SENSOR) {
ret = 0;
break;
}
}
return ret;
}
static struct hid_report *sensor_hub_report(int id, struct hid_device *hdev, static struct hid_report *sensor_hub_report(int id, struct hid_device *hdev,
int dir) int dir)
{ {
...@@ -437,9 +420,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev, ...@@ -437,9 +420,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
ptr = raw_data; ptr = raw_data;
ptr++; /*Skip report id*/ ptr++; /*Skip report id*/
if (!report)
goto err_report;
spin_lock_irqsave(&pdata->lock, flags); spin_lock_irqsave(&pdata->lock, flags);
for (i = 0; i < report->maxfield; ++i) { for (i = 0; i < report->maxfield; ++i) {
...@@ -485,7 +465,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev, ...@@ -485,7 +465,6 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
callback->pdev); callback->pdev);
spin_unlock_irqrestore(&pdata->lock, flags); spin_unlock_irqrestore(&pdata->lock, flags);
err_report:
return 1; return 1;
} }
...@@ -524,10 +503,6 @@ static int sensor_hub_probe(struct hid_device *hdev, ...@@ -524,10 +503,6 @@ static int sensor_hub_probe(struct hid_device *hdev,
hid_err(hdev, "parse failed\n"); hid_err(hdev, "parse failed\n");
goto err_free; goto err_free;
} }
if (sensor_hub_check_for_sensor_page(hdev) < 0) {
hid_err(hdev, "sensor page not found\n");
goto err_free;
}
INIT_LIST_HEAD(&hdev->inputs); INIT_LIST_HEAD(&hdev->inputs);
ret = hid_hw_start(hdev, 0); ret = hid_hw_start(hdev, 0);
...@@ -630,16 +605,7 @@ static void sensor_hub_remove(struct hid_device *hdev) ...@@ -630,16 +605,7 @@ static void sensor_hub_remove(struct hid_device *hdev)
} }
static const struct hid_device_id sensor_hub_devices[] = { static const struct hid_device_id sensor_hub_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, { HID_DEVICE(BUS_USB, HID_GROUP_SENSOR_HUB, HID_ANY_ID, HID_ANY_ID) },
USB_DEVICE_ID_SENSOR_HUB_1020) },
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087,
USB_DEVICE_ID_SENSOR_HUB_1020) },
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086,
USB_DEVICE_ID_SENSOR_HUB_09FA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087,
USB_DEVICE_ID_SENSOR_HUB_09FA) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
USB_DEVICE_ID_SENSOR_HUB_7014) },
{ } { }
}; };
MODULE_DEVICE_TABLE(hid, sensor_hub_devices); MODULE_DEVICE_TABLE(hid, sensor_hub_devices);
......
...@@ -57,10 +57,6 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, ...@@ -57,10 +57,6 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
while (list->head == list->tail) { while (list->head == list->tail) {
if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
break;
}
if (signal_pending(current)) { if (signal_pending(current)) {
ret = -ERESTARTSYS; ret = -ERESTARTSYS;
break; break;
...@@ -69,6 +65,10 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, ...@@ -69,6 +65,10 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
ret = -EIO; ret = -EIO;
break; break;
} }
if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
break;
}
/* allow O_NONBLOCK to work well from other threads */ /* allow O_NONBLOCK to work well from other threads */
mutex_unlock(&list->read_mutex); mutex_unlock(&list->read_mutex);
...@@ -295,6 +295,13 @@ static int hidraw_open(struct inode *inode, struct file *file) ...@@ -295,6 +295,13 @@ static int hidraw_open(struct inode *inode, struct file *file)
} }
static int hidraw_fasync(int fd, struct file *file, int on)
{
struct hidraw_list *list = file->private_data;
return fasync_helper(fd, file, on, &list->fasync);
}
static int hidraw_release(struct inode * inode, struct file * file) static int hidraw_release(struct inode * inode, struct file * file)
{ {
unsigned int minor = iminor(inode); unsigned int minor = iminor(inode);
...@@ -438,6 +445,7 @@ static const struct file_operations hidraw_ops = { ...@@ -438,6 +445,7 @@ static const struct file_operations hidraw_ops = {
.open = hidraw_open, .open = hidraw_open,
.release = hidraw_release, .release = hidraw_release,
.unlocked_ioctl = hidraw_ioctl, .unlocked_ioctl = hidraw_ioctl,
.fasync = hidraw_fasync,
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
.compat_ioctl = hidraw_ioctl, .compat_ioctl = hidraw_ioctl,
#endif #endif
......
menu "I2C HID support"
depends on I2C
config I2C_HID
tristate "HID over I2C transport layer"
default n
depends on I2C && INPUT
select HID
---help---
Say Y here if you use a keyboard, a touchpad, a touchscreen, or any
other HID based devices which is connected to your computer via I2C.
If unsure, say N.
This support is also available as a module. If so, the module
will be called i2c-hid.
endmenu
#
# Makefile for the I2C input drivers
#
obj-$(CONFIG_I2C_HID) += i2c-hid.o
This diff is collapsed.
...@@ -72,6 +72,7 @@ static const struct hid_blacklist { ...@@ -72,6 +72,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
...@@ -79,9 +80,11 @@ static const struct hid_blacklist { ...@@ -79,9 +80,11 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT },
......
...@@ -361,10 +361,6 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun ...@@ -361,10 +361,6 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE); prepare_to_wait(&list->hiddev->wait, &wait, TASK_INTERRUPTIBLE);
while (list->head == list->tail) { while (list->head == list->tail) {
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
}
if (signal_pending(current)) { if (signal_pending(current)) {
retval = -ERESTARTSYS; retval = -ERESTARTSYS;
break; break;
...@@ -373,6 +369,10 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun ...@@ -373,6 +369,10 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun
retval = -EIO; retval = -EIO;
break; break;
} }
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
}
/* let O_NONBLOCK tasks run */ /* let O_NONBLOCK tasks run */
mutex_unlock(&list->thread_lock); mutex_unlock(&list->thread_lock);
...@@ -625,7 +625,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -625,7 +625,7 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break; break;
case HIDIOCAPPLICATION: case HIDIOCAPPLICATION:
if (arg < 0 || arg >= hid->maxapplication) if (arg >= hid->maxapplication)
break; break;
for (i = 0; i < hid->maxcollection; i++) for (i = 0; i < hid->maxcollection; i++)
......
...@@ -251,7 +251,7 @@ void input_mt_sync_frame(struct input_dev *dev) ...@@ -251,7 +251,7 @@ void input_mt_sync_frame(struct input_dev *dev)
if (mt->flags & INPUT_MT_DROP_UNUSED) { if (mt->flags & INPUT_MT_DROP_UNUSED) {
for (s = mt->slots; s != mt->slots + mt->num_slots; s++) { for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
if (s->frame == mt->frame) if (input_mt_is_used(mt, s))
continue; continue;
input_mt_slot(dev, s - mt->slots); input_mt_slot(dev, s - mt->slots);
input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#ifndef _HID_SENSORS_IDS_H #ifndef _HID_SENSORS_IDS_H
#define _HID_SENSORS_IDS_H #define _HID_SENSORS_IDS_H
#define HID_UP_SENSOR 0x00200000
#define HID_MAX_PHY_DEVICES 0xFF #define HID_MAX_PHY_DEVICES 0xFF
/* Accel 3D (200073) */ /* Accel 3D (200073) */
......
...@@ -167,6 +167,7 @@ struct hid_item { ...@@ -167,6 +167,7 @@ struct hid_item {
#define HID_UP_MSVENDOR 0xff000000 #define HID_UP_MSVENDOR 0xff000000
#define HID_UP_CUSTOM 0x00ff0000 #define HID_UP_CUSTOM 0x00ff0000
#define HID_UP_LOGIVENDOR 0xffbc0000 #define HID_UP_LOGIVENDOR 0xffbc0000
#define HID_UP_SENSOR 0x00200000
#define HID_USAGE 0x0000ffff #define HID_USAGE 0x0000ffff
...@@ -292,6 +293,7 @@ struct hid_item { ...@@ -292,6 +293,7 @@ struct hid_item {
*/ */
#define HID_GROUP_GENERIC 0x0001 #define HID_GROUP_GENERIC 0x0001
#define HID_GROUP_MULTITOUCH 0x0002 #define HID_GROUP_MULTITOUCH 0x0002
#define HID_GROUP_SENSOR_HUB 0x0003
/* /*
* This is the global environment of the parser. This information is * This is the global environment of the parser. This information is
...@@ -342,6 +344,7 @@ struct hid_collection { ...@@ -342,6 +344,7 @@ struct hid_collection {
struct hid_usage { struct hid_usage {
unsigned hid; /* hid usage code */ unsigned hid; /* hid usage code */
unsigned collection_index; /* index into collection array */ unsigned collection_index; /* index into collection array */
unsigned usage_index; /* index into usage array */
/* hidinput data */ /* hidinput data */
__u16 code; /* input driver code */ __u16 code; /* input driver code */
__u8 type; /* input driver type */ __u8 type; /* input driver type */
...@@ -684,6 +687,7 @@ struct hid_ll_driver { ...@@ -684,6 +687,7 @@ struct hid_ll_driver {
extern int hid_debug; extern int hid_debug;
extern bool hid_ignore(struct hid_device *);
extern int hid_add_device(struct hid_device *); extern int hid_add_device(struct hid_device *);
extern void hid_destroy_device(struct hid_device *); extern void hid_destroy_device(struct hid_device *);
...@@ -706,6 +710,7 @@ int hid_input_report(struct hid_device *, int type, u8 *, int, int); ...@@ -706,6 +710,7 @@ int hid_input_report(struct hid_device *, int type, u8 *, int, int);
int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
struct hid_field *hidinput_get_led_field(struct hid_device *hid); struct hid_field *hidinput_get_led_field(struct hid_device *hid);
unsigned int hidinput_count_leds(struct hid_device *hid); unsigned int hidinput_count_leds(struct hid_device *hid);
__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
void hid_output_report(struct hid_report *report, __u8 *data); void hid_output_report(struct hid_report *report, __u8 *data);
struct hid_device *hid_allocate_device(void); struct hid_device *hid_allocate_device(void);
struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
...@@ -716,6 +721,7 @@ int hid_connect(struct hid_device *hid, unsigned int connect_mask); ...@@ -716,6 +721,7 @@ int hid_connect(struct hid_device *hid, unsigned int connect_mask);
void hid_disconnect(struct hid_device *hid); void hid_disconnect(struct hid_device *hid);
const struct hid_device_id *hid_match_id(struct hid_device *hdev, const struct hid_device_id *hid_match_id(struct hid_device *hdev,
const struct hid_device_id *id); const struct hid_device_id *id);
s32 hid_snto32(__u32 value, unsigned n);
/** /**
* hid_map_usage - map usage input bits * hid_map_usage - map usage input bits
......
/*
* HID over I2C protocol implementation
*
* Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
* Copyright (c) 2012 Ecole Nationale de l'Aviation Civile, France
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*/
#ifndef __LINUX_I2C_HID_H
#define __LINUX_I2C_HID_H
#include <linux/types.h>
/**
* struct i2chid_platform_data - used by hid over i2c implementation.
* @hid_descriptor_address: i2c register where the HID descriptor is stored.
*
* Note that it is the responsibility of the platform driver (or the acpi 5.0
* driver) to setup the irq related to the gpio in the struct i2c_board_info.
* The platform driver should also setup the gpio according to the device:
*
* A typical example is the following:
* irq = gpio_to_irq(intr_gpio);
* hkdk4412_i2c_devs5[0].irq = irq; // store the irq in i2c_board_info
* gpio_request(intr_gpio, "elan-irq");
* s3c_gpio_setpull(intr_gpio, S3C_GPIO_PULL_UP);
*/
struct i2c_hid_platform_data {
u16 hid_descriptor_address;
};
#endif /* __LINUX_I2C_HID_H */
...@@ -69,6 +69,12 @@ static inline bool input_mt_is_active(const struct input_mt_slot *slot) ...@@ -69,6 +69,12 @@ static inline bool input_mt_is_active(const struct input_mt_slot *slot)
return input_mt_get_value(slot, ABS_MT_TRACKING_ID) >= 0; return input_mt_get_value(slot, ABS_MT_TRACKING_ID) >= 0;
} }
static inline bool input_mt_is_used(const struct input_mt *mt,
const struct input_mt_slot *slot)
{
return slot->frame == mt->frame;
}
int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots, int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
unsigned int flags); unsigned int flags);
void input_mt_destroy_slots(struct input_dev *dev); void input_mt_destroy_slots(struct input_dev *dev);
......
...@@ -851,6 +851,7 @@ struct input_keymap_entry { ...@@ -851,6 +851,7 @@ struct input_keymap_entry {
#define MSC_GESTURE 0x02 #define MSC_GESTURE 0x02
#define MSC_RAW 0x03 #define MSC_RAW 0x03
#define MSC_SCAN 0x04 #define MSC_SCAN 0x04
#define MSC_TIMESTAMP 0x05
#define MSC_MAX 0x07 #define MSC_MAX 0x07
#define MSC_CNT (MSC_MAX+1) #define MSC_CNT (MSC_MAX+1)
......
...@@ -945,6 +945,13 @@ static int hidp_setup_hid(struct hidp_session *session, ...@@ -945,6 +945,13 @@ static int hidp_setup_hid(struct hidp_session *session,
hid->hid_get_raw_report = hidp_get_raw_report; hid->hid_get_raw_report = hidp_get_raw_report;
hid->hid_output_raw_report = hidp_output_raw_report; hid->hid_output_raw_report = hidp_output_raw_report;
/* True if device is blacklisted in drivers/hid/hid-core.c */
if (hid_ignore(hid)) {
hid_destroy_device(session->hid);
session->hid = NULL;
return -ENODEV;
}
return 0; return 0;
fault: fault:
...@@ -1017,7 +1024,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, ...@@ -1017,7 +1024,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
if (req->rd_size > 0) { if (req->rd_size > 0) {
err = hidp_setup_hid(session, req); err = hidp_setup_hid(session, req);
if (err) if (err && err != -ENODEV)
goto purge; goto purge;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment