diff options
42 files changed, 3934 insertions, 374 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra new file mode 100644 index 000000000000..ad1125b02ff4 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra | |||
| @@ -0,0 +1,98 @@ | |||
| 1 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_cpi | ||
| 2 | Date: August 2010 | ||
| 3 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 4 | Description: It is possible to switch the cpi setting of the mouse with the | ||
| 5 | press of a button. | ||
| 6 | When read, this file returns the raw number of the actual cpi | ||
| 7 | setting reported by the mouse. This number has to be further | ||
| 8 | processed to receive the real dpi value. | ||
| 9 | |||
| 10 | VALUE DPI | ||
| 11 | 1 400 | ||
| 12 | 2 800 | ||
| 13 | 4 1600 | ||
| 14 | |||
| 15 | This file is readonly. | ||
| 16 | |||
| 17 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_profile | ||
| 18 | Date: August 2010 | ||
| 19 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 20 | Description: When read, this file returns the number of the actual profile in | ||
| 21 | range 0-4. | ||
| 22 | This file is readonly. | ||
| 23 | |||
| 24 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/firmware_version | ||
| 25 | Date: August 2010 | ||
| 26 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 27 | Description: When read, this file returns the raw integer version number of the | ||
| 28 | firmware reported by the mouse. Using the integer value eases | ||
| 29 | further usage in other programs. To receive the real version | ||
| 30 | number the decimal point has to be shifted 2 positions to the | ||
| 31 | left. E.g. a returned value of 138 means 1.38 | ||
| 32 | This file is readonly. | ||
| 33 | |||
| 34 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile_settings | ||
| 35 | Date: August 2010 | ||
| 36 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 37 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 38 | press of a button. A profile is split in settings and buttons. | ||
| 39 | profile_settings holds informations like resolution, sensitivity | ||
| 40 | and light effects. | ||
| 41 | When written, this file lets one write the respective profile | ||
| 42 | settings back to the mouse. The data has to be 13 bytes long. | ||
| 43 | The mouse will reject invalid data. | ||
| 44 | Which profile to write is determined by the profile number | ||
| 45 | contained in the data. | ||
| 46 | This file is writeonly. | ||
| 47 | |||
| 48 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]_settings | ||
| 49 | Date: August 2010 | ||
| 50 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 51 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 52 | press of a button. A profile is split in settings and buttons. | ||
| 53 | profile_settings holds informations like resolution, sensitivity | ||
| 54 | and light effects. | ||
| 55 | When read, these files return the respective profile settings. | ||
| 56 | The returned data is 13 bytes in size. | ||
| 57 | This file is readonly. | ||
| 58 | |||
| 59 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile_buttons | ||
| 60 | Date: August 2010 | ||
| 61 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 62 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 63 | press of a button. A profile is split in settings and buttons. | ||
| 64 | profile_buttons holds informations about button layout. | ||
| 65 | When written, this file lets one write the respective profile | ||
| 66 | buttons back to the mouse. The data has to be 19 bytes long. | ||
| 67 | The mouse will reject invalid data. | ||
| 68 | Which profile to write is determined by the profile number | ||
| 69 | contained in the data. | ||
| 70 | This file is writeonly. | ||
| 71 | |||
| 72 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]_buttons | ||
| 73 | Date: August 2010 | ||
| 74 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 75 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 76 | press of a button. A profile is split in settings and buttons. | ||
| 77 | profile_buttons holds informations about button layout. | ||
| 78 | When read, these files return the respective profile buttons. | ||
| 79 | The returned data is 19 bytes in size. | ||
| 80 | This file is readonly. | ||
| 81 | |||
| 82 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/startup_profile | ||
| 83 | Date: August 2010 | ||
| 84 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 85 | Description: The integer value of this attribute ranges from 0-4. | ||
| 86 | When read, this attribute returns the number of the profile | ||
| 87 | that's active when the mouse is powered on. | ||
| 88 | This file is readonly. | ||
| 89 | |||
| 90 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/settings | ||
| 91 | Date: August 2010 | ||
| 92 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 93 | Description: When read, this file returns the settings stored in the mouse. | ||
| 94 | The size of the data is 3 bytes and holds information on the | ||
| 95 | startup_profile. | ||
| 96 | When written, this file lets write settings back to the mouse. | ||
| 97 | The data has to be 3 bytes long. The mouse will reject invalid | ||
| 98 | data. | ||
diff --git a/Documentation/input/ntrig.txt b/Documentation/input/ntrig.txt new file mode 100644 index 000000000000..be1fd981f73f --- /dev/null +++ b/Documentation/input/ntrig.txt | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | N-Trig touchscreen Driver | ||
| 2 | ------------------------- | ||
| 3 | Copyright (c) 2008-2010 Rafi Rubin <rafi@seas.upenn.edu> | ||
| 4 | Copyright (c) 2009-2010 Stephane Chatty | ||
| 5 | |||
| 6 | This driver provides support for N-Trig pen and multi-touch sensors. Single | ||
| 7 | and multi-touch events are translated to the appropriate protocols for | ||
| 8 | the hid and input systems. Pen events are sufficiently hid compliant and | ||
| 9 | are left to the hid core. The driver also provides additional filtering | ||
| 10 | and utility functions accessible with sysfs and module parameters. | ||
| 11 | |||
| 12 | This driver has been reported to work properly with multiple N-Trig devices | ||
| 13 | attached. | ||
| 14 | |||
| 15 | |||
| 16 | Parameters | ||
| 17 | ---------- | ||
| 18 | |||
| 19 | Note: values set at load time are global and will apply to all applicable | ||
| 20 | devices. Adjusting parameters with sysfs will override the load time values, | ||
| 21 | but only for that one device. | ||
| 22 | |||
| 23 | The following parameters are used to configure filters to reduce noise: | ||
| 24 | |||
| 25 | activate_slack number of fingers to ignore before processing events | ||
| 26 | |||
| 27 | activation_height size threshold to activate immediately | ||
| 28 | activation_width | ||
| 29 | |||
| 30 | min_height size threshold bellow which fingers are ignored | ||
| 31 | min_width both to decide activation and during activity | ||
| 32 | |||
| 33 | deactivate_slack the number of "no contact" frames to ignore before | ||
| 34 | propagating the end of activity events | ||
| 35 | |||
| 36 | When the last finger is removed from the device, it sends a number of empty | ||
| 37 | frames. By holding off on deactivation for a few frames we can tolerate false | ||
| 38 | erroneous disconnects, where the sensor may mistakenly not detect a finger that | ||
| 39 | is still present. Thus deactivate_slack addresses problems where a users might | ||
| 40 | see breaks in lines during drawing, or drop an object during a long drag. | ||
| 41 | |||
| 42 | |||
| 43 | Additional sysfs items | ||
| 44 | ---------------------- | ||
| 45 | |||
| 46 | These nodes just provide easy access to the ranges reported by the device. | ||
| 47 | sensor_logical_height the range for positions reported during activity | ||
| 48 | sensor_logical_width | ||
| 49 | |||
| 50 | sensor_physical_height internal ranges not used for normal events but | ||
| 51 | sensor_physical_width useful for tuning | ||
| 52 | |||
| 53 | All N-Trig devices with product id of 1 report events in the ranges of | ||
| 54 | X: 0-9600 | ||
| 55 | Y: 0-7200 | ||
| 56 | However not all of these devices have the same physical dimensions. Most | ||
| 57 | seem to be 12" sensors (Dell Latitude XT and XT2 and the HP TX2), and | ||
| 58 | at least one model (Dell Studio 17) has a 17" sensor. The ratio of physical | ||
| 59 | to logical sizes is used to adjust the size based filter parameters. | ||
| 60 | |||
| 61 | |||
| 62 | Filtering | ||
| 63 | --------- | ||
| 64 | |||
| 65 | With the release of the early multi-touch firmwares it became increasingly | ||
| 66 | obvious that these sensors were prone to erroneous events. Users reported | ||
| 67 | seeing both inappropriately dropped contact and ghosts, contacts reported | ||
| 68 | where no finger was actually touching the screen. | ||
| 69 | |||
| 70 | Deactivation slack helps prevent dropped contact for single touch use, but does | ||
| 71 | not address the problem of dropping one of more contacts while other contacts | ||
| 72 | are still active. Drops in the multi-touch context require additional | ||
| 73 | processing and should be handled in tandem with tacking. | ||
| 74 | |||
| 75 | As observed ghost contacts are similar to actual use of the sensor, but they | ||
| 76 | seem to have different profiles. Ghost activity typically shows up as small | ||
| 77 | short lived touches. As such, I assume that the longer the continuous stream | ||
| 78 | of events the more likely those events are from a real contact, and that the | ||
| 79 | larger the size of each contact the more likely it is real. Balancing the | ||
| 80 | goals of preventing ghosts and accepting real events quickly (to minimize | ||
| 81 | user observable latency), the filter accumulates confidence for incoming | ||
| 82 | events until it hits thresholds and begins propagating. In the interest in | ||
| 83 | minimizing stored state as well as the cost of operations to make a decision, | ||
| 84 | I've kept that decision simple. | ||
| 85 | |||
| 86 | Time is measured in terms of the number of fingers reported, not frames since | ||
| 87 | the probability of multiple simultaneous ghosts is expected to drop off | ||
| 88 | dramatically with increasing numbers. Rather than accumulate weight as a | ||
| 89 | function of size, I just use it as a binary threshold. A sufficiently large | ||
| 90 | contact immediately overrides the waiting period and leads to activation. | ||
| 91 | |||
| 92 | Setting the activation size thresholds to large values will result in deciding | ||
| 93 | primarily on activation slack. If you see longer lived ghosts, turning up the | ||
| 94 | activation slack while reducing the size thresholds may suffice to eliminate | ||
| 95 | the ghosts while keeping the screen quite responsive to firm taps. | ||
| 96 | |||
| 97 | Contacts continue to be filtered with min_height and min_width even after | ||
| 98 | the initial activation filter is satisfied. The intent is to provide | ||
| 99 | a mechanism for filtering out ghosts in the form of an extra finger while | ||
| 100 | you actually are using the screen. In practice this sort of ghost has | ||
| 101 | been far less problematic or relatively rare and I've left the defaults | ||
| 102 | set to 0 for both parameters, effectively turning off that filter. | ||
| 103 | |||
| 104 | I don't know what the optimal values are for these filters. If the defaults | ||
| 105 | don't work for you, please play with the parameters. If you do find other | ||
| 106 | values more comfortable, I would appreciate feedback. | ||
| 107 | |||
| 108 | The calibration of these devices does drift over time. If ghosts or contact | ||
| 109 | dropping worsen and interfere with the normal usage of your device, try | ||
| 110 | recalibrating it. | ||
| 111 | |||
| 112 | |||
| 113 | Calibration | ||
| 114 | ----------- | ||
| 115 | |||
| 116 | The N-Trig windows tools provide calibration and testing routines. Also an | ||
| 117 | unofficial unsupported set of user space tools including a calibrator is | ||
| 118 | available at: | ||
| 119 | http://code.launchpad.net/~rafi-seas/+junk/ntrig_calib | ||
| 120 | |||
| 121 | |||
| 122 | Tracking | ||
| 123 | -------- | ||
| 124 | |||
| 125 | As of yet, all tested N-Trig firmwares do not track fingers. When multiple | ||
| 126 | contacts are active they seem to be sorted primarily by Y position. | ||
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 6369ba7f96f8..3052e2969ad0 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
| @@ -56,20 +56,20 @@ menu "Special HID drivers" | |||
| 56 | depends on HID | 56 | depends on HID |
| 57 | 57 | ||
| 58 | config HID_3M_PCT | 58 | config HID_3M_PCT |
| 59 | tristate "3M PCT" | 59 | tristate "3M PCT touchscreen" |
| 60 | depends on USB_HID | 60 | depends on USB_HID |
| 61 | ---help--- | 61 | ---help--- |
| 62 | Support for 3M PCT touch screens. | 62 | Support for 3M PCT touch screens. |
| 63 | 63 | ||
| 64 | config HID_A4TECH | 64 | config HID_A4TECH |
| 65 | tristate "A4 tech" if EMBEDDED | 65 | tristate "A4 tech mice" if EMBEDDED |
| 66 | depends on USB_HID | 66 | depends on USB_HID |
| 67 | default !EMBEDDED | 67 | default !EMBEDDED |
| 68 | ---help--- | 68 | ---help--- |
| 69 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. | 69 | Support for A4 tech X5 and WOP-35 / Trust 450L mice. |
| 70 | 70 | ||
| 71 | config HID_ACRUX_FF | 71 | config HID_ACRUX_FF |
| 72 | tristate "ACRUX force feedback support" | 72 | tristate "ACRUX force feedback" |
| 73 | depends on USB_HID | 73 | depends on USB_HID |
| 74 | select INPUT_FF_MEMLESS | 74 | select INPUT_FF_MEMLESS |
| 75 | ---help--- | 75 | ---help--- |
| @@ -77,7 +77,7 @@ config HID_ACRUX_FF | |||
| 77 | game controllers. | 77 | game controllers. |
| 78 | 78 | ||
| 79 | config HID_APPLE | 79 | config HID_APPLE |
| 80 | tristate "Apple" if EMBEDDED | 80 | tristate "Apple {i,Power,Mac}Books" if EMBEDDED |
| 81 | depends on (USB_HID || BT_HIDP) | 81 | depends on (USB_HID || BT_HIDP) |
| 82 | default !EMBEDDED | 82 | default !EMBEDDED |
| 83 | ---help--- | 83 | ---help--- |
| @@ -88,7 +88,7 @@ config HID_APPLE | |||
| 88 | MacBooks, MacBook Pros and Apple Aluminum. | 88 | MacBooks, MacBook Pros and Apple Aluminum. |
| 89 | 89 | ||
| 90 | config HID_BELKIN | 90 | config HID_BELKIN |
| 91 | tristate "Belkin" if EMBEDDED | 91 | tristate "Belkin Flip KVM and Wireless keyboard" if EMBEDDED |
| 92 | depends on USB_HID | 92 | depends on USB_HID |
| 93 | default !EMBEDDED | 93 | default !EMBEDDED |
| 94 | ---help--- | 94 | ---help--- |
| @@ -101,14 +101,14 @@ config HID_CANDO | |||
| 101 | Support for Cando dual touch panel. | 101 | Support for Cando dual touch panel. |
| 102 | 102 | ||
| 103 | config HID_CHERRY | 103 | config HID_CHERRY |
| 104 | tristate "Cherry" if EMBEDDED | 104 | tristate "Cherry Cymotion keyboard" if EMBEDDED |
| 105 | depends on USB_HID | 105 | depends on USB_HID |
| 106 | default !EMBEDDED | 106 | default !EMBEDDED |
| 107 | ---help--- | 107 | ---help--- |
| 108 | Support for Cherry Cymotion keyboard. | 108 | Support for Cherry Cymotion keyboard. |
| 109 | 109 | ||
| 110 | config HID_CHICONY | 110 | config HID_CHICONY |
| 111 | tristate "Chicony" if EMBEDDED | 111 | tristate "Chicony Tactical pad" if EMBEDDED |
| 112 | depends on USB_HID | 112 | depends on USB_HID |
| 113 | default !EMBEDDED | 113 | default !EMBEDDED |
| 114 | ---help--- | 114 | ---help--- |
| @@ -130,20 +130,20 @@ config HID_PRODIKEYS | |||
| 130 | and some additional multimedia keys. | 130 | and some additional multimedia keys. |
| 131 | 131 | ||
| 132 | config HID_CYPRESS | 132 | config HID_CYPRESS |
| 133 | tristate "Cypress" if EMBEDDED | 133 | tristate "Cypress mouse and barcode readers" if EMBEDDED |
| 134 | depends on USB_HID | 134 | depends on USB_HID |
| 135 | default !EMBEDDED | 135 | default !EMBEDDED |
| 136 | ---help--- | 136 | ---help--- |
| 137 | Support for cypress mouse and barcode readers. | 137 | Support for cypress mouse and barcode readers. |
| 138 | 138 | ||
| 139 | config HID_DRAGONRISE | 139 | config HID_DRAGONRISE |
| 140 | tristate "DragonRise Inc. support" | 140 | tristate "DragonRise Inc. game controller" |
| 141 | depends on USB_HID | 141 | depends on USB_HID |
| 142 | ---help--- | 142 | ---help--- |
| 143 | Say Y here if you have DragonRise Inc.game controllers. | 143 | Say Y here if you have DragonRise Inc.game controllers. |
| 144 | 144 | ||
| 145 | config DRAGONRISE_FF | 145 | config DRAGONRISE_FF |
| 146 | bool "DragonRise Inc. force feedback support" | 146 | bool "DragonRise Inc. force feedback" |
| 147 | depends on HID_DRAGONRISE | 147 | depends on HID_DRAGONRISE |
| 148 | select INPUT_FF_MEMLESS | 148 | select INPUT_FF_MEMLESS |
| 149 | ---help--- | 149 | ---help--- |
| @@ -157,46 +157,58 @@ config HID_EGALAX | |||
| 157 | Support for the eGalax dual-touch panel. | 157 | Support for the eGalax dual-touch panel. |
| 158 | 158 | ||
| 159 | config HID_ELECOM | 159 | config HID_ELECOM |
| 160 | tristate "ELECOM" | 160 | tristate "ELECOM BM084 bluetooth mouse" |
| 161 | depends on BT_HIDP | 161 | depends on BT_HIDP |
| 162 | ---help--- | 162 | ---help--- |
| 163 | Support for the ELECOM BM084 (bluetooth mouse). | 163 | Support for the ELECOM BM084 (bluetooth mouse). |
| 164 | 164 | ||
| 165 | config HID_EZKEY | 165 | config HID_EZKEY |
| 166 | tristate "Ezkey" if EMBEDDED | 166 | tristate "Ezkey BTC 8193 keyboard" if EMBEDDED |
| 167 | depends on USB_HID | 167 | depends on USB_HID |
| 168 | default !EMBEDDED | 168 | default !EMBEDDED |
| 169 | ---help--- | 169 | ---help--- |
| 170 | Support for Ezkey BTC 8193 keyboard. | 170 | Support for Ezkey BTC 8193 keyboard. |
| 171 | 171 | ||
| 172 | config HID_KYE | 172 | config HID_KYE |
| 173 | tristate "Kye" if EMBEDDED | 173 | tristate "Kye/Genius Ergo Mouse" if EMBEDDED |
| 174 | depends on USB_HID | 174 | depends on USB_HID |
| 175 | default !EMBEDDED | 175 | default !EMBEDDED |
| 176 | ---help--- | 176 | ---help--- |
| 177 | Support for Kye/Genius Ergo Mouse. | 177 | Support for Kye/Genius Ergo Mouse. |
| 178 | 178 | ||
| 179 | config HID_UCLOGIC | ||
| 180 | tristate "UC-Logic" | ||
| 181 | depends on USB_HID | ||
| 182 | ---help--- | ||
| 183 | Support for UC-Logic tablets. | ||
| 184 | |||
| 185 | config HID_WALTOP | ||
| 186 | tristate "Waltop" | ||
| 187 | depends on USB_HID | ||
| 188 | ---help--- | ||
| 189 | Support for Waltop tablets. | ||
| 190 | |||
| 179 | config HID_GYRATION | 191 | config HID_GYRATION |
| 180 | tristate "Gyration" | 192 | tristate "Gyration remote control" |
| 181 | depends on USB_HID | 193 | depends on USB_HID |
| 182 | ---help--- | 194 | ---help--- |
| 183 | Support for Gyration remote control. | 195 | Support for Gyration remote control. |
| 184 | 196 | ||
| 185 | config HID_TWINHAN | 197 | config HID_TWINHAN |
| 186 | tristate "Twinhan" | 198 | tristate "Twinhan IR remote control" |
| 187 | depends on USB_HID | 199 | depends on USB_HID |
| 188 | ---help--- | 200 | ---help--- |
| 189 | Support for Twinhan IR remote control. | 201 | Support for Twinhan IR remote control. |
| 190 | 202 | ||
| 191 | config HID_KENSINGTON | 203 | config HID_KENSINGTON |
| 192 | tristate "Kensington" if EMBEDDED | 204 | tristate "Kensington Slimblade Trackball" if EMBEDDED |
| 193 | depends on USB_HID | 205 | depends on USB_HID |
| 194 | default !EMBEDDED | 206 | default !EMBEDDED |
| 195 | ---help--- | 207 | ---help--- |
| 196 | Support for Kensington Slimblade Trackball. | 208 | Support for Kensington Slimblade Trackball. |
| 197 | 209 | ||
| 198 | config HID_LOGITECH | 210 | config HID_LOGITECH |
| 199 | tristate "Logitech" if EMBEDDED | 211 | tristate "Logitech devices" if EMBEDDED |
| 200 | depends on USB_HID | 212 | depends on USB_HID |
| 201 | default !EMBEDDED | 213 | default !EMBEDDED |
| 202 | ---help--- | 214 | ---help--- |
| @@ -220,12 +232,12 @@ config LOGITECH_FF | |||
| 220 | force feedback. | 232 | force feedback. |
| 221 | 233 | ||
| 222 | config LOGIRUMBLEPAD2_FF | 234 | config LOGIRUMBLEPAD2_FF |
| 223 | bool "Logitech Rumblepad 2 force feedback support" | 235 | bool "Logitech RumblePad/Rumblepad 2 force feedback support" |
| 224 | depends on HID_LOGITECH | 236 | depends on HID_LOGITECH |
| 225 | select INPUT_FF_MEMLESS | 237 | select INPUT_FF_MEMLESS |
| 226 | help | 238 | help |
| 227 | Say Y here if you want to enable force feedback support for Logitech | 239 | Say Y here if you want to enable force feedback support for Logitech |
| 228 | Rumblepad 2 devices. | 240 | RumblePad and Rumblepad 2 devices. |
| 229 | 241 | ||
| 230 | config LOGIG940_FF | 242 | config LOGIG940_FF |
| 231 | bool "Logitech Flight System G940 force feedback support" | 243 | bool "Logitech Flight System G940 force feedback support" |
| @@ -235,6 +247,14 @@ config LOGIG940_FF | |||
| 235 | Say Y here if you want to enable force feedback support for Logitech | 247 | Say Y here if you want to enable force feedback support for Logitech |
| 236 | Flight System G940 devices. | 248 | Flight System G940 devices. |
| 237 | 249 | ||
| 250 | config LOGIWII_FF | ||
| 251 | bool "Logitech Speed Force Wireless force feedback support" | ||
| 252 | depends on HID_LOGITECH | ||
| 253 | select INPUT_FF_MEMLESS | ||
| 254 | help | ||
| 255 | Say Y here if you want to enable force feedback support for Logitech | ||
| 256 | Speed Force Wireless (Wii) devices. | ||
| 257 | |||
| 238 | config HID_MAGICMOUSE | 258 | config HID_MAGICMOUSE |
| 239 | tristate "Apple MagicMouse multi-touch support" | 259 | tristate "Apple MagicMouse multi-touch support" |
| 240 | depends on BT_HIDP | 260 | depends on BT_HIDP |
| @@ -245,39 +265,39 @@ config HID_MAGICMOUSE | |||
| 245 | Apple Wireless "Magic" Mouse. | 265 | Apple Wireless "Magic" Mouse. |
| 246 | 266 | ||
| 247 | config HID_MICROSOFT | 267 | config HID_MICROSOFT |
| 248 | tristate "Microsoft" if EMBEDDED | 268 | tristate "Microsoft non-fully HID-compliant devices" if EMBEDDED |
| 249 | depends on USB_HID | 269 | depends on USB_HID |
| 250 | default !EMBEDDED | 270 | default !EMBEDDED |
| 251 | ---help--- | 271 | ---help--- |
| 252 | Support for Microsoft devices that are not fully compliant with HID standard. | 272 | Support for Microsoft devices that are not fully compliant with HID standard. |
| 253 | 273 | ||
| 254 | config HID_MOSART | 274 | config HID_MOSART |
| 255 | tristate "MosArt" | 275 | tristate "MosArt dual-touch panels" |
| 256 | depends on USB_HID | 276 | depends on USB_HID |
| 257 | ---help--- | 277 | ---help--- |
| 258 | Support for MosArt dual-touch panels. | 278 | Support for MosArt dual-touch panels. |
| 259 | 279 | ||
| 260 | config HID_MONTEREY | 280 | config HID_MONTEREY |
| 261 | tristate "Monterey" if EMBEDDED | 281 | tristate "Monterey Genius KB29E keyboard" if EMBEDDED |
| 262 | depends on USB_HID | 282 | depends on USB_HID |
| 263 | default !EMBEDDED | 283 | default !EMBEDDED |
| 264 | ---help--- | 284 | ---help--- |
| 265 | Support for Monterey Genius KB29E. | 285 | Support for Monterey Genius KB29E. |
| 266 | 286 | ||
| 267 | config HID_NTRIG | 287 | config HID_NTRIG |
| 268 | tristate "NTrig" | 288 | tristate "N-Trig touch screen" |
| 269 | depends on USB_HID | 289 | depends on USB_HID |
| 270 | ---help--- | 290 | ---help--- |
| 271 | Support for N-Trig touch screen. | 291 | Support for N-Trig touch screen. |
| 272 | 292 | ||
| 273 | config HID_ORTEK | 293 | config HID_ORTEK |
| 274 | tristate "Ortek" | 294 | tristate "Ortek WKB-2000 wireless keyboard and mouse trackpad" |
| 275 | depends on USB_HID | 295 | depends on USB_HID |
| 276 | ---help--- | 296 | ---help--- |
| 277 | Support for Ortek WKB-2000 wireless keyboard + mouse trackpad. | 297 | Support for Ortek WKB-2000 wireless keyboard + mouse trackpad. |
| 278 | 298 | ||
| 279 | config HID_PANTHERLORD | 299 | config HID_PANTHERLORD |
| 280 | tristate "Pantherlord support" | 300 | tristate "Pantherlord/GreenAsia game controller" |
| 281 | depends on USB_HID | 301 | depends on USB_HID |
| 282 | ---help--- | 302 | ---help--- |
| 283 | Say Y here if you have a PantherLord/GreenAsia based game controller | 303 | Say Y here if you have a PantherLord/GreenAsia based game controller |
| @@ -292,7 +312,7 @@ config PANTHERLORD_FF | |||
| 292 | or adapter and want to enable force feedback support for it. | 312 | or adapter and want to enable force feedback support for it. |
| 293 | 313 | ||
| 294 | config HID_PETALYNX | 314 | config HID_PETALYNX |
| 295 | tristate "Petalynx" | 315 | tristate "Petalynx Maxter remote control" |
| 296 | depends on USB_HID | 316 | depends on USB_HID |
| 297 | ---help--- | 317 | ---help--- |
| 298 | Support for Petalynx Maxter remote control. | 318 | Support for Petalynx Maxter remote control. |
| @@ -356,7 +376,7 @@ config HID_PICOLCD_LEDS | |||
| 356 | Provide access to PicoLCD's GPO pins via leds class. | 376 | Provide access to PicoLCD's GPO pins via leds class. |
| 357 | 377 | ||
| 358 | config HID_QUANTA | 378 | config HID_QUANTA |
| 359 | tristate "Quanta Optical Touch" | 379 | tristate "Quanta Optical Touch panels" |
| 360 | depends on USB_HID | 380 | depends on USB_HID |
| 361 | ---help--- | 381 | ---help--- |
| 362 | Support for Quanta Optical Touch dual-touch panels. | 382 | Support for Quanta Optical Touch dual-touch panels. |
| @@ -376,32 +396,39 @@ config HID_ROCCAT_KONE | |||
| 376 | ---help--- | 396 | ---help--- |
| 377 | Support for Roccat Kone mouse. | 397 | Support for Roccat Kone mouse. |
| 378 | 398 | ||
| 399 | config HID_ROCCAT_PYRA | ||
| 400 | tristate "Roccat Pyra mouse support" | ||
| 401 | depends on USB_HID | ||
| 402 | select HID_ROCCAT | ||
| 403 | ---help--- | ||
| 404 | Support for Roccat Pyra mouse. | ||
| 405 | |||
| 379 | config HID_SAMSUNG | 406 | config HID_SAMSUNG |
| 380 | tristate "Samsung" | 407 | tristate "Samsung InfraRed remote control or keyboards" |
| 381 | depends on USB_HID | 408 | depends on USB_HID |
| 382 | ---help--- | 409 | ---help--- |
| 383 | Support for Samsung InfraRed remote control or keyboards. | 410 | Support for Samsung InfraRed remote control or keyboards. |
| 384 | 411 | ||
| 385 | config HID_SONY | 412 | config HID_SONY |
| 386 | tristate "Sony" | 413 | tristate "Sony PS3 controller" |
| 387 | depends on USB_HID | 414 | depends on USB_HID |
| 388 | ---help--- | 415 | ---help--- |
| 389 | Support for Sony PS3 controller. | 416 | Support for Sony PS3 controller. |
| 390 | 417 | ||
| 391 | config HID_STANTUM | 418 | config HID_STANTUM |
| 392 | tristate "Stantum" | 419 | tristate "Stantum multitouch panel" |
| 393 | depends on USB_HID | 420 | depends on USB_HID |
| 394 | ---help--- | 421 | ---help--- |
| 395 | Support for Stantum multitouch panel. | 422 | Support for Stantum multitouch panel. |
| 396 | 423 | ||
| 397 | config HID_SUNPLUS | 424 | config HID_SUNPLUS |
| 398 | tristate "Sunplus" | 425 | tristate "Sunplus wireless desktop" |
| 399 | depends on USB_HID | 426 | depends on USB_HID |
| 400 | ---help--- | 427 | ---help--- |
| 401 | Support for Sunplus wireless desktop. | 428 | Support for Sunplus wireless desktop. |
| 402 | 429 | ||
| 403 | config HID_GREENASIA | 430 | config HID_GREENASIA |
| 404 | tristate "GreenAsia (Product ID 0x12) support" | 431 | tristate "GreenAsia (Product ID 0x12) game controller support" |
| 405 | depends on USB_HID | 432 | depends on USB_HID |
| 406 | ---help--- | 433 | ---help--- |
| 407 | Say Y here if you have a GreenAsia (Product ID 0x12) based game | 434 | Say Y here if you have a GreenAsia (Product ID 0x12) based game |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 46f037f3df80..c335605b9200 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
| @@ -21,6 +21,9 @@ endif | |||
| 21 | ifdef CONFIG_LOGIG940_FF | 21 | ifdef CONFIG_LOGIG940_FF |
| 22 | hid-logitech-objs += hid-lg3ff.o | 22 | hid-logitech-objs += hid-lg3ff.o |
| 23 | endif | 23 | endif |
| 24 | ifdef CONFIG_LOGIWII_FF | ||
| 25 | hid-logitech-objs += hid-lg4ff.o | ||
| 26 | endif | ||
| 24 | 27 | ||
| 25 | obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o | 28 | obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o |
| 26 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o | 29 | obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o |
| @@ -52,6 +55,7 @@ obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o | |||
| 52 | obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o | 55 | obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o |
| 53 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o | 56 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o |
| 54 | obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o | 57 | obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o |
| 58 | obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o | ||
| 55 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o | 59 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o |
| 56 | obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o | 60 | obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o |
| 57 | obj-$(CONFIG_HID_SONY) += hid-sony.o | 61 | obj-$(CONFIG_HID_SONY) += hid-sony.o |
| @@ -61,9 +65,11 @@ obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o | |||
| 61 | obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o | 65 | obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o |
| 62 | obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o | 66 | obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o |
| 63 | obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o | 67 | obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o |
| 68 | obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o | ||
| 64 | obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o | 69 | obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o |
| 65 | obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o | 70 | obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o |
| 66 | obj-$(CONFIG_HID_WACOM) += hid-wacom.o | 71 | obj-$(CONFIG_HID_WACOM) += hid-wacom.o |
| 72 | obj-$(CONFIG_HID_WALTOP) += hid-waltop.o | ||
| 67 | 73 | ||
| 68 | obj-$(CONFIG_USB_HID) += usbhid/ | 74 | obj-$(CONFIG_USB_HID) += usbhid/ |
| 69 | obj-$(CONFIG_USB_MOUSE) += usbhid/ | 75 | obj-$(CONFIG_USB_MOUSE) += usbhid/ |
diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c index 2a0d56b7a02b..02d8cd3b1b1b 100644 --- a/drivers/hid/hid-3m-pct.c +++ b/drivers/hid/hid-3m-pct.c | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | * HID driver for 3M PCT multitouch panels | 2 | * HID driver for 3M PCT multitouch panels |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> | 4 | * Copyright (c) 2009-2010 Stephane Chatty <chatty@enac.fr> |
| 5 | * Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se> | ||
| 6 | * Copyright (c) 2010 Canonical, Ltd. | ||
| 5 | * | 7 | * |
| 6 | */ | 8 | */ |
| 7 | 9 | ||
| @@ -24,15 +26,26 @@ MODULE_LICENSE("GPL"); | |||
| 24 | 26 | ||
| 25 | #include "hid-ids.h" | 27 | #include "hid-ids.h" |
| 26 | 28 | ||
| 29 | #define MAX_SLOTS 60 | ||
| 30 | #define MAX_TRKID USHRT_MAX | ||
| 31 | #define MAX_EVENTS 360 | ||
| 32 | |||
| 33 | /* estimated signal-to-noise ratios */ | ||
| 34 | #define SN_MOVE 2048 | ||
| 35 | #define SN_WIDTH 128 | ||
| 36 | |||
| 27 | struct mmm_finger { | 37 | struct mmm_finger { |
| 28 | __s32 x, y, w, h; | 38 | __s32 x, y, w, h; |
| 29 | __u8 rank; | 39 | __u16 id; |
| 40 | bool prev_touch; | ||
| 30 | bool touch, valid; | 41 | bool touch, valid; |
| 31 | }; | 42 | }; |
| 32 | 43 | ||
| 33 | struct mmm_data { | 44 | struct mmm_data { |
| 34 | struct mmm_finger f[10]; | 45 | struct mmm_finger f[MAX_SLOTS]; |
| 35 | __u8 curid, num; | 46 | __u16 id; |
| 47 | __u8 curid; | ||
| 48 | __u8 nexp, nreal; | ||
| 36 | bool touch, valid; | 49 | bool touch, valid; |
| 37 | }; | 50 | }; |
| 38 | 51 | ||
| @@ -40,6 +53,10 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 40 | struct hid_field *field, struct hid_usage *usage, | 53 | struct hid_field *field, struct hid_usage *usage, |
| 41 | unsigned long **bit, int *max) | 54 | unsigned long **bit, int *max) |
| 42 | { | 55 | { |
| 56 | int f1 = field->logical_minimum; | ||
| 57 | int f2 = field->logical_maximum; | ||
| 58 | int df = f2 - f1; | ||
| 59 | |||
| 43 | switch (usage->hid & HID_USAGE_PAGE) { | 60 | switch (usage->hid & HID_USAGE_PAGE) { |
| 44 | 61 | ||
| 45 | case HID_UP_BUTTON: | 62 | case HID_UP_BUTTON: |
| @@ -50,18 +67,20 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 50 | case HID_GD_X: | 67 | case HID_GD_X: |
| 51 | hid_map_usage(hi, usage, bit, max, | 68 | hid_map_usage(hi, usage, bit, max, |
| 52 | EV_ABS, ABS_MT_POSITION_X); | 69 | EV_ABS, ABS_MT_POSITION_X); |
| 70 | input_set_abs_params(hi->input, ABS_MT_POSITION_X, | ||
| 71 | f1, f2, df / SN_MOVE, 0); | ||
| 53 | /* touchscreen emulation */ | 72 | /* touchscreen emulation */ |
| 54 | input_set_abs_params(hi->input, ABS_X, | 73 | input_set_abs_params(hi->input, ABS_X, |
| 55 | field->logical_minimum, | 74 | f1, f2, df / SN_MOVE, 0); |
| 56 | field->logical_maximum, 0, 0); | ||
| 57 | return 1; | 75 | return 1; |
| 58 | case HID_GD_Y: | 76 | case HID_GD_Y: |
| 59 | hid_map_usage(hi, usage, bit, max, | 77 | hid_map_usage(hi, usage, bit, max, |
| 60 | EV_ABS, ABS_MT_POSITION_Y); | 78 | EV_ABS, ABS_MT_POSITION_Y); |
| 79 | input_set_abs_params(hi->input, ABS_MT_POSITION_Y, | ||
| 80 | f1, f2, df / SN_MOVE, 0); | ||
| 61 | /* touchscreen emulation */ | 81 | /* touchscreen emulation */ |
| 62 | input_set_abs_params(hi->input, ABS_Y, | 82 | input_set_abs_params(hi->input, ABS_Y, |
| 63 | field->logical_minimum, | 83 | f1, f2, df / SN_MOVE, 0); |
| 64 | field->logical_maximum, 0, 0); | ||
| 65 | return 1; | 84 | return 1; |
| 66 | } | 85 | } |
| 67 | return 0; | 86 | return 0; |
| @@ -81,21 +100,31 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 81 | case HID_DG_TIPSWITCH: | 100 | case HID_DG_TIPSWITCH: |
| 82 | /* touchscreen emulation */ | 101 | /* touchscreen emulation */ |
| 83 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | 102 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); |
| 103 | input_set_capability(hi->input, EV_KEY, BTN_TOUCH); | ||
| 84 | return 1; | 104 | return 1; |
| 85 | case HID_DG_WIDTH: | 105 | case HID_DG_WIDTH: |
| 86 | hid_map_usage(hi, usage, bit, max, | 106 | hid_map_usage(hi, usage, bit, max, |
| 87 | EV_ABS, ABS_MT_TOUCH_MAJOR); | 107 | EV_ABS, ABS_MT_TOUCH_MAJOR); |
| 108 | input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR, | ||
| 109 | f1, f2, df / SN_WIDTH, 0); | ||
| 88 | return 1; | 110 | return 1; |
| 89 | case HID_DG_HEIGHT: | 111 | case HID_DG_HEIGHT: |
| 90 | hid_map_usage(hi, usage, bit, max, | 112 | hid_map_usage(hi, usage, bit, max, |
| 91 | EV_ABS, ABS_MT_TOUCH_MINOR); | 113 | EV_ABS, ABS_MT_TOUCH_MINOR); |
| 114 | input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR, | ||
| 115 | f1, f2, df / SN_WIDTH, 0); | ||
| 92 | input_set_abs_params(hi->input, ABS_MT_ORIENTATION, | 116 | input_set_abs_params(hi->input, ABS_MT_ORIENTATION, |
| 93 | 1, 1, 0, 0); | 117 | 0, 1, 0, 0); |
| 94 | return 1; | 118 | return 1; |
| 95 | case HID_DG_CONTACTID: | 119 | case HID_DG_CONTACTID: |
| 96 | field->logical_maximum = 59; | 120 | field->logical_maximum = MAX_TRKID; |
| 97 | hid_map_usage(hi, usage, bit, max, | 121 | hid_map_usage(hi, usage, bit, max, |
| 98 | EV_ABS, ABS_MT_TRACKING_ID); | 122 | EV_ABS, ABS_MT_TRACKING_ID); |
| 123 | input_set_abs_params(hi->input, ABS_MT_TRACKING_ID, | ||
| 124 | 0, MAX_TRKID, 0, 0); | ||
| 125 | if (!hi->input->mt) | ||
| 126 | input_mt_create_slots(hi->input, MAX_SLOTS); | ||
| 127 | input_set_events_per_packet(hi->input, MAX_EVENTS); | ||
| 99 | return 1; | 128 | return 1; |
| 100 | } | 129 | } |
| 101 | /* let hid-input decide for the others */ | 130 | /* let hid-input decide for the others */ |
| @@ -113,10 +142,10 @@ static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
| 113 | struct hid_field *field, struct hid_usage *usage, | 142 | struct hid_field *field, struct hid_usage *usage, |
| 114 | unsigned long **bit, int *max) | 143 | unsigned long **bit, int *max) |
| 115 | { | 144 | { |
| 145 | /* tell hid-input to skip setup of these event types */ | ||
| 116 | if (usage->type == EV_KEY || usage->type == EV_ABS) | 146 | if (usage->type == EV_KEY || usage->type == EV_ABS) |
| 117 | clear_bit(usage->code, *bit); | 147 | set_bit(usage->type, hi->input->evbit); |
| 118 | 148 | return -1; | |
| 119 | return 0; | ||
| 120 | } | 149 | } |
| 121 | 150 | ||
| 122 | /* | 151 | /* |
| @@ -126,70 +155,49 @@ static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
| 126 | static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) | 155 | static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) |
| 127 | { | 156 | { |
| 128 | struct mmm_finger *oldest = 0; | 157 | struct mmm_finger *oldest = 0; |
| 129 | bool pressed = false, released = false; | ||
| 130 | int i; | 158 | int i; |
| 131 | 159 | for (i = 0; i < MAX_SLOTS; ++i) { | |
| 132 | /* | ||
| 133 | * we need to iterate on all fingers to decide if we have a press | ||
| 134 | * or a release event in our touchscreen emulation. | ||
| 135 | */ | ||
| 136 | for (i = 0; i < 10; ++i) { | ||
| 137 | struct mmm_finger *f = &md->f[i]; | 160 | struct mmm_finger *f = &md->f[i]; |
| 138 | if (!f->valid) { | 161 | if (!f->valid) { |
| 139 | /* this finger is just placeholder data, ignore */ | 162 | /* this finger is just placeholder data, ignore */ |
| 140 | } else if (f->touch) { | 163 | continue; |
| 164 | } | ||
| 165 | input_mt_slot(input, i); | ||
| 166 | if (f->touch) { | ||
| 141 | /* this finger is on the screen */ | 167 | /* this finger is on the screen */ |
| 142 | int wide = (f->w > f->h); | 168 | int wide = (f->w > f->h); |
| 143 | input_event(input, EV_ABS, ABS_MT_TRACKING_ID, i); | 169 | /* divided by two to match visual scale of touch */ |
| 170 | int major = max(f->w, f->h) >> 1; | ||
| 171 | int minor = min(f->w, f->h) >> 1; | ||
| 172 | |||
| 173 | if (!f->prev_touch) | ||
| 174 | f->id = md->id++; | ||
| 175 | input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id); | ||
| 144 | input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); | 176 | input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); |
| 145 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); | 177 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); |
| 146 | input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); | 178 | input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); |
| 147 | input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, | 179 | input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); |
| 148 | wide ? f->w : f->h); | 180 | input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); |
| 149 | input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, | 181 | /* touchscreen emulation: pick the oldest contact */ |
| 150 | wide ? f->h : f->w); | 182 | if (!oldest || ((f->id - oldest->id) & (SHRT_MAX + 1))) |
| 151 | input_mt_sync(input); | ||
| 152 | /* | ||
| 153 | * touchscreen emulation: maintain the age rank | ||
| 154 | * of this finger, decide if we have a press | ||
| 155 | */ | ||
| 156 | if (f->rank == 0) { | ||
| 157 | f->rank = ++(md->num); | ||
| 158 | if (f->rank == 1) | ||
| 159 | pressed = true; | ||
| 160 | } | ||
| 161 | if (f->rank == 1) | ||
| 162 | oldest = f; | 183 | oldest = f; |
| 163 | } else { | 184 | } else { |
| 164 | /* this finger took off the screen */ | 185 | /* this finger took off the screen */ |
| 165 | /* touchscreen emulation: maintain age rank of others */ | 186 | input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1); |
| 166 | int j; | ||
| 167 | |||
| 168 | for (j = 0; j < 10; ++j) { | ||
| 169 | struct mmm_finger *g = &md->f[j]; | ||
| 170 | if (g->rank > f->rank) { | ||
| 171 | g->rank--; | ||
| 172 | if (g->rank == 1) | ||
| 173 | oldest = g; | ||
| 174 | } | ||
| 175 | } | ||
| 176 | f->rank = 0; | ||
| 177 | --(md->num); | ||
| 178 | if (md->num == 0) | ||
| 179 | released = true; | ||
| 180 | } | 187 | } |
| 188 | f->prev_touch = f->touch; | ||
| 181 | f->valid = 0; | 189 | f->valid = 0; |
| 182 | } | 190 | } |
| 183 | 191 | ||
| 184 | /* touchscreen emulation */ | 192 | /* touchscreen emulation */ |
| 185 | if (oldest) { | 193 | if (oldest) { |
| 186 | if (pressed) | 194 | input_event(input, EV_KEY, BTN_TOUCH, 1); |
| 187 | input_event(input, EV_KEY, BTN_TOUCH, 1); | ||
| 188 | input_event(input, EV_ABS, ABS_X, oldest->x); | 195 | input_event(input, EV_ABS, ABS_X, oldest->x); |
| 189 | input_event(input, EV_ABS, ABS_Y, oldest->y); | 196 | input_event(input, EV_ABS, ABS_Y, oldest->y); |
| 190 | } else if (released) { | 197 | } else { |
| 191 | input_event(input, EV_KEY, BTN_TOUCH, 0); | 198 | input_event(input, EV_KEY, BTN_TOUCH, 0); |
| 192 | } | 199 | } |
| 200 | input_sync(input); | ||
| 193 | } | 201 | } |
| 194 | 202 | ||
| 195 | /* | 203 | /* |
| @@ -223,10 +231,12 @@ static int mmm_event(struct hid_device *hid, struct hid_field *field, | |||
| 223 | md->f[md->curid].h = value; | 231 | md->f[md->curid].h = value; |
| 224 | break; | 232 | break; |
| 225 | case HID_DG_CONTACTID: | 233 | case HID_DG_CONTACTID: |
| 234 | value = clamp_val(value, 0, MAX_SLOTS - 1); | ||
| 226 | if (md->valid) { | 235 | if (md->valid) { |
| 227 | md->curid = value; | 236 | md->curid = value; |
| 228 | md->f[value].touch = md->touch; | 237 | md->f[value].touch = md->touch; |
| 229 | md->f[value].valid = 1; | 238 | md->f[value].valid = 1; |
| 239 | md->nreal++; | ||
| 230 | } | 240 | } |
| 231 | break; | 241 | break; |
| 232 | case HID_GD_X: | 242 | case HID_GD_X: |
| @@ -238,7 +248,12 @@ static int mmm_event(struct hid_device *hid, struct hid_field *field, | |||
| 238 | md->f[md->curid].y = value; | 248 | md->f[md->curid].y = value; |
| 239 | break; | 249 | break; |
| 240 | case HID_DG_CONTACTCOUNT: | 250 | case HID_DG_CONTACTCOUNT: |
| 241 | mmm_filter_event(md, input); | 251 | if (value) |
| 252 | md->nexp = value; | ||
| 253 | if (md->nreal >= md->nexp) { | ||
| 254 | mmm_filter_event(md, input); | ||
| 255 | md->nreal = 0; | ||
| 256 | } | ||
| 242 | break; | 257 | break; |
| 243 | } | 258 | } |
| 244 | } | 259 | } |
| @@ -255,6 +270,8 @@ static int mmm_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 255 | int ret; | 270 | int ret; |
| 256 | struct mmm_data *md; | 271 | struct mmm_data *md; |
| 257 | 272 | ||
| 273 | hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; | ||
| 274 | |||
| 258 | md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL); | 275 | md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL); |
| 259 | if (!md) { | 276 | if (!md) { |
| 260 | dev_err(&hdev->dev, "cannot allocate 3M data\n"); | 277 | dev_err(&hdev->dev, "cannot allocate 3M data\n"); |
diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c index 3a2b223c1da4..1666c1684e79 100644 --- a/drivers/hid/hid-a4tech.c +++ b/drivers/hid/hid-a4tech.c | |||
| @@ -133,6 +133,8 @@ static const struct hid_device_id a4_devices[] = { | |||
| 133 | .driver_data = A4_2WHEEL_MOUSE_HACK_7 }, | 133 | .driver_data = A4_2WHEEL_MOUSE_HACK_7 }, |
| 134 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D), | 134 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D), |
| 135 | .driver_data = A4_2WHEEL_MOUSE_HACK_B8 }, | 135 | .driver_data = A4_2WHEEL_MOUSE_HACK_B8 }, |
| 136 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649), | ||
| 137 | .driver_data = A4_2WHEEL_MOUSE_HACK_B8 }, | ||
| 136 | { } | 138 | { } |
| 137 | }; | 139 | }; |
| 138 | MODULE_DEVICE_TABLE(hid, a4_devices); | 140 | MODULE_DEVICE_TABLE(hid, a4_devices); |
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index bba05d0a8980..eaeca564a8d3 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c | |||
| @@ -246,17 +246,18 @@ static int apple_event(struct hid_device *hdev, struct hid_field *field, | |||
| 246 | /* | 246 | /* |
| 247 | * MacBook JIS keyboard has wrong logical maximum | 247 | * MacBook JIS keyboard has wrong logical maximum |
| 248 | */ | 248 | */ |
| 249 | static void apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 249 | static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 250 | unsigned int rsize) | 250 | unsigned int *rsize) |
| 251 | { | 251 | { |
| 252 | struct apple_sc *asc = hid_get_drvdata(hdev); | 252 | struct apple_sc *asc = hid_get_drvdata(hdev); |
| 253 | 253 | ||
| 254 | if ((asc->quirks & APPLE_RDESC_JIS) && rsize >= 60 && | 254 | if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 && |
| 255 | rdesc[53] == 0x65 && rdesc[59] == 0x65) { | 255 | rdesc[53] == 0x65 && rdesc[59] == 0x65) { |
| 256 | dev_info(&hdev->dev, "fixing up MacBook JIS keyboard report " | 256 | dev_info(&hdev->dev, "fixing up MacBook JIS keyboard report " |
| 257 | "descriptor\n"); | 257 | "descriptor\n"); |
| 258 | rdesc[53] = rdesc[59] = 0xe7; | 258 | rdesc[53] = rdesc[59] = 0xe7; |
| 259 | } | 259 | } |
| 260 | return rdesc; | ||
| 260 | } | 261 | } |
| 261 | 262 | ||
| 262 | static void apple_setup_input(struct input_dev *input) | 263 | static void apple_setup_input(struct input_dev *input) |
diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c index 24663a8717b1..e880086c2311 100644 --- a/drivers/hid/hid-cherry.c +++ b/drivers/hid/hid-cherry.c | |||
| @@ -26,15 +26,16 @@ | |||
| 26 | * Cherry Cymotion keyboard have an invalid HID report descriptor, | 26 | * Cherry Cymotion keyboard have an invalid HID report descriptor, |
| 27 | * that needs fixing before we can parse it. | 27 | * that needs fixing before we can parse it. |
| 28 | */ | 28 | */ |
| 29 | static void ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 29 | static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 30 | unsigned int rsize) | 30 | unsigned int *rsize) |
| 31 | { | 31 | { |
| 32 | if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { | 32 | if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { |
| 33 | dev_info(&hdev->dev, "fixing up Cherry Cymotion report " | 33 | dev_info(&hdev->dev, "fixing up Cherry Cymotion report " |
| 34 | "descriptor\n"); | 34 | "descriptor\n"); |
| 35 | rdesc[11] = rdesc[16] = 0xff; | 35 | rdesc[11] = rdesc[16] = 0xff; |
| 36 | rdesc[12] = rdesc[17] = 0x03; | 36 | rdesc[12] = rdesc[17] = 0x03; |
| 37 | } | 37 | } |
| 38 | return rdesc; | ||
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | #define ch_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 41 | #define ch_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 3cb6632d4518..7832b6e2478b 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -388,12 +388,6 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) | |||
| 388 | __u32 data; | 388 | __u32 data; |
| 389 | unsigned n; | 389 | unsigned n; |
| 390 | 390 | ||
| 391 | /* Local delimiter could have value 0, which allows size to be 0 */ | ||
| 392 | if (item->size == 0 && item->tag != HID_LOCAL_ITEM_TAG_DELIMITER) { | ||
| 393 | dbg_hid("item data expected for local item\n"); | ||
| 394 | return -1; | ||
| 395 | } | ||
| 396 | |||
| 397 | data = item_udata(item); | 391 | data = item_udata(item); |
| 398 | 392 | ||
| 399 | switch (item->tag) { | 393 | switch (item->tag) { |
| @@ -651,7 +645,7 @@ int hid_parse_report(struct hid_device *device, __u8 *start, | |||
| 651 | }; | 645 | }; |
| 652 | 646 | ||
| 653 | if (device->driver->report_fixup) | 647 | if (device->driver->report_fixup) |
| 654 | device->driver->report_fixup(device, start, size); | 648 | start = device->driver->report_fixup(device, start, &size); |
| 655 | 649 | ||
| 656 | device->rdesc = kmemdup(start, size, GFP_KERNEL); | 650 | device->rdesc = kmemdup(start, size, GFP_KERNEL); |
| 657 | if (device->rdesc == NULL) | 651 | if (device->rdesc == NULL) |
| @@ -1241,6 +1235,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1241 | { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, | 1235 | { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, |
| 1242 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, | 1236 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) }, |
| 1243 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, | 1237 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) }, |
| 1238 | { HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) }, | ||
| 1244 | #if defined(CONFIG_HID_ACRUX_FF) || defined(CONFIG_HID_ACRUX_FF_MODULE) | 1239 | #if defined(CONFIG_HID_ACRUX_FF) || defined(CONFIG_HID_ACRUX_FF_MODULE) |
| 1245 | { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, | 1240 | { HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) }, |
| 1246 | #endif | 1241 | #endif |
| @@ -1248,6 +1243,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1248 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, | 1243 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) }, |
| 1249 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, | 1244 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) }, |
| 1250 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, | 1245 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) }, |
| 1246 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICTRACKPAD) }, | ||
| 1251 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, | 1247 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) }, |
| 1252 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) }, | 1248 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) }, |
| 1253 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) }, | 1249 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) }, |
| @@ -1327,6 +1323,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1327 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, | 1323 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500) }, |
| 1328 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, | 1324 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D) }, |
| 1329 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) }, | 1325 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL) }, |
| 1326 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) }, | ||
| 1330 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, | 1327 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, |
| 1331 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, | 1328 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, |
| 1332 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, | 1329 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, |
| @@ -1336,6 +1333,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1336 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, | 1333 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) }, |
| 1337 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, | 1334 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) }, |
| 1338 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, | 1335 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) }, |
| 1336 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) }, | ||
| 1339 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, | 1337 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) }, |
| 1340 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, | 1338 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, |
| 1341 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, | 1339 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, |
| @@ -1371,12 +1369,15 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1371 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, | 1369 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, |
| 1372 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, | 1370 | { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, |
| 1373 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, | 1371 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, |
| 1372 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, | ||
| 1374 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, | 1373 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, |
| 1375 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, | 1374 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, |
| 1376 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, | 1375 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, |
| 1377 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, | 1376 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, |
| 1378 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, | 1377 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) }, |
| 1379 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, | 1378 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, |
| 1379 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) }, | ||
| 1380 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) }, | ||
| 1380 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, | 1381 | { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) }, |
| 1381 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, | 1382 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) }, |
| 1382 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, | 1383 | { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) }, |
| @@ -1388,8 +1389,16 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1388 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, | 1389 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, |
| 1389 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, | 1390 | { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, |
| 1390 | { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, | 1391 | { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, |
| 1392 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, | ||
| 1393 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, | ||
| 1394 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, | ||
| 1395 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, | ||
| 1391 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, | 1396 | { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, |
| 1392 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, | 1397 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH) }, |
| 1398 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, | ||
| 1399 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, | ||
| 1400 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, | ||
| 1401 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, | ||
| 1393 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, | 1402 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, |
| 1394 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, | 1403 | { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, |
| 1395 | { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, | 1404 | { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, |
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index 998b6f443d7d..4cd0e2345991 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c | |||
| @@ -31,16 +31,16 @@ | |||
| 31 | * Some USB barcode readers from cypress have usage min and usage max in | 31 | * Some USB barcode readers from cypress have usage min and usage max in |
| 32 | * the wrong order | 32 | * the wrong order |
| 33 | */ | 33 | */ |
| 34 | static void cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 34 | static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 35 | unsigned int rsize) | 35 | unsigned int *rsize) |
| 36 | { | 36 | { |
| 37 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | 37 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); |
| 38 | unsigned int i; | 38 | unsigned int i; |
| 39 | 39 | ||
| 40 | if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX)) | 40 | if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX)) |
| 41 | return; | 41 | return rdesc; |
| 42 | 42 | ||
| 43 | for (i = 0; i < rsize - 4; i++) | 43 | for (i = 0; i < *rsize - 4; i++) |
| 44 | if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) { | 44 | if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) { |
| 45 | __u8 tmp; | 45 | __u8 tmp; |
| 46 | 46 | ||
| @@ -50,6 +50,7 @@ static void cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 50 | rdesc[i + 3] = rdesc[i + 1]; | 50 | rdesc[i + 3] = rdesc[i + 1]; |
| 51 | rdesc[i + 1] = tmp; | 51 | rdesc[i + 1] = tmp; |
| 52 | } | 52 | } |
| 53 | return rdesc; | ||
| 53 | } | 54 | } |
| 54 | 55 | ||
| 55 | static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi, | 56 | static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi, |
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 61a3e572224a..75c5e23d09d2 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c | |||
| @@ -570,6 +570,8 @@ void hid_debug_event(struct hid_device *hdev, char *buf) | |||
| 570 | buf[i]; | 570 | buf[i]; |
| 571 | list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE; | 571 | list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE; |
| 572 | } | 572 | } |
| 573 | |||
| 574 | wake_up_interruptible(&hdev->debug_wait); | ||
| 573 | } | 575 | } |
| 574 | EXPORT_SYMBOL_GPL(hid_debug_event); | 576 | EXPORT_SYMBOL_GPL(hid_debug_event); |
| 575 | 577 | ||
diff --git a/drivers/hid/hid-egalax.c b/drivers/hid/hid-egalax.c index 8ca7f65cf2f8..54b017ad258d 100644 --- a/drivers/hid/hid-egalax.c +++ b/drivers/hid/hid-egalax.c | |||
| @@ -31,7 +31,7 @@ struct egalax_data { | |||
| 31 | bool first; /* is this the first finger in the frame? */ | 31 | bool first; /* is this the first finger in the frame? */ |
| 32 | bool valid; /* valid finger data, or just placeholder? */ | 32 | bool valid; /* valid finger data, or just placeholder? */ |
| 33 | bool activity; /* at least one active finger previously? */ | 33 | bool activity; /* at least one active finger previously? */ |
| 34 | __u16 lastx, lasty; /* latest valid (x, y) in the frame */ | 34 | __u16 lastx, lasty, lastz; /* latest valid (x, y, z) in the frame */ |
| 35 | }; | 35 | }; |
| 36 | 36 | ||
| 37 | static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi, | 37 | static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi, |
| @@ -79,6 +79,10 @@ static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 79 | case HID_DG_TIPPRESSURE: | 79 | case HID_DG_TIPPRESSURE: |
| 80 | hid_map_usage(hi, usage, bit, max, | 80 | hid_map_usage(hi, usage, bit, max, |
| 81 | EV_ABS, ABS_MT_PRESSURE); | 81 | EV_ABS, ABS_MT_PRESSURE); |
| 82 | /* touchscreen emulation */ | ||
| 83 | input_set_abs_params(hi->input, ABS_PRESSURE, | ||
| 84 | field->logical_minimum, | ||
| 85 | field->logical_maximum, 0, 0); | ||
| 82 | return 1; | 86 | return 1; |
| 83 | } | 87 | } |
| 84 | return 0; | 88 | return 0; |
| @@ -109,8 +113,8 @@ static void egalax_filter_event(struct egalax_data *td, struct input_dev *input) | |||
| 109 | if (td->valid) { | 113 | if (td->valid) { |
| 110 | /* emit multitouch events */ | 114 | /* emit multitouch events */ |
| 111 | input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); | 115 | input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); |
| 112 | input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); | 116 | input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x >> 3); |
| 113 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); | 117 | input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y >> 3); |
| 114 | input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z); | 118 | input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z); |
| 115 | 119 | ||
| 116 | input_mt_sync(input); | 120 | input_mt_sync(input); |
| @@ -121,6 +125,7 @@ static void egalax_filter_event(struct egalax_data *td, struct input_dev *input) | |||
| 121 | */ | 125 | */ |
| 122 | td->lastx = td->x; | 126 | td->lastx = td->x; |
| 123 | td->lasty = td->y; | 127 | td->lasty = td->y; |
| 128 | td->lastz = td->z; | ||
| 124 | } | 129 | } |
| 125 | 130 | ||
| 126 | /* | 131 | /* |
| @@ -129,8 +134,9 @@ static void egalax_filter_event(struct egalax_data *td, struct input_dev *input) | |||
| 129 | * the oldest on the panel, the one we want for single touch | 134 | * the oldest on the panel, the one we want for single touch |
| 130 | */ | 135 | */ |
| 131 | if (!td->first && td->activity) { | 136 | if (!td->first && td->activity) { |
| 132 | input_event(input, EV_ABS, ABS_X, td->lastx); | 137 | input_event(input, EV_ABS, ABS_X, td->lastx >> 3); |
| 133 | input_event(input, EV_ABS, ABS_Y, td->lasty); | 138 | input_event(input, EV_ABS, ABS_Y, td->lasty >> 3); |
| 139 | input_event(input, EV_ABS, ABS_PRESSURE, td->lastz); | ||
| 134 | } | 140 | } |
| 135 | 141 | ||
| 136 | if (!td->valid) { | 142 | if (!td->valid) { |
diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c index 7a40878f46b4..6e31f305397d 100644 --- a/drivers/hid/hid-elecom.c +++ b/drivers/hid/hid-elecom.c | |||
| @@ -20,14 +20,15 @@ | |||
| 20 | 20 | ||
| 21 | #include "hid-ids.h" | 21 | #include "hid-ids.h" |
| 22 | 22 | ||
| 23 | static void elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 23 | static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 24 | unsigned int rsize) | 24 | unsigned int *rsize) |
| 25 | { | 25 | { |
| 26 | if (rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) { | 26 | if (*rsize >= 48 && rdesc[46] == 0x05 && rdesc[47] == 0x0c) { |
| 27 | dev_info(&hdev->dev, "Fixing up Elecom BM084 " | 27 | dev_info(&hdev->dev, "Fixing up Elecom BM084 " |
| 28 | "report descriptor.\n"); | 28 | "report descriptor.\n"); |
| 29 | rdesc[47] = 0x00; | 29 | rdesc[47] = 0x00; |
| 30 | } | 30 | } |
| 31 | return rdesc; | ||
| 31 | } | 32 | } |
| 32 | 33 | ||
| 33 | static const struct hid_device_id elecom_devices[] = { | 34 | static const struct hid_device_id elecom_devices[] = { |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 855aa8e355f4..3ee999d33004 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #define USB_VENDOR_ID_A4TECH 0x09da | 25 | #define USB_VENDOR_ID_A4TECH 0x09da |
| 26 | #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 | 26 | #define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006 |
| 27 | #define USB_DEVICE_ID_A4TECH_X5_005D 0x000a | 27 | #define USB_DEVICE_ID_A4TECH_X5_005D 0x000a |
| 28 | #define USB_DEVICE_ID_A4TECH_RP_649 0x001a | ||
| 28 | 29 | ||
| 29 | #define USB_VENDOR_ID_AASHIMA 0x06d6 | 30 | #define USB_VENDOR_ID_AASHIMA 0x06d6 |
| 30 | #define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 | 31 | #define USB_DEVICE_ID_AASHIMA_GAMEPAD 0x0025 |
| @@ -63,6 +64,7 @@ | |||
| 63 | #define USB_VENDOR_ID_APPLE 0x05ac | 64 | #define USB_VENDOR_ID_APPLE 0x05ac |
| 64 | #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 | 65 | #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 |
| 65 | #define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d | 66 | #define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d |
| 67 | #define USB_DEVICE_ID_APPLE_MAGICTRACKPAD 0x030e | ||
| 66 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e | 68 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e |
| 67 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f | 69 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f |
| 68 | #define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214 | 70 | #define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214 |
| @@ -142,6 +144,7 @@ | |||
| 142 | #define USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE 0x0051 | 144 | #define USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE 0x0051 |
| 143 | #define USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE 0x00ff | 145 | #define USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE 0x00ff |
| 144 | #define USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK 0x00d3 | 146 | #define USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK 0x00d3 |
| 147 | #define USB_DEVICE_ID_CH_AXIS_295 0x001c | ||
| 145 | 148 | ||
| 146 | #define USB_VENDOR_ID_CHERRY 0x046a | 149 | #define USB_VENDOR_ID_CHERRY 0x046a |
| 147 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 | 150 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 |
| @@ -343,6 +346,7 @@ | |||
| 343 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 | 346 | #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 |
| 344 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 | 347 | #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 |
| 345 | #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f | 348 | #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f |
| 349 | #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD 0xc20a | ||
| 346 | #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211 | 350 | #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD 0xc211 |
| 347 | #define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215 | 351 | #define USB_DEVICE_ID_LOGITECH_EXTREME_3D 0xc215 |
| 348 | #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218 | 352 | #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218 |
| @@ -354,6 +358,7 @@ | |||
| 354 | #define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG 0xc293 | 358 | #define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG 0xc293 |
| 355 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 | 359 | #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 |
| 356 | #define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 | 360 | #define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 |
| 361 | #define USB_DEVICE_ID_LOGITECH_WII_WHEEL 0xc29c | ||
| 357 | #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a | 362 | #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a |
| 358 | #define USB_DEVICE_ID_S510_RECEIVER 0xc50c | 363 | #define USB_DEVICE_ID_S510_RECEIVER 0xc50c |
| 359 | #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 | 364 | #define USB_DEVICE_ID_S510_RECEIVER_2 0xc517 |
| @@ -466,6 +471,8 @@ | |||
| 466 | 471 | ||
| 467 | #define USB_VENDOR_ID_ROCCAT 0x1e7d | 472 | #define USB_VENDOR_ID_ROCCAT 0x1e7d |
| 468 | #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced | 473 | #define USB_DEVICE_ID_ROCCAT_KONE 0x2ced |
| 474 | #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED 0x2c24 | ||
| 475 | #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS 0x2cf6 | ||
| 469 | 476 | ||
| 470 | #define USB_VENDOR_ID_SAITEK 0x06a3 | 477 | #define USB_VENDOR_ID_SAITEK 0x06a3 |
| 471 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 | 478 | #define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17 |
| @@ -485,6 +492,12 @@ | |||
| 485 | #define USB_VENDOR_ID_STANTUM 0x1f87 | 492 | #define USB_VENDOR_ID_STANTUM 0x1f87 |
| 486 | #define USB_DEVICE_ID_MTP 0x0002 | 493 | #define USB_DEVICE_ID_MTP 0x0002 |
| 487 | 494 | ||
| 495 | #define USB_VENDOR_ID_STANTUM_STM 0x0483 | ||
| 496 | #define USB_DEVICE_ID_MTP_STM 0x3261 | ||
| 497 | |||
| 498 | #define USB_VENDOR_ID_STANTUM_SITRONIX 0x1403 | ||
| 499 | #define USB_DEVICE_ID_MTP_SITRONIX 0x5001 | ||
| 500 | |||
| 488 | #define USB_VENDOR_ID_SUN 0x0430 | 501 | #define USB_VENDOR_ID_SUN 0x0430 |
| 489 | #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab | 502 | #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab |
| 490 | 503 | ||
| @@ -514,8 +527,10 @@ | |||
| 514 | 527 | ||
| 515 | #define USB_VENDOR_ID_UCLOGIC 0x5543 | 528 | #define USB_VENDOR_ID_UCLOGIC 0x5543 |
| 516 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 | 529 | #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 |
| 517 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 | ||
| 518 | #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 | 530 | #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 |
| 531 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 | ||
| 532 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 | ||
| 533 | #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 | ||
| 519 | 534 | ||
| 520 | #define USB_VENDOR_ID_VERNIER 0x08f7 | 535 | #define USB_VENDOR_ID_VERNIER 0x08f7 |
| 521 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 | 536 | #define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 |
| @@ -527,6 +542,12 @@ | |||
| 527 | #define USB_VENDOR_ID_WACOM 0x056a | 542 | #define USB_VENDOR_ID_WACOM 0x056a |
| 528 | #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 | 543 | #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 |
| 529 | 544 | ||
| 545 | #define USB_VENDOR_ID_WALTOP 0x172f | ||
| 546 | #define USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH 0x0032 | ||
| 547 | #define USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH 0x0034 | ||
| 548 | #define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH 0x0501 | ||
| 549 | #define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH 0x0500 | ||
| 550 | |||
| 530 | #define USB_VENDOR_ID_WISEGROUP 0x0925 | 551 | #define USB_VENDOR_ID_WISEGROUP 0x0925 |
| 531 | #define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 | 552 | #define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 |
| 532 | #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 | 553 | #define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 6c03dcc5760a..834ef47b76d6 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
| @@ -149,6 +149,83 @@ static int hidinput_setkeycode(struct input_dev *dev, | |||
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | 151 | ||
| 152 | /** | ||
| 153 | * hidinput_calc_abs_res - calculate an absolute axis resolution | ||
| 154 | * @field: the HID report field to calculate resolution for | ||
| 155 | * @code: axis code | ||
| 156 | * | ||
| 157 | * The formula is: | ||
| 158 | * (logical_maximum - logical_minimum) | ||
| 159 | * resolution = ---------------------------------------------------------- | ||
| 160 | * (physical_maximum - physical_minimum) * 10 ^ unit_exponent | ||
| 161 | * | ||
| 162 | * as seen in the HID specification v1.11 6.2.2.7 Global Items. | ||
| 163 | * | ||
| 164 | * Only exponent 1 length units are processed. Centimeters are converted to | ||
| 165 | * inches. Degrees are converted to radians. | ||
| 166 | */ | ||
| 167 | static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) | ||
| 168 | { | ||
| 169 | __s32 unit_exponent = field->unit_exponent; | ||
| 170 | __s32 logical_extents = field->logical_maximum - | ||
| 171 | field->logical_minimum; | ||
| 172 | __s32 physical_extents = field->physical_maximum - | ||
| 173 | field->physical_minimum; | ||
| 174 | __s32 prev; | ||
| 175 | |||
| 176 | /* Check if the extents are sane */ | ||
| 177 | if (logical_extents <= 0 || physical_extents <= 0) | ||
| 178 | return 0; | ||
| 179 | |||
| 180 | /* | ||
| 181 | * Verify and convert units. | ||
| 182 | * See HID specification v1.11 6.2.2.7 Global Items for unit decoding | ||
| 183 | */ | ||
| 184 | if (code == ABS_X || code == ABS_Y || code == ABS_Z) { | ||
| 185 | if (field->unit == 0x11) { /* If centimeters */ | ||
| 186 | /* Convert to inches */ | ||
| 187 | prev = logical_extents; | ||
| 188 | logical_extents *= 254; | ||
| 189 | if (logical_extents < prev) | ||
| 190 | return 0; | ||
| 191 | unit_exponent += 2; | ||
| 192 | } else if (field->unit != 0x13) { /* If not inches */ | ||
| 193 | return 0; | ||
| 194 | } | ||
| 195 | } else if (code == ABS_RX || code == ABS_RY || code == ABS_RZ) { | ||
| 196 | if (field->unit == 0x14) { /* If degrees */ | ||
| 197 | /* Convert to radians */ | ||
| 198 | prev = logical_extents; | ||
| 199 | logical_extents *= 573; | ||
| 200 | if (logical_extents < prev) | ||
| 201 | return 0; | ||
| 202 | unit_exponent += 1; | ||
| 203 | } else if (field->unit != 0x12) { /* If not radians */ | ||
| 204 | return 0; | ||
| 205 | } | ||
| 206 | } else { | ||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | /* Apply negative unit exponent */ | ||
| 211 | for (; unit_exponent < 0; unit_exponent++) { | ||
| 212 | prev = logical_extents; | ||
| 213 | logical_extents *= 10; | ||
| 214 | if (logical_extents < prev) | ||
| 215 | return 0; | ||
| 216 | } | ||
| 217 | /* Apply positive unit exponent */ | ||
| 218 | for (; unit_exponent > 0; unit_exponent--) { | ||
| 219 | prev = physical_extents; | ||
| 220 | physical_extents *= 10; | ||
| 221 | if (physical_extents < prev) | ||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | /* Calculate resolution */ | ||
| 226 | return logical_extents / physical_extents; | ||
| 227 | } | ||
| 228 | |||
| 152 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, | 229 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, |
| 153 | struct hid_usage *usage) | 230 | struct hid_usage *usage) |
| 154 | { | 231 | { |
| @@ -336,6 +413,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 336 | map_key_clear(BTN_STYLUS); | 413 | map_key_clear(BTN_STYLUS); |
| 337 | break; | 414 | break; |
| 338 | 415 | ||
| 416 | case 0x46: /* TabletPick */ | ||
| 417 | map_key_clear(BTN_STYLUS2); | ||
| 418 | break; | ||
| 419 | |||
| 339 | default: goto unknown; | 420 | default: goto unknown; |
| 340 | } | 421 | } |
| 341 | break; | 422 | break; |
| @@ -537,6 +618,9 @@ mapped: | |||
| 537 | input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); | 618 | input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); |
| 538 | else input_set_abs_params(input, usage->code, a, b, 0, 0); | 619 | else input_set_abs_params(input, usage->code, a, b, 0, 0); |
| 539 | 620 | ||
| 621 | input_abs_set_res(input, usage->code, | ||
| 622 | hidinput_calc_abs_res(field, usage->code)); | ||
| 623 | |||
| 540 | /* use a larger default input buffer for MT devices */ | 624 | /* use a larger default input buffer for MT devices */ |
| 541 | if (usage->code == ABS_MT_POSITION_X && input->hint_events_per_packet == 0) | 625 | if (usage->code == ABS_MT_POSITION_X && input->hint_events_per_packet == 0) |
| 542 | input_set_events_per_packet(input, 60); | 626 | input_set_events_per_packet(input, 60); |
| @@ -659,6 +743,9 @@ void hidinput_report_event(struct hid_device *hid, struct hid_report *report) | |||
| 659 | { | 743 | { |
| 660 | struct hid_input *hidinput; | 744 | struct hid_input *hidinput; |
| 661 | 745 | ||
| 746 | if (hid->quirks & HID_QUIRK_NO_INPUT_SYNC) | ||
| 747 | return; | ||
| 748 | |||
| 662 | list_for_each_entry(hidinput, &hid->inputs, list) | 749 | list_for_each_entry(hidinput, &hid->inputs, list) |
| 663 | input_sync(hidinput->input); | 750 | input_sync(hidinput->input); |
| 664 | } | 751 | } |
diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c index f8871712b7b5..817247ee006c 100644 --- a/drivers/hid/hid-kye.c +++ b/drivers/hid/hid-kye.c | |||
| @@ -23,10 +23,10 @@ | |||
| 23 | * - report size 8 count 1 must be size 1 count 8 for button bitfield | 23 | * - report size 8 count 1 must be size 1 count 8 for button bitfield |
| 24 | * - change the button usage range to 4-7 for the extra buttons | 24 | * - change the button usage range to 4-7 for the extra buttons |
| 25 | */ | 25 | */ |
| 26 | static void kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 26 | static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 27 | unsigned int rsize) | 27 | unsigned int *rsize) |
| 28 | { | 28 | { |
| 29 | if (rsize >= 74 && | 29 | if (*rsize >= 74 && |
| 30 | rdesc[61] == 0x05 && rdesc[62] == 0x08 && | 30 | rdesc[61] == 0x05 && rdesc[62] == 0x08 && |
| 31 | rdesc[63] == 0x19 && rdesc[64] == 0x08 && | 31 | rdesc[63] == 0x19 && rdesc[64] == 0x08 && |
| 32 | rdesc[65] == 0x29 && rdesc[66] == 0x0f && | 32 | rdesc[65] == 0x29 && rdesc[66] == 0x0f && |
| @@ -40,6 +40,7 @@ static void kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 40 | rdesc[72] = 0x01; | 40 | rdesc[72] = 0x01; |
| 41 | rdesc[74] = 0x08; | 41 | rdesc[74] = 0x08; |
| 42 | } | 42 | } |
| 43 | return rdesc; | ||
| 43 | } | 44 | } |
| 44 | 45 | ||
| 45 | static const struct hid_device_id kye_devices[] = { | 46 | static const struct hid_device_id kye_devices[] = { |
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index f6433d8050a9..b629fba5a057 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | * Copyright (c) 2006-2007 Jiri Kosina | 7 | * Copyright (c) 2006-2007 Jiri Kosina |
| 8 | * Copyright (c) 2007 Paul Walmsley | 8 | * Copyright (c) 2007 Paul Walmsley |
| 9 | * Copyright (c) 2008 Jiri Slaby | 9 | * Copyright (c) 2008 Jiri Slaby |
| 10 | * Copyright (c) 2010 Hendrik Iben | ||
| 10 | */ | 11 | */ |
| 11 | 12 | ||
| 12 | /* | 13 | /* |
| @@ -19,6 +20,9 @@ | |||
| 19 | #include <linux/device.h> | 20 | #include <linux/device.h> |
| 20 | #include <linux/hid.h> | 21 | #include <linux/hid.h> |
| 21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/random.h> | ||
| 24 | #include <linux/sched.h> | ||
| 25 | #include <linux/wait.h> | ||
| 22 | 26 | ||
| 23 | #include "hid-ids.h" | 27 | #include "hid-ids.h" |
| 24 | #include "hid-lg.h" | 28 | #include "hid-lg.h" |
| @@ -35,31 +39,43 @@ | |||
| 35 | #define LG_FF2 0x400 | 39 | #define LG_FF2 0x400 |
| 36 | #define LG_RDESC_REL_ABS 0x800 | 40 | #define LG_RDESC_REL_ABS 0x800 |
| 37 | #define LG_FF3 0x1000 | 41 | #define LG_FF3 0x1000 |
| 42 | #define LG_FF4 0x2000 | ||
| 38 | 43 | ||
| 39 | /* | 44 | /* |
| 40 | * Certain Logitech keyboards send in report #3 keys which are far | 45 | * Certain Logitech keyboards send in report #3 keys which are far |
| 41 | * above the logical maximum described in descriptor. This extends | 46 | * above the logical maximum described in descriptor. This extends |
| 42 | * the original value of 0x28c of logical maximum to 0x104d | 47 | * the original value of 0x28c of logical maximum to 0x104d |
| 43 | */ | 48 | */ |
| 44 | static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 49 | static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 45 | unsigned int rsize) | 50 | unsigned int *rsize) |
| 46 | { | 51 | { |
| 47 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | 52 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); |
| 48 | 53 | ||
| 49 | if ((quirks & LG_RDESC) && rsize >= 90 && rdesc[83] == 0x26 && | 54 | if ((quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && |
| 50 | rdesc[84] == 0x8c && rdesc[85] == 0x02) { | 55 | rdesc[84] == 0x8c && rdesc[85] == 0x02) { |
| 51 | dev_info(&hdev->dev, "fixing up Logitech keyboard report " | 56 | dev_info(&hdev->dev, "fixing up Logitech keyboard report " |
| 52 | "descriptor\n"); | 57 | "descriptor\n"); |
| 53 | rdesc[84] = rdesc[89] = 0x4d; | 58 | rdesc[84] = rdesc[89] = 0x4d; |
| 54 | rdesc[85] = rdesc[90] = 0x10; | 59 | rdesc[85] = rdesc[90] = 0x10; |
| 55 | } | 60 | } |
| 56 | if ((quirks & LG_RDESC_REL_ABS) && rsize >= 50 && | 61 | if ((quirks & LG_RDESC_REL_ABS) && *rsize >= 50 && |
| 57 | rdesc[32] == 0x81 && rdesc[33] == 0x06 && | 62 | rdesc[32] == 0x81 && rdesc[33] == 0x06 && |
| 58 | rdesc[49] == 0x81 && rdesc[50] == 0x06) { | 63 | rdesc[49] == 0x81 && rdesc[50] == 0x06) { |
| 59 | dev_info(&hdev->dev, "fixing up rel/abs in Logitech " | 64 | dev_info(&hdev->dev, "fixing up rel/abs in Logitech " |
| 60 | "report descriptor\n"); | 65 | "report descriptor\n"); |
| 61 | rdesc[33] = rdesc[50] = 0x02; | 66 | rdesc[33] = rdesc[50] = 0x02; |
| 62 | } | 67 | } |
| 68 | if ((quirks & LG_FF4) && *rsize >= 101 && | ||
| 69 | rdesc[41] == 0x95 && rdesc[42] == 0x0B && | ||
| 70 | rdesc[47] == 0x05 && rdesc[48] == 0x09) { | ||
| 71 | dev_info(&hdev->dev, "fixing up Logitech Speed Force Wireless " | ||
| 72 | "button descriptor\n"); | ||
| 73 | rdesc[41] = 0x05; | ||
| 74 | rdesc[42] = 0x09; | ||
| 75 | rdesc[47] = 0x95; | ||
| 76 | rdesc[48] = 0x0B; | ||
| 77 | } | ||
| 78 | return rdesc; | ||
| 63 | } | 79 | } |
| 64 | 80 | ||
| 65 | #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 81 | #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
| @@ -285,12 +301,33 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 285 | goto err_free; | 301 | goto err_free; |
| 286 | } | 302 | } |
| 287 | 303 | ||
| 304 | if (quirks & LG_FF4) { | ||
| 305 | unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
| 306 | |||
| 307 | ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); | ||
| 308 | |||
| 309 | if (ret >= 0) { | ||
| 310 | /* insert a little delay of 10 jiffies ~ 40ms */ | ||
| 311 | wait_queue_head_t wait; | ||
| 312 | init_waitqueue_head (&wait); | ||
| 313 | wait_event_interruptible_timeout(wait, 0, 10); | ||
| 314 | |||
| 315 | /* Select random Address */ | ||
| 316 | buf[1] = 0xB2; | ||
| 317 | get_random_bytes(&buf[2], 2); | ||
| 318 | |||
| 319 | ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 288 | if (quirks & LG_FF) | 323 | if (quirks & LG_FF) |
| 289 | lgff_init(hdev); | 324 | lgff_init(hdev); |
| 290 | if (quirks & LG_FF2) | 325 | if (quirks & LG_FF2) |
| 291 | lg2ff_init(hdev); | 326 | lg2ff_init(hdev); |
| 292 | if (quirks & LG_FF3) | 327 | if (quirks & LG_FF3) |
| 293 | lg3ff_init(hdev); | 328 | lg3ff_init(hdev); |
| 329 | if (quirks & LG_FF4) | ||
| 330 | lg4ff_init(hdev); | ||
| 294 | 331 | ||
| 295 | return 0; | 332 | return 0; |
| 296 | err_free: | 333 | err_free: |
| @@ -325,6 +362,8 @@ static const struct hid_device_id lg_devices[] = { | |||
| 325 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), | 362 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), |
| 326 | .driver_data = LG_NOGET | LG_FF }, | 363 | .driver_data = LG_NOGET | LG_FF }, |
| 327 | 364 | ||
| 365 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD), | ||
| 366 | .driver_data = LG_FF2 }, | ||
| 328 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD), | 367 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD), |
| 329 | .driver_data = LG_FF }, | 368 | .driver_data = LG_FF }, |
| 330 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2), | 369 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2), |
| @@ -339,6 +378,8 @@ static const struct hid_device_id lg_devices[] = { | |||
| 339 | .driver_data = LG_FF }, | 378 | .driver_data = LG_FF }, |
| 340 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), | 379 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), |
| 341 | .driver_data = LG_FF }, | 380 | .driver_data = LG_FF }, |
| 381 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), | ||
| 382 | .driver_data = LG_FF4 }, | ||
| 342 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), | 383 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), |
| 343 | .driver_data = LG_FF }, | 384 | .driver_data = LG_FF }, |
| 344 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), | 385 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), |
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h index ce2ac8672624..b0100ba2ae0b 100644 --- a/drivers/hid/hid-lg.h +++ b/drivers/hid/hid-lg.h | |||
| @@ -19,4 +19,10 @@ int lg3ff_init(struct hid_device *hdev); | |||
| 19 | static inline int lg3ff_init(struct hid_device *hdev) { return -1; } | 19 | static inline int lg3ff_init(struct hid_device *hdev) { return -1; } |
| 20 | #endif | 20 | #endif |
| 21 | 21 | ||
| 22 | #ifdef CONFIG_LOGIWII_FF | ||
| 23 | int lg4ff_init(struct hid_device *hdev); | ||
| 24 | #else | ||
| 25 | static inline int lg4ff_init(struct hid_device *hdev) { return -1; } | ||
| 26 | #endif | ||
| 27 | |||
| 22 | #endif | 28 | #endif |
diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c index d888f1e6794f..4258253c36b3 100644 --- a/drivers/hid/hid-lg2ff.c +++ b/drivers/hid/hid-lg2ff.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Force feedback support for Logitech Rumblepad 2 | 2 | * Force feedback support for Logitech RumblePad and Rumblepad 2 |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2008 Anssi Hannula <anssi.hannula@gmail.com> | 4 | * Copyright (c) 2008 Anssi Hannula <anssi.hannula@gmail.com> |
| 5 | */ | 5 | */ |
| @@ -110,7 +110,7 @@ int lg2ff_init(struct hid_device *hid) | |||
| 110 | 110 | ||
| 111 | usbhid_submit_report(hid, report, USB_DIR_OUT); | 111 | usbhid_submit_report(hid, report, USB_DIR_OUT); |
| 112 | 112 | ||
| 113 | dev_info(&hid->dev, "Force feedback for Logitech Rumblepad 2 by " | 113 | dev_info(&hid->dev, "Force feedback for Logitech RumblePad/Rumblepad 2 by " |
| 114 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); | 114 | "Anssi Hannula <anssi.hannula@gmail.com>\n"); |
| 115 | 115 | ||
| 116 | return 0; | 116 | return 0; |
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c new file mode 100644 index 000000000000..7eef5a2ce948 --- /dev/null +++ b/drivers/hid/hid-lg4ff.c | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | /* | ||
| 2 | * Force feedback support for Logitech Speed Force Wireless | ||
| 3 | * | ||
| 4 | * http://wiibrew.org/wiki/Logitech_USB_steering_wheel | ||
| 5 | * | ||
| 6 | * Copyright (c) 2010 Simon Wood <simon@mungewell.org> | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 23 | */ | ||
| 24 | |||
| 25 | |||
| 26 | #include <linux/input.h> | ||
| 27 | #include <linux/usb.h> | ||
| 28 | #include <linux/hid.h> | ||
| 29 | |||
| 30 | #include "usbhid/usbhid.h" | ||
| 31 | #include "hid-lg.h" | ||
| 32 | |||
| 33 | struct lg4ff_device { | ||
| 34 | struct hid_report *report; | ||
| 35 | }; | ||
| 36 | |||
| 37 | static const signed short ff4_wheel_ac[] = { | ||
| 38 | FF_CONSTANT, | ||
| 39 | FF_AUTOCENTER, | ||
| 40 | -1 | ||
| 41 | }; | ||
| 42 | |||
| 43 | static int hid_lg4ff_play(struct input_dev *dev, void *data, | ||
| 44 | struct ff_effect *effect) | ||
| 45 | { | ||
| 46 | struct hid_device *hid = input_get_drvdata(dev); | ||
| 47 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
| 48 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | ||
| 49 | int x; | ||
| 50 | |||
| 51 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff | ||
| 52 | |||
| 53 | switch (effect->type) { | ||
| 54 | case FF_CONSTANT: | ||
| 55 | x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ | ||
| 56 | CLAMP(x); | ||
| 57 | report->field[0]->value[0] = 0x11; /* Slot 1 */ | ||
| 58 | report->field[0]->value[1] = 0x10; | ||
| 59 | report->field[0]->value[2] = x; | ||
| 60 | report->field[0]->value[3] = 0x00; | ||
| 61 | report->field[0]->value[4] = 0x00; | ||
| 62 | report->field[0]->value[5] = 0x08; | ||
| 63 | report->field[0]->value[6] = 0x00; | ||
| 64 | dbg_hid("Autocenter, x=0x%02X\n", x); | ||
| 65 | |||
| 66 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
| 67 | break; | ||
| 68 | } | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | static void hid_lg4ff_set_autocenter(struct input_dev *dev, u16 magnitude) | ||
| 73 | { | ||
| 74 | struct hid_device *hid = input_get_drvdata(dev); | ||
| 75 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
| 76 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | ||
| 77 | __s32 *value = report->field[0]->value; | ||
| 78 | |||
| 79 | *value++ = 0xfe; | ||
| 80 | *value++ = 0x0d; | ||
| 81 | *value++ = 0x07; | ||
| 82 | *value++ = 0x07; | ||
| 83 | *value++ = (magnitude >> 8) & 0xff; | ||
| 84 | *value++ = 0x00; | ||
| 85 | *value = 0x00; | ||
| 86 | |||
| 87 | usbhid_submit_report(hid, report, USB_DIR_OUT); | ||
| 88 | } | ||
| 89 | |||
| 90 | |||
| 91 | int lg4ff_init(struct hid_device *hid) | ||
| 92 | { | ||
| 93 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | ||
| 94 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
| 95 | struct input_dev *dev = hidinput->input; | ||
| 96 | struct hid_report *report; | ||
| 97 | struct hid_field *field; | ||
| 98 | const signed short *ff_bits = ff4_wheel_ac; | ||
| 99 | int error; | ||
| 100 | int i; | ||
| 101 | |||
| 102 | /* Find the report to use */ | ||
| 103 | if (list_empty(report_list)) { | ||
| 104 | err_hid("No output report found"); | ||
| 105 | return -1; | ||
| 106 | } | ||
| 107 | |||
| 108 | /* Check that the report looks ok */ | ||
| 109 | report = list_entry(report_list->next, struct hid_report, list); | ||
| 110 | if (!report) { | ||
| 111 | err_hid("NULL output report"); | ||
| 112 | return -1; | ||
| 113 | } | ||
| 114 | |||
| 115 | field = report->field[0]; | ||
| 116 | if (!field) { | ||
| 117 | err_hid("NULL field"); | ||
| 118 | return -1; | ||
| 119 | } | ||
| 120 | |||
| 121 | for (i = 0; ff_bits[i] >= 0; i++) | ||
| 122 | set_bit(ff_bits[i], dev->ffbit); | ||
| 123 | |||
| 124 | error = input_ff_create_memless(dev, NULL, hid_lg4ff_play); | ||
| 125 | |||
| 126 | if (error) | ||
| 127 | return error; | ||
| 128 | |||
| 129 | if (test_bit(FF_AUTOCENTER, dev->ffbit)) | ||
| 130 | dev->ff->set_autocenter = hid_lg4ff_set_autocenter; | ||
| 131 | |||
| 132 | dev_info(&hid->dev, "Force feedback for Logitech Speed Force Wireless by " | ||
| 133 | "Simon Wood <simon@mungewell.org>\n"); | ||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 319b0e57ee41..e6dc15171664 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | * Apple "Magic" Wireless Mouse driver | 2 | * Apple "Magic" Wireless Mouse driver |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2010 Michael Poole <mdpoole@troilus.org> | 4 | * Copyright (c) 2010 Michael Poole <mdpoole@troilus.org> |
| 5 | * Copyright (c) 2010 Chase Douglas <chase.douglas@canonical.com> | ||
| 5 | */ | 6 | */ |
| 6 | 7 | ||
| 7 | /* | 8 | /* |
| @@ -53,7 +54,9 @@ static bool report_undeciphered; | |||
| 53 | module_param(report_undeciphered, bool, 0644); | 54 | module_param(report_undeciphered, bool, 0644); |
| 54 | MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event"); | 55 | MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event"); |
| 55 | 56 | ||
| 56 | #define TOUCH_REPORT_ID 0x29 | 57 | #define TRACKPAD_REPORT_ID 0x28 |
| 58 | #define MOUSE_REPORT_ID 0x29 | ||
| 59 | #define DOUBLE_REPORT_ID 0xf7 | ||
| 57 | /* These definitions are not precise, but they're close enough. (Bits | 60 | /* These definitions are not precise, but they're close enough. (Bits |
| 58 | * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem | 61 | * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem |
| 59 | * to be some kind of bit mask -- 0x20 may be a near-field reading, | 62 | * to be some kind of bit mask -- 0x20 may be a near-field reading, |
| @@ -67,15 +70,19 @@ MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state fie | |||
| 67 | 70 | ||
| 68 | #define SCROLL_ACCEL_DEFAULT 7 | 71 | #define SCROLL_ACCEL_DEFAULT 7 |
| 69 | 72 | ||
| 73 | /* Single touch emulation should only begin when no touches are currently down. | ||
| 74 | * This is true when single_touch_id is equal to NO_TOUCHES. If multiple touches | ||
| 75 | * are down and the touch providing for single touch emulation is lifted, | ||
| 76 | * single_touch_id is equal to SINGLE_TOUCH_UP. While single touch emulation is | ||
| 77 | * occuring, single_touch_id corresponds with the tracking id of the touch used. | ||
| 78 | */ | ||
| 79 | #define NO_TOUCHES -1 | ||
| 80 | #define SINGLE_TOUCH_UP -2 | ||
| 81 | |||
| 70 | /** | 82 | /** |
| 71 | * struct magicmouse_sc - Tracks Magic Mouse-specific data. | 83 | * struct magicmouse_sc - Tracks Magic Mouse-specific data. |
| 72 | * @input: Input device through which we report events. | 84 | * @input: Input device through which we report events. |
| 73 | * @quirks: Currently unused. | 85 | * @quirks: Currently unused. |
| 74 | * @last_timestamp: Timestamp from most recent (18-bit) touch report | ||
| 75 | * (units of milliseconds over short windows, but seems to | ||
| 76 | * increase faster when there are no touches). | ||
| 77 | * @delta_time: 18-bit difference between the two most recent touch | ||
| 78 | * reports from the mouse. | ||
| 79 | * @ntouches: Number of touches in most recent touch report. | 86 | * @ntouches: Number of touches in most recent touch report. |
| 80 | * @scroll_accel: Number of consecutive scroll motions. | 87 | * @scroll_accel: Number of consecutive scroll motions. |
| 81 | * @scroll_jiffies: Time of last scroll motion. | 88 | * @scroll_jiffies: Time of last scroll motion. |
| @@ -86,8 +93,6 @@ struct magicmouse_sc { | |||
| 86 | struct input_dev *input; | 93 | struct input_dev *input; |
| 87 | unsigned long quirks; | 94 | unsigned long quirks; |
| 88 | 95 | ||
| 89 | int last_timestamp; | ||
| 90 | int delta_time; | ||
| 91 | int ntouches; | 96 | int ntouches; |
| 92 | int scroll_accel; | 97 | int scroll_accel; |
| 93 | unsigned long scroll_jiffies; | 98 | unsigned long scroll_jiffies; |
| @@ -98,9 +103,9 @@ struct magicmouse_sc { | |||
| 98 | short scroll_x; | 103 | short scroll_x; |
| 99 | short scroll_y; | 104 | short scroll_y; |
| 100 | u8 size; | 105 | u8 size; |
| 101 | u8 down; | ||
| 102 | } touches[16]; | 106 | } touches[16]; |
| 103 | int tracking_ids[16]; | 107 | int tracking_ids[16]; |
| 108 | int single_touch_id; | ||
| 104 | }; | 109 | }; |
| 105 | 110 | ||
| 106 | static int magicmouse_firm_touch(struct magicmouse_sc *msc) | 111 | static int magicmouse_firm_touch(struct magicmouse_sc *msc) |
| @@ -166,18 +171,35 @@ static void magicmouse_emit_buttons(struct magicmouse_sc *msc, int state) | |||
| 166 | static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) | 171 | static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata) |
| 167 | { | 172 | { |
| 168 | struct input_dev *input = msc->input; | 173 | struct input_dev *input = msc->input; |
| 169 | __s32 x_y = tdata[0] << 8 | tdata[1] << 16 | tdata[2] << 24; | 174 | int id, x, y, size, orientation, touch_major, touch_minor, state, down; |
| 170 | int misc = tdata[5] | tdata[6] << 8; | 175 | |
| 171 | int id = (misc >> 6) & 15; | 176 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { |
| 172 | int x = x_y << 12 >> 20; | 177 | id = (tdata[6] << 2 | tdata[5] >> 6) & 0xf; |
| 173 | int y = -(x_y >> 20); | 178 | x = (tdata[1] << 28 | tdata[0] << 20) >> 20; |
| 174 | int down = (tdata[7] & TOUCH_STATE_MASK) != TOUCH_STATE_NONE; | 179 | y = -((tdata[2] << 24 | tdata[1] << 16) >> 20); |
| 180 | size = tdata[5] & 0x3f; | ||
| 181 | orientation = (tdata[6] >> 2) - 32; | ||
| 182 | touch_major = tdata[3]; | ||
| 183 | touch_minor = tdata[4]; | ||
| 184 | state = tdata[7] & TOUCH_STATE_MASK; | ||
| 185 | down = state != TOUCH_STATE_NONE; | ||
| 186 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
| 187 | id = (tdata[7] << 2 | tdata[6] >> 6) & 0xf; | ||
| 188 | x = (tdata[1] << 27 | tdata[0] << 19) >> 19; | ||
| 189 | y = -((tdata[3] << 30 | tdata[2] << 22 | tdata[1] << 14) >> 19); | ||
| 190 | size = tdata[6] & 0x3f; | ||
| 191 | orientation = (tdata[7] >> 2) - 32; | ||
| 192 | touch_major = tdata[4]; | ||
| 193 | touch_minor = tdata[5]; | ||
| 194 | state = tdata[8] & TOUCH_STATE_MASK; | ||
| 195 | down = state != TOUCH_STATE_NONE; | ||
| 196 | } | ||
| 175 | 197 | ||
| 176 | /* Store tracking ID and other fields. */ | 198 | /* Store tracking ID and other fields. */ |
| 177 | msc->tracking_ids[raw_id] = id; | 199 | msc->tracking_ids[raw_id] = id; |
| 178 | msc->touches[id].x = x; | 200 | msc->touches[id].x = x; |
| 179 | msc->touches[id].y = y; | 201 | msc->touches[id].y = y; |
| 180 | msc->touches[id].size = misc & 63; | 202 | msc->touches[id].size = size; |
| 181 | 203 | ||
| 182 | /* If requested, emulate a scroll wheel by detecting small | 204 | /* If requested, emulate a scroll wheel by detecting small |
| 183 | * vertical touch motions. | 205 | * vertical touch motions. |
| @@ -188,7 +210,7 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda | |||
| 188 | int step_y = msc->touches[id].scroll_y - y; | 210 | int step_y = msc->touches[id].scroll_y - y; |
| 189 | 211 | ||
| 190 | /* Calculate and apply the scroll motion. */ | 212 | /* Calculate and apply the scroll motion. */ |
| 191 | switch (tdata[7] & TOUCH_STATE_MASK) { | 213 | switch (state) { |
| 192 | case TOUCH_STATE_START: | 214 | case TOUCH_STATE_START: |
| 193 | msc->touches[id].scroll_x = x; | 215 | msc->touches[id].scroll_x = x; |
| 194 | msc->touches[id].scroll_y = y; | 216 | msc->touches[id].scroll_y = y; |
| @@ -222,21 +244,28 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda | |||
| 222 | } | 244 | } |
| 223 | } | 245 | } |
| 224 | 246 | ||
| 247 | if (down) { | ||
| 248 | msc->ntouches++; | ||
| 249 | if (msc->single_touch_id == NO_TOUCHES) | ||
| 250 | msc->single_touch_id = id; | ||
| 251 | } else if (msc->single_touch_id == id) | ||
| 252 | msc->single_touch_id = SINGLE_TOUCH_UP; | ||
| 253 | |||
| 225 | /* Generate the input events for this touch. */ | 254 | /* Generate the input events for this touch. */ |
| 226 | if (report_touches && down) { | 255 | if (report_touches && down) { |
| 227 | int orientation = (misc >> 10) - 32; | ||
| 228 | |||
| 229 | msc->touches[id].down = 1; | ||
| 230 | |||
| 231 | input_report_abs(input, ABS_MT_TRACKING_ID, id); | 256 | input_report_abs(input, ABS_MT_TRACKING_ID, id); |
| 232 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, tdata[3]); | 257 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2); |
| 233 | input_report_abs(input, ABS_MT_TOUCH_MINOR, tdata[4]); | 258 | input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2); |
| 234 | input_report_abs(input, ABS_MT_ORIENTATION, orientation); | 259 | input_report_abs(input, ABS_MT_ORIENTATION, orientation); |
| 235 | input_report_abs(input, ABS_MT_POSITION_X, x); | 260 | input_report_abs(input, ABS_MT_POSITION_X, x); |
| 236 | input_report_abs(input, ABS_MT_POSITION_Y, y); | 261 | input_report_abs(input, ABS_MT_POSITION_Y, y); |
| 237 | 262 | ||
| 238 | if (report_undeciphered) | 263 | if (report_undeciphered) { |
| 239 | input_event(input, EV_MSC, MSC_RAW, tdata[7]); | 264 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) |
| 265 | input_event(input, EV_MSC, MSC_RAW, tdata[7]); | ||
| 266 | else /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
| 267 | input_event(input, EV_MSC, MSC_RAW, tdata[8]); | ||
| 268 | } | ||
| 240 | 269 | ||
| 241 | input_mt_sync(input); | 270 | input_mt_sync(input); |
| 242 | } | 271 | } |
| @@ -247,39 +276,43 @@ static int magicmouse_raw_event(struct hid_device *hdev, | |||
| 247 | { | 276 | { |
| 248 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); | 277 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); |
| 249 | struct input_dev *input = msc->input; | 278 | struct input_dev *input = msc->input; |
| 250 | int x, y, ts, ii, clicks, last_up; | 279 | int x = 0, y = 0, ii, clicks = 0, npoints; |
| 251 | 280 | ||
| 252 | switch (data[0]) { | 281 | switch (data[0]) { |
| 253 | case 0x10: | 282 | case TRACKPAD_REPORT_ID: |
| 254 | if (size != 6) | 283 | /* Expect four bytes of prefix, and N*9 bytes of touch data. */ |
| 284 | if (size < 4 || ((size - 4) % 9) != 0) | ||
| 255 | return 0; | 285 | return 0; |
| 256 | x = (__s16)(data[2] | data[3] << 8); | 286 | npoints = (size - 4) / 9; |
| 257 | y = (__s16)(data[4] | data[5] << 8); | 287 | msc->ntouches = 0; |
| 288 | for (ii = 0; ii < npoints; ii++) | ||
| 289 | magicmouse_emit_touch(msc, ii, data + ii * 9 + 4); | ||
| 290 | |||
| 291 | /* We don't need an MT sync here because trackpad emits a | ||
| 292 | * BTN_TOUCH event in a new frame when all touches are released. | ||
| 293 | */ | ||
| 294 | if (msc->ntouches == 0) | ||
| 295 | msc->single_touch_id = NO_TOUCHES; | ||
| 296 | |||
| 258 | clicks = data[1]; | 297 | clicks = data[1]; |
| 298 | |||
| 299 | /* The following bits provide a device specific timestamp. They | ||
| 300 | * are unused here. | ||
| 301 | * | ||
| 302 | * ts = data[1] >> 6 | data[2] << 2 | data[3] << 10; | ||
| 303 | */ | ||
| 259 | break; | 304 | break; |
| 260 | case TOUCH_REPORT_ID: | 305 | case MOUSE_REPORT_ID: |
| 261 | /* Expect six bytes of prefix, and N*8 bytes of touch data. */ | 306 | /* Expect six bytes of prefix, and N*8 bytes of touch data. */ |
| 262 | if (size < 6 || ((size - 6) % 8) != 0) | 307 | if (size < 6 || ((size - 6) % 8) != 0) |
| 263 | return 0; | 308 | return 0; |
| 264 | ts = data[3] >> 6 | data[4] << 2 | data[5] << 10; | 309 | npoints = (size - 6) / 8; |
| 265 | msc->delta_time = (ts - msc->last_timestamp) & 0x3ffff; | 310 | msc->ntouches = 0; |
| 266 | msc->last_timestamp = ts; | 311 | for (ii = 0; ii < npoints; ii++) |
| 267 | msc->ntouches = (size - 6) / 8; | ||
| 268 | for (ii = 0; ii < msc->ntouches; ii++) | ||
| 269 | magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); | 312 | magicmouse_emit_touch(msc, ii, data + ii * 8 + 6); |
| 270 | 313 | ||
| 271 | if (report_touches) { | 314 | if (report_touches && msc->ntouches == 0) |
| 272 | last_up = 1; | 315 | input_mt_sync(input); |
| 273 | for (ii = 0; ii < ARRAY_SIZE(msc->touches); ii++) { | ||
| 274 | if (msc->touches[ii].down) { | ||
| 275 | last_up = 0; | ||
| 276 | msc->touches[ii].down = 0; | ||
| 277 | } | ||
| 278 | } | ||
| 279 | if (last_up) { | ||
| 280 | input_mt_sync(input); | ||
| 281 | } | ||
| 282 | } | ||
| 283 | 316 | ||
| 284 | /* When emulating three-button mode, it is important | 317 | /* When emulating three-button mode, it is important |
| 285 | * to have the current touch information before | 318 | * to have the current touch information before |
| @@ -288,68 +321,72 @@ static int magicmouse_raw_event(struct hid_device *hdev, | |||
| 288 | x = (int)(((data[3] & 0x0c) << 28) | (data[1] << 22)) >> 22; | 321 | x = (int)(((data[3] & 0x0c) << 28) | (data[1] << 22)) >> 22; |
| 289 | y = (int)(((data[3] & 0x30) << 26) | (data[2] << 22)) >> 22; | 322 | y = (int)(((data[3] & 0x30) << 26) | (data[2] << 22)) >> 22; |
| 290 | clicks = data[3]; | 323 | clicks = data[3]; |
| 324 | |||
| 325 | /* The following bits provide a device specific timestamp. They | ||
| 326 | * are unused here. | ||
| 327 | * | ||
| 328 | * ts = data[3] >> 6 | data[4] << 2 | data[5] << 10; | ||
| 329 | */ | ||
| 330 | break; | ||
| 331 | case DOUBLE_REPORT_ID: | ||
| 332 | /* Sometimes the trackpad sends two touch reports in one | ||
| 333 | * packet. | ||
| 334 | */ | ||
| 335 | magicmouse_raw_event(hdev, report, data + 2, data[1]); | ||
| 336 | magicmouse_raw_event(hdev, report, data + 2 + data[1], | ||
| 337 | size - 2 - data[1]); | ||
| 291 | break; | 338 | break; |
| 292 | case 0x20: /* Theoretically battery status (0-100), but I have | ||
| 293 | * never seen it -- maybe it is only upon request. | ||
| 294 | */ | ||
| 295 | case 0x60: /* Unknown, maybe laser on/off. */ | ||
| 296 | case 0x61: /* Laser reflection status change. | ||
| 297 | * data[1]: 0 = spotted, 1 = lost | ||
| 298 | */ | ||
| 299 | default: | 339 | default: |
| 300 | return 0; | 340 | return 0; |
| 301 | } | 341 | } |
| 302 | 342 | ||
| 303 | magicmouse_emit_buttons(msc, clicks & 3); | 343 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { |
| 304 | input_report_rel(input, REL_X, x); | 344 | magicmouse_emit_buttons(msc, clicks & 3); |
| 305 | input_report_rel(input, REL_Y, y); | 345 | input_report_rel(input, REL_X, x); |
| 346 | input_report_rel(input, REL_Y, y); | ||
| 347 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
| 348 | input_report_key(input, BTN_MOUSE, clicks & 1); | ||
| 349 | input_report_key(input, BTN_TOUCH, msc->ntouches > 0); | ||
| 350 | input_report_key(input, BTN_TOOL_FINGER, msc->ntouches == 1); | ||
| 351 | input_report_key(input, BTN_TOOL_DOUBLETAP, msc->ntouches == 2); | ||
| 352 | input_report_key(input, BTN_TOOL_TRIPLETAP, msc->ntouches == 3); | ||
| 353 | input_report_key(input, BTN_TOOL_QUADTAP, msc->ntouches == 4); | ||
| 354 | if (msc->single_touch_id >= 0) { | ||
| 355 | input_report_abs(input, ABS_X, | ||
| 356 | msc->touches[msc->single_touch_id].x); | ||
| 357 | input_report_abs(input, ABS_Y, | ||
| 358 | msc->touches[msc->single_touch_id].y); | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 306 | input_sync(input); | 362 | input_sync(input); |
| 307 | return 1; | 363 | return 1; |
| 308 | } | 364 | } |
| 309 | 365 | ||
| 310 | static int magicmouse_input_open(struct input_dev *dev) | ||
| 311 | { | ||
| 312 | struct hid_device *hid = input_get_drvdata(dev); | ||
| 313 | |||
| 314 | return hid->ll_driver->open(hid); | ||
| 315 | } | ||
| 316 | |||
| 317 | static void magicmouse_input_close(struct input_dev *dev) | ||
| 318 | { | ||
| 319 | struct hid_device *hid = input_get_drvdata(dev); | ||
| 320 | |||
| 321 | hid->ll_driver->close(hid); | ||
| 322 | } | ||
| 323 | |||
| 324 | static void magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev) | 366 | static void magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev) |
| 325 | { | 367 | { |
| 326 | input_set_drvdata(input, hdev); | ||
| 327 | input->event = hdev->ll_driver->hidinput_input_event; | ||
| 328 | input->open = magicmouse_input_open; | ||
| 329 | input->close = magicmouse_input_close; | ||
| 330 | |||
| 331 | input->name = hdev->name; | ||
| 332 | input->phys = hdev->phys; | ||
| 333 | input->uniq = hdev->uniq; | ||
| 334 | input->id.bustype = hdev->bus; | ||
| 335 | input->id.vendor = hdev->vendor; | ||
| 336 | input->id.product = hdev->product; | ||
| 337 | input->id.version = hdev->version; | ||
| 338 | input->dev.parent = hdev->dev.parent; | ||
| 339 | |||
| 340 | __set_bit(EV_KEY, input->evbit); | 368 | __set_bit(EV_KEY, input->evbit); |
| 341 | __set_bit(BTN_LEFT, input->keybit); | 369 | |
| 342 | __set_bit(BTN_RIGHT, input->keybit); | 370 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { |
| 343 | if (emulate_3button) | 371 | __set_bit(BTN_LEFT, input->keybit); |
| 344 | __set_bit(BTN_MIDDLE, input->keybit); | 372 | __set_bit(BTN_RIGHT, input->keybit); |
| 345 | __set_bit(BTN_TOOL_FINGER, input->keybit); | 373 | if (emulate_3button) |
| 346 | 374 | __set_bit(BTN_MIDDLE, input->keybit); | |
| 347 | __set_bit(EV_REL, input->evbit); | 375 | |
| 348 | __set_bit(REL_X, input->relbit); | 376 | __set_bit(EV_REL, input->evbit); |
| 349 | __set_bit(REL_Y, input->relbit); | 377 | __set_bit(REL_X, input->relbit); |
| 350 | if (emulate_scroll_wheel) { | 378 | __set_bit(REL_Y, input->relbit); |
| 351 | __set_bit(REL_WHEEL, input->relbit); | 379 | if (emulate_scroll_wheel) { |
| 352 | __set_bit(REL_HWHEEL, input->relbit); | 380 | __set_bit(REL_WHEEL, input->relbit); |
| 381 | __set_bit(REL_HWHEEL, input->relbit); | ||
| 382 | } | ||
| 383 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
| 384 | __set_bit(BTN_MOUSE, input->keybit); | ||
| 385 | __set_bit(BTN_TOOL_FINGER, input->keybit); | ||
| 386 | __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); | ||
| 387 | __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); | ||
| 388 | __set_bit(BTN_TOOL_QUADTAP, input->keybit); | ||
| 389 | __set_bit(BTN_TOUCH, input->keybit); | ||
| 353 | } | 390 | } |
| 354 | 391 | ||
| 355 | if (report_touches) { | 392 | if (report_touches) { |
| @@ -359,16 +396,26 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h | |||
| 359 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0); | 396 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0); |
| 360 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0); | 397 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0); |
| 361 | input_set_abs_params(input, ABS_MT_ORIENTATION, -32, 31, 1, 0); | 398 | input_set_abs_params(input, ABS_MT_ORIENTATION, -32, 31, 1, 0); |
| 362 | input_set_abs_params(input, ABS_MT_POSITION_X, -1100, 1358, | 399 | |
| 363 | 4, 0); | ||
| 364 | /* Note: Touch Y position from the device is inverted relative | 400 | /* Note: Touch Y position from the device is inverted relative |
| 365 | * to how pointer motion is reported (and relative to how USB | 401 | * to how pointer motion is reported (and relative to how USB |
| 366 | * HID recommends the coordinates work). This driver keeps | 402 | * HID recommends the coordinates work). This driver keeps |
| 367 | * the origin at the same position, and just uses the additive | 403 | * the origin at the same position, and just uses the additive |
| 368 | * inverse of the reported Y. | 404 | * inverse of the reported Y. |
| 369 | */ | 405 | */ |
| 370 | input_set_abs_params(input, ABS_MT_POSITION_Y, -1589, 2047, | 406 | if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE) { |
| 371 | 4, 0); | 407 | input_set_abs_params(input, ABS_MT_POSITION_X, -1100, |
| 408 | 1358, 4, 0); | ||
| 409 | input_set_abs_params(input, ABS_MT_POSITION_Y, -1589, | ||
| 410 | 2047, 4, 0); | ||
| 411 | } else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
| 412 | input_set_abs_params(input, ABS_X, -2909, 3167, 4, 0); | ||
| 413 | input_set_abs_params(input, ABS_Y, -2456, 2565, 4, 0); | ||
| 414 | input_set_abs_params(input, ABS_MT_POSITION_X, -2909, | ||
| 415 | 3167, 4, 0); | ||
| 416 | input_set_abs_params(input, ABS_MT_POSITION_Y, -2456, | ||
| 417 | 2565, 4, 0); | ||
| 418 | } | ||
| 372 | } | 419 | } |
| 373 | 420 | ||
| 374 | if (report_undeciphered) { | 421 | if (report_undeciphered) { |
| @@ -377,12 +424,22 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h | |||
| 377 | } | 424 | } |
| 378 | } | 425 | } |
| 379 | 426 | ||
| 427 | static int magicmouse_input_mapping(struct hid_device *hdev, | ||
| 428 | struct hid_input *hi, struct hid_field *field, | ||
| 429 | struct hid_usage *usage, unsigned long **bit, int *max) | ||
| 430 | { | ||
| 431 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); | ||
| 432 | |||
| 433 | if (!msc->input) | ||
| 434 | msc->input = hi->input; | ||
| 435 | |||
| 436 | return 0; | ||
| 437 | } | ||
| 438 | |||
| 380 | static int magicmouse_probe(struct hid_device *hdev, | 439 | static int magicmouse_probe(struct hid_device *hdev, |
| 381 | const struct hid_device_id *id) | 440 | const struct hid_device_id *id) |
| 382 | { | 441 | { |
| 383 | __u8 feature_1[] = { 0xd7, 0x01 }; | 442 | __u8 feature[] = { 0xd7, 0x01 }; |
| 384 | __u8 feature_2[] = { 0xf8, 0x01, 0x32 }; | ||
| 385 | struct input_dev *input; | ||
| 386 | struct magicmouse_sc *msc; | 443 | struct magicmouse_sc *msc; |
| 387 | struct hid_report *report; | 444 | struct hid_report *report; |
| 388 | int ret; | 445 | int ret; |
| @@ -398,6 +455,8 @@ static int magicmouse_probe(struct hid_device *hdev, | |||
| 398 | msc->quirks = id->driver_data; | 455 | msc->quirks = id->driver_data; |
| 399 | hid_set_drvdata(hdev, msc); | 456 | hid_set_drvdata(hdev, msc); |
| 400 | 457 | ||
| 458 | msc->single_touch_id = NO_TOUCHES; | ||
| 459 | |||
| 401 | ret = hid_parse(hdev); | 460 | ret = hid_parse(hdev); |
| 402 | if (ret) { | 461 | if (ret) { |
| 403 | dev_err(&hdev->dev, "magicmouse hid parse failed\n"); | 462 | dev_err(&hdev->dev, "magicmouse hid parse failed\n"); |
| @@ -410,10 +469,22 @@ static int magicmouse_probe(struct hid_device *hdev, | |||
| 410 | goto err_free; | 469 | goto err_free; |
| 411 | } | 470 | } |
| 412 | 471 | ||
| 413 | /* we are handling the input ourselves */ | 472 | /* We do this after hid-input is done parsing reports so that |
| 414 | hidinput_disconnect(hdev); | 473 | * hid-input uses the most natural button and axis IDs. |
| 474 | */ | ||
| 475 | if (msc->input) | ||
| 476 | magicmouse_setup_input(msc->input, hdev); | ||
| 477 | |||
| 478 | if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE) | ||
| 479 | report = hid_register_report(hdev, HID_INPUT_REPORT, | ||
| 480 | MOUSE_REPORT_ID); | ||
| 481 | else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */ | ||
| 482 | report = hid_register_report(hdev, HID_INPUT_REPORT, | ||
| 483 | TRACKPAD_REPORT_ID); | ||
| 484 | report = hid_register_report(hdev, HID_INPUT_REPORT, | ||
| 485 | DOUBLE_REPORT_ID); | ||
| 486 | } | ||
| 415 | 487 | ||
| 416 | report = hid_register_report(hdev, HID_INPUT_REPORT, TOUCH_REPORT_ID); | ||
| 417 | if (!report) { | 488 | if (!report) { |
| 418 | dev_err(&hdev->dev, "unable to register touch report\n"); | 489 | dev_err(&hdev->dev, "unable to register touch report\n"); |
| 419 | ret = -ENOMEM; | 490 | ret = -ENOMEM; |
| @@ -421,39 +492,15 @@ static int magicmouse_probe(struct hid_device *hdev, | |||
| 421 | } | 492 | } |
| 422 | report->size = 6; | 493 | report->size = 6; |
| 423 | 494 | ||
| 424 | ret = hdev->hid_output_raw_report(hdev, feature_1, sizeof(feature_1), | 495 | ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), |
| 425 | HID_FEATURE_REPORT); | 496 | HID_FEATURE_REPORT); |
| 426 | if (ret != sizeof(feature_1)) { | 497 | if (ret != sizeof(feature)) { |
| 427 | dev_err(&hdev->dev, "unable to request touch data (1:%d)\n", | 498 | dev_err(&hdev->dev, "unable to request touch data (%d)\n", |
| 428 | ret); | ||
| 429 | goto err_stop_hw; | ||
| 430 | } | ||
| 431 | ret = hdev->hid_output_raw_report(hdev, feature_2, | ||
| 432 | sizeof(feature_2), HID_FEATURE_REPORT); | ||
| 433 | if (ret != sizeof(feature_2)) { | ||
| 434 | dev_err(&hdev->dev, "unable to request touch data (2:%d)\n", | ||
| 435 | ret); | 499 | ret); |
| 436 | goto err_stop_hw; | 500 | goto err_stop_hw; |
| 437 | } | 501 | } |
| 438 | 502 | ||
| 439 | input = input_allocate_device(); | ||
| 440 | if (!input) { | ||
| 441 | dev_err(&hdev->dev, "can't alloc input device\n"); | ||
| 442 | ret = -ENOMEM; | ||
| 443 | goto err_stop_hw; | ||
| 444 | } | ||
| 445 | magicmouse_setup_input(input, hdev); | ||
| 446 | |||
| 447 | ret = input_register_device(input); | ||
| 448 | if (ret) { | ||
| 449 | dev_err(&hdev->dev, "input device registration failed\n"); | ||
| 450 | goto err_input; | ||
| 451 | } | ||
| 452 | msc->input = input; | ||
| 453 | |||
| 454 | return 0; | 503 | return 0; |
| 455 | err_input: | ||
| 456 | input_free_device(input); | ||
| 457 | err_stop_hw: | 504 | err_stop_hw: |
| 458 | hid_hw_stop(hdev); | 505 | hid_hw_stop(hdev); |
| 459 | err_free: | 506 | err_free: |
| @@ -466,13 +513,14 @@ static void magicmouse_remove(struct hid_device *hdev) | |||
| 466 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); | 513 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); |
| 467 | 514 | ||
| 468 | hid_hw_stop(hdev); | 515 | hid_hw_stop(hdev); |
| 469 | input_unregister_device(msc->input); | ||
| 470 | kfree(msc); | 516 | kfree(msc); |
| 471 | } | 517 | } |
| 472 | 518 | ||
| 473 | static const struct hid_device_id magic_mice[] = { | 519 | static const struct hid_device_id magic_mice[] = { |
| 474 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE), | 520 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, |
| 475 | .driver_data = 0 }, | 521 | USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 }, |
| 522 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, | ||
| 523 | USB_DEVICE_ID_APPLE_MAGICTRACKPAD), .driver_data = 0 }, | ||
| 476 | { } | 524 | { } |
| 477 | }; | 525 | }; |
| 478 | MODULE_DEVICE_TABLE(hid, magic_mice); | 526 | MODULE_DEVICE_TABLE(hid, magic_mice); |
| @@ -483,6 +531,7 @@ static struct hid_driver magicmouse_driver = { | |||
| 483 | .probe = magicmouse_probe, | 531 | .probe = magicmouse_probe, |
| 484 | .remove = magicmouse_remove, | 532 | .remove = magicmouse_remove, |
| 485 | .raw_event = magicmouse_raw_event, | 533 | .raw_event = magicmouse_raw_event, |
| 534 | .input_mapping = magicmouse_input_mapping, | ||
| 486 | }; | 535 | }; |
| 487 | 536 | ||
| 488 | static int __init magicmouse_init(void) | 537 | static int __init magicmouse_init(void) |
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 359cc447c6c6..dc618c33d0a2 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c | |||
| @@ -33,18 +33,19 @@ | |||
| 33 | * Microsoft Wireless Desktop Receiver (Model 1028) has | 33 | * Microsoft Wireless Desktop Receiver (Model 1028) has |
| 34 | * 'Usage Min/Max' where it ought to have 'Physical Min/Max' | 34 | * 'Usage Min/Max' where it ought to have 'Physical Min/Max' |
| 35 | */ | 35 | */ |
| 36 | static void ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 36 | static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 37 | unsigned int rsize) | 37 | unsigned int *rsize) |
| 38 | { | 38 | { |
| 39 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | 39 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); |
| 40 | 40 | ||
| 41 | if ((quirks & MS_RDESC) && rsize == 571 && rdesc[557] == 0x19 && | 41 | if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 && |
| 42 | rdesc[559] == 0x29) { | 42 | rdesc[559] == 0x29) { |
| 43 | dev_info(&hdev->dev, "fixing up Microsoft Wireless Receiver " | 43 | dev_info(&hdev->dev, "fixing up Microsoft Wireless Receiver " |
| 44 | "Model 1028 report descriptor\n"); | 44 | "Model 1028 report descriptor\n"); |
| 45 | rdesc[557] = 0x35; | 45 | rdesc[557] = 0x35; |
| 46 | rdesc[559] = 0x45; | 46 | rdesc[559] = 0x45; |
| 47 | } | 47 | } |
| 48 | return rdesc; | ||
| 48 | } | 49 | } |
| 49 | 50 | ||
| 50 | #define ms_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 51 | #define ms_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c index 2cd05aa244b9..c95c31e2d869 100644 --- a/drivers/hid/hid-monterey.c +++ b/drivers/hid/hid-monterey.c | |||
| @@ -22,14 +22,15 @@ | |||
| 22 | 22 | ||
| 23 | #include "hid-ids.h" | 23 | #include "hid-ids.h" |
| 24 | 24 | ||
| 25 | static void mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 25 | static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 26 | unsigned int rsize) | 26 | unsigned int *rsize) |
| 27 | { | 27 | { |
| 28 | if (rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { | 28 | if (*rsize >= 30 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { |
| 29 | dev_info(&hdev->dev, "fixing up button/consumer in HID report " | 29 | dev_info(&hdev->dev, "fixing up button/consumer in HID report " |
| 30 | "descriptor\n"); | 30 | "descriptor\n"); |
| 31 | rdesc[30] = 0x0c; | 31 | rdesc[30] = 0x0c; |
| 32 | } | 32 | } |
| 33 | return rdesc; | ||
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | #define mr_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 36 | #define mr_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index fb69b8c4953f..69169efa1e16 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c | |||
| @@ -90,6 +90,55 @@ struct ntrig_data { | |||
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | 92 | ||
| 93 | /* | ||
| 94 | * This function converts the 4 byte raw firmware code into | ||
| 95 | * a string containing 5 comma separated numbers. | ||
| 96 | */ | ||
| 97 | static int ntrig_version_string(unsigned char *raw, char *buf) | ||
| 98 | { | ||
| 99 | __u8 a = (raw[1] & 0x0e) >> 1; | ||
| 100 | __u8 b = (raw[0] & 0x3c) >> 2; | ||
| 101 | __u8 c = ((raw[0] & 0x03) << 3) | ((raw[3] & 0xe0) >> 5); | ||
| 102 | __u8 d = ((raw[3] & 0x07) << 3) | ((raw[2] & 0xe0) >> 5); | ||
| 103 | __u8 e = raw[2] & 0x07; | ||
| 104 | |||
| 105 | /* | ||
| 106 | * As yet unmapped bits: | ||
| 107 | * 0b11000000 0b11110001 0b00011000 0b00011000 | ||
| 108 | */ | ||
| 109 | |||
| 110 | return sprintf(buf, "%u.%u.%u.%u.%u", a, b, c, d, e); | ||
| 111 | } | ||
| 112 | |||
| 113 | static void ntrig_report_version(struct hid_device *hdev) | ||
| 114 | { | ||
| 115 | int ret; | ||
| 116 | char buf[20]; | ||
| 117 | struct usb_device *usb_dev = hid_to_usb_dev(hdev); | ||
| 118 | unsigned char *data = kmalloc(8, GFP_KERNEL); | ||
| 119 | |||
| 120 | if (!data) | ||
| 121 | goto err_free; | ||
| 122 | |||
| 123 | ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
| 124 | USB_REQ_CLEAR_FEATURE, | ||
| 125 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | | ||
| 126 | USB_DIR_IN, | ||
| 127 | 0x30c, 1, data, 8, | ||
| 128 | USB_CTRL_SET_TIMEOUT); | ||
| 129 | |||
| 130 | if (ret == 8) { | ||
| 131 | ret = ntrig_version_string(&data[2], buf); | ||
| 132 | |||
| 133 | dev_info(&hdev->dev, | ||
| 134 | "Firmware version: %s (%02x%02x %02x%02x)\n", | ||
| 135 | buf, data[2], data[3], data[4], data[5]); | ||
| 136 | } | ||
| 137 | |||
| 138 | err_free: | ||
| 139 | kfree(data); | ||
| 140 | } | ||
| 141 | |||
| 93 | static ssize_t show_phys_width(struct device *dev, | 142 | static ssize_t show_phys_width(struct device *dev, |
| 94 | struct device_attribute *attr, | 143 | struct device_attribute *attr, |
| 95 | char *buf) | 144 | char *buf) |
| @@ -377,8 +426,8 @@ static struct attribute_group ntrig_attribute_group = { | |||
| 377 | */ | 426 | */ |
| 378 | 427 | ||
| 379 | static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, | 428 | static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, |
| 380 | struct hid_field *field, struct hid_usage *usage, | 429 | struct hid_field *field, struct hid_usage *usage, |
| 381 | unsigned long **bit, int *max) | 430 | unsigned long **bit, int *max) |
| 382 | { | 431 | { |
| 383 | struct ntrig_data *nd = hid_get_drvdata(hdev); | 432 | struct ntrig_data *nd = hid_get_drvdata(hdev); |
| 384 | 433 | ||
| @@ -448,13 +497,13 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 448 | /* width/height mapped on TouchMajor/TouchMinor/Orientation */ | 497 | /* width/height mapped on TouchMajor/TouchMinor/Orientation */ |
| 449 | case HID_DG_WIDTH: | 498 | case HID_DG_WIDTH: |
| 450 | hid_map_usage(hi, usage, bit, max, | 499 | hid_map_usage(hi, usage, bit, max, |
| 451 | EV_ABS, ABS_MT_TOUCH_MAJOR); | 500 | EV_ABS, ABS_MT_TOUCH_MAJOR); |
| 452 | return 1; | 501 | return 1; |
| 453 | case HID_DG_HEIGHT: | 502 | case HID_DG_HEIGHT: |
| 454 | hid_map_usage(hi, usage, bit, max, | 503 | hid_map_usage(hi, usage, bit, max, |
| 455 | EV_ABS, ABS_MT_TOUCH_MINOR); | 504 | EV_ABS, ABS_MT_TOUCH_MINOR); |
| 456 | input_set_abs_params(hi->input, ABS_MT_ORIENTATION, | 505 | input_set_abs_params(hi->input, ABS_MT_ORIENTATION, |
| 457 | 0, 1, 0, 0); | 506 | 0, 1, 0, 0); |
| 458 | return 1; | 507 | return 1; |
| 459 | } | 508 | } |
| 460 | return 0; | 509 | return 0; |
| @@ -468,8 +517,8 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 468 | } | 517 | } |
| 469 | 518 | ||
| 470 | static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, | 519 | static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, |
| 471 | struct hid_field *field, struct hid_usage *usage, | 520 | struct hid_field *field, struct hid_usage *usage, |
| 472 | unsigned long **bit, int *max) | 521 | unsigned long **bit, int *max) |
| 473 | { | 522 | { |
| 474 | /* No special mappings needed for the pen and single touch */ | 523 | /* No special mappings needed for the pen and single touch */ |
| 475 | if (field->physical) | 524 | if (field->physical) |
| @@ -489,7 +538,7 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
| 489 | * and call input_mt_sync after each point if necessary | 538 | * and call input_mt_sync after each point if necessary |
| 490 | */ | 539 | */ |
| 491 | static int ntrig_event (struct hid_device *hid, struct hid_field *field, | 540 | static int ntrig_event (struct hid_device *hid, struct hid_field *field, |
| 492 | struct hid_usage *usage, __s32 value) | 541 | struct hid_usage *usage, __s32 value) |
| 493 | { | 542 | { |
| 494 | struct input_dev *input = field->hidinput->input; | 543 | struct input_dev *input = field->hidinput->input; |
| 495 | struct ntrig_data *nd = hid_get_drvdata(hid); | 544 | struct ntrig_data *nd = hid_get_drvdata(hid); |
| @@ -848,6 +897,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 848 | if (report) | 897 | if (report) |
| 849 | usbhid_submit_report(hdev, report, USB_DIR_OUT); | 898 | usbhid_submit_report(hdev, report, USB_DIR_OUT); |
| 850 | 899 | ||
| 900 | ntrig_report_version(hdev); | ||
| 901 | |||
| 851 | ret = sysfs_create_group(&hdev->dev.kobj, | 902 | ret = sysfs_create_group(&hdev->dev.kobj, |
| 852 | &ntrig_attribute_group); | 903 | &ntrig_attribute_group); |
| 853 | 904 | ||
| @@ -860,7 +911,7 @@ err_free: | |||
| 860 | static void ntrig_remove(struct hid_device *hdev) | 911 | static void ntrig_remove(struct hid_device *hdev) |
| 861 | { | 912 | { |
| 862 | sysfs_remove_group(&hdev->dev.kobj, | 913 | sysfs_remove_group(&hdev->dev.kobj, |
| 863 | &ntrig_attribute_group); | 914 | &ntrig_attribute_group); |
| 864 | hid_hw_stop(hdev); | 915 | hid_hw_stop(hdev); |
| 865 | kfree(hid_get_drvdata(hdev)); | 916 | kfree(hid_get_drvdata(hdev)); |
| 866 | } | 917 | } |
diff --git a/drivers/hid/hid-ortek.c b/drivers/hid/hid-ortek.c index aa9a960f73a4..2e79716dca31 100644 --- a/drivers/hid/hid-ortek.c +++ b/drivers/hid/hid-ortek.c | |||
| @@ -19,14 +19,15 @@ | |||
| 19 | 19 | ||
| 20 | #include "hid-ids.h" | 20 | #include "hid-ids.h" |
| 21 | 21 | ||
| 22 | static void ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 22 | static __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 23 | unsigned int rsize) | 23 | unsigned int *rsize) |
| 24 | { | 24 | { |
| 25 | if (rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) { | 25 | if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) { |
| 26 | dev_info(&hdev->dev, "Fixing up Ortek WKB-2000 " | 26 | dev_info(&hdev->dev, "Fixing up Ortek WKB-2000 " |
| 27 | "report descriptor.\n"); | 27 | "report descriptor.\n"); |
| 28 | rdesc[55] = 0x92; | 28 | rdesc[55] = 0x92; |
| 29 | } | 29 | } |
| 30 | return rdesc; | ||
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | static const struct hid_device_id ortek_devices[] = { | 33 | static const struct hid_device_id ortek_devices[] = { |
diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c index 500fbd0652dc..308d6ae48a3e 100644 --- a/drivers/hid/hid-petalynx.c +++ b/drivers/hid/hid-petalynx.c | |||
| @@ -23,10 +23,10 @@ | |||
| 23 | #include "hid-ids.h" | 23 | #include "hid-ids.h" |
| 24 | 24 | ||
| 25 | /* Petalynx Maxter Remote has maximum for consumer page set too low */ | 25 | /* Petalynx Maxter Remote has maximum for consumer page set too low */ |
| 26 | static void pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 26 | static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 27 | unsigned int rsize) | 27 | unsigned int *rsize) |
| 28 | { | 28 | { |
| 29 | if (rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && | 29 | if (*rsize >= 60 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && |
| 30 | rdesc[41] == 0x00 && rdesc[59] == 0x26 && | 30 | rdesc[41] == 0x00 && rdesc[59] == 0x26 && |
| 31 | rdesc[60] == 0xf9 && rdesc[61] == 0x00) { | 31 | rdesc[60] == 0xf9 && rdesc[61] == 0x00) { |
| 32 | dev_info(&hdev->dev, "fixing up Petalynx Maxter Remote report " | 32 | dev_info(&hdev->dev, "fixing up Petalynx Maxter Remote report " |
| @@ -34,6 +34,7 @@ static void pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 34 | rdesc[60] = 0xfa; | 34 | rdesc[60] = 0xfa; |
| 35 | rdesc[40] = 0xfa; | 35 | rdesc[40] = 0xfa; |
| 36 | } | 36 | } |
| 37 | return rdesc; | ||
| 37 | } | 38 | } |
| 38 | 39 | ||
| 39 | #define pl_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 40 | #define pl_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 845f428b8090..48eab84f53b5 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c | |||
| @@ -740,10 +740,10 @@ int pcmidi_snd_terminate(struct pcmidi_snd *pm) | |||
| 740 | /* | 740 | /* |
| 741 | * PC-MIDI report descriptor for report id is wrong. | 741 | * PC-MIDI report descriptor for report id is wrong. |
| 742 | */ | 742 | */ |
| 743 | static void pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 743 | static __u8 *pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 744 | unsigned int rsize) | 744 | unsigned int *rsize) |
| 745 | { | 745 | { |
| 746 | if (rsize == 178 && | 746 | if (*rsize == 178 && |
| 747 | rdesc[111] == 0x06 && rdesc[112] == 0x00 && | 747 | rdesc[111] == 0x06 && rdesc[112] == 0x00 && |
| 748 | rdesc[113] == 0xff) { | 748 | rdesc[113] == 0xff) { |
| 749 | dev_info(&hdev->dev, "fixing up pc-midi keyboard report " | 749 | dev_info(&hdev->dev, "fixing up pc-midi keyboard report " |
| @@ -751,6 +751,7 @@ static void pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 751 | 751 | ||
| 752 | rdesc[144] = 0x18; /* report 4: was 0x10 report count */ | 752 | rdesc[144] = 0x18; /* report 4: was 0x10 report count */ |
| 753 | } | 753 | } |
| 754 | return rdesc; | ||
| 754 | } | 755 | } |
| 755 | 756 | ||
| 756 | static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi, | 757 | static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi, |
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c new file mode 100644 index 000000000000..9bf23047892a --- /dev/null +++ b/drivers/hid/hid-roccat-pyra.c | |||
| @@ -0,0 +1,968 @@ | |||
| 1 | /* | ||
| 2 | * Roccat Pyra driver for Linux | ||
| 3 | * | ||
| 4 | * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 11 | * any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | /* | ||
| 15 | * Roccat Pyra is a mobile gamer mouse which comes in wired and wireless | ||
| 16 | * variant. Wireless variant is not tested. | ||
| 17 | * Userland tools can be found at http://sourceforge.net/projects/roccat | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/device.h> | ||
| 21 | #include <linux/input.h> | ||
| 22 | #include <linux/hid.h> | ||
| 23 | #include <linux/usb.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | #include "hid-ids.h" | ||
| 27 | #include "hid-roccat.h" | ||
| 28 | #include "hid-roccat-pyra.h" | ||
| 29 | |||
| 30 | static void profile_activated(struct pyra_device *pyra, | ||
| 31 | unsigned int new_profile) | ||
| 32 | { | ||
| 33 | pyra->actual_profile = new_profile; | ||
| 34 | pyra->actual_cpi = pyra->profile_settings[pyra->actual_profile].y_cpi; | ||
| 35 | } | ||
| 36 | |||
| 37 | static int pyra_send_control(struct usb_device *usb_dev, int value, | ||
| 38 | enum pyra_control_requests request) | ||
| 39 | { | ||
| 40 | int len; | ||
| 41 | struct pyra_control control; | ||
| 42 | |||
| 43 | if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS || | ||
| 44 | request == PYRA_CONTROL_REQUEST_PROFILE_BUTTONS) && | ||
| 45 | (value < 0 || value > 4)) | ||
| 46 | return -EINVAL; | ||
| 47 | |||
| 48 | control.command = PYRA_COMMAND_CONTROL; | ||
| 49 | control.value = value; | ||
| 50 | control.request = request; | ||
| 51 | |||
| 52 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
| 53 | USB_REQ_SET_CONFIGURATION, | ||
| 54 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
| 55 | PYRA_USB_COMMAND_CONTROL, 0, (char *)&control, | ||
| 56 | sizeof(struct pyra_control), | ||
| 57 | USB_CTRL_SET_TIMEOUT); | ||
| 58 | |||
| 59 | if (len != sizeof(struct pyra_control)) | ||
| 60 | return len; | ||
| 61 | |||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static int pyra_receive_control_status(struct usb_device *usb_dev) | ||
| 66 | { | ||
| 67 | int len; | ||
| 68 | struct pyra_control control; | ||
| 69 | |||
| 70 | do { | ||
| 71 | msleep(10); | ||
| 72 | |||
| 73 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
| 74 | USB_REQ_CLEAR_FEATURE, | ||
| 75 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | | ||
| 76 | USB_DIR_IN, | ||
| 77 | PYRA_USB_COMMAND_CONTROL, 0, (char *)&control, | ||
| 78 | sizeof(struct pyra_control), | ||
| 79 | USB_CTRL_SET_TIMEOUT); | ||
| 80 | |||
| 81 | /* requested too early, try again */ | ||
| 82 | } while (len == -EPROTO); | ||
| 83 | |||
| 84 | if (len == sizeof(struct pyra_control) && | ||
| 85 | control.command == PYRA_COMMAND_CONTROL && | ||
| 86 | control.request == PYRA_CONTROL_REQUEST_STATUS && | ||
| 87 | control.value == 1) | ||
| 88 | return 0; | ||
| 89 | else { | ||
| 90 | dev_err(&usb_dev->dev, "receive control status: " | ||
| 91 | "unknown response 0x%x 0x%x\n", | ||
| 92 | control.request, control.value); | ||
| 93 | return -EINVAL; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | static int pyra_get_profile_settings(struct usb_device *usb_dev, | ||
| 98 | struct pyra_profile_settings *buf, int number) | ||
| 99 | { | ||
| 100 | int retval; | ||
| 101 | |||
| 102 | retval = pyra_send_control(usb_dev, number, | ||
| 103 | PYRA_CONTROL_REQUEST_PROFILE_SETTINGS); | ||
| 104 | |||
| 105 | if (retval) | ||
| 106 | return retval; | ||
| 107 | |||
| 108 | retval = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
| 109 | USB_REQ_CLEAR_FEATURE, | ||
| 110 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
| 111 | PYRA_USB_COMMAND_PROFILE_SETTINGS, 0, (char *)buf, | ||
| 112 | sizeof(struct pyra_profile_settings), | ||
| 113 | USB_CTRL_SET_TIMEOUT); | ||
| 114 | |||
| 115 | if (retval != sizeof(struct pyra_profile_settings)) | ||
| 116 | return retval; | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | static int pyra_get_profile_buttons(struct usb_device *usb_dev, | ||
| 122 | struct pyra_profile_buttons *buf, int number) | ||
| 123 | { | ||
| 124 | int retval; | ||
| 125 | |||
| 126 | retval = pyra_send_control(usb_dev, number, | ||
| 127 | PYRA_CONTROL_REQUEST_PROFILE_BUTTONS); | ||
| 128 | |||
| 129 | if (retval) | ||
| 130 | return retval; | ||
| 131 | |||
| 132 | retval = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
| 133 | USB_REQ_CLEAR_FEATURE, | ||
| 134 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
| 135 | PYRA_USB_COMMAND_PROFILE_BUTTONS, 0, (char *)buf, | ||
| 136 | sizeof(struct pyra_profile_buttons), | ||
| 137 | USB_CTRL_SET_TIMEOUT); | ||
| 138 | |||
| 139 | if (retval != sizeof(struct pyra_profile_buttons)) | ||
| 140 | return retval; | ||
| 141 | |||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int pyra_get_settings(struct usb_device *usb_dev, | ||
| 146 | struct pyra_settings *buf) | ||
| 147 | { | ||
| 148 | int len; | ||
| 149 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
| 150 | USB_REQ_CLEAR_FEATURE, | ||
| 151 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
| 152 | PYRA_USB_COMMAND_SETTINGS, 0, buf, | ||
| 153 | sizeof(struct pyra_settings), USB_CTRL_SET_TIMEOUT); | ||
| 154 | if (len != sizeof(struct pyra_settings)) | ||
| 155 | return -EIO; | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf) | ||
| 160 | { | ||
| 161 | int len; | ||
| 162 | len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), | ||
| 163 | USB_REQ_CLEAR_FEATURE, | ||
| 164 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | ||
| 165 | PYRA_USB_COMMAND_INFO, 0, buf, | ||
| 166 | sizeof(struct pyra_info), USB_CTRL_SET_TIMEOUT); | ||
| 167 | if (len != sizeof(struct pyra_info)) | ||
| 168 | return -EIO; | ||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | |||
| 172 | static int pyra_set_profile_settings(struct usb_device *usb_dev, | ||
| 173 | struct pyra_profile_settings const *settings) | ||
| 174 | { | ||
| 175 | int len; | ||
| 176 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
| 177 | USB_REQ_SET_CONFIGURATION, | ||
| 178 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
| 179 | PYRA_USB_COMMAND_PROFILE_SETTINGS, 0, (char *)settings, | ||
| 180 | sizeof(struct pyra_profile_settings), | ||
| 181 | USB_CTRL_SET_TIMEOUT); | ||
| 182 | if (len != sizeof(struct pyra_profile_settings)) | ||
| 183 | return -EIO; | ||
| 184 | if (pyra_receive_control_status(usb_dev)) | ||
| 185 | return -EIO; | ||
| 186 | return 0; | ||
| 187 | } | ||
| 188 | |||
| 189 | static int pyra_set_profile_buttons(struct usb_device *usb_dev, | ||
| 190 | struct pyra_profile_buttons const *buttons) | ||
| 191 | { | ||
| 192 | int len; | ||
| 193 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
| 194 | USB_REQ_SET_CONFIGURATION, | ||
| 195 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
| 196 | PYRA_USB_COMMAND_PROFILE_BUTTONS, 0, (char *)buttons, | ||
| 197 | sizeof(struct pyra_profile_buttons), | ||
| 198 | USB_CTRL_SET_TIMEOUT); | ||
| 199 | if (len != sizeof(struct pyra_profile_buttons)) | ||
| 200 | return -EIO; | ||
| 201 | if (pyra_receive_control_status(usb_dev)) | ||
| 202 | return -EIO; | ||
| 203 | return 0; | ||
| 204 | } | ||
| 205 | |||
| 206 | static int pyra_set_settings(struct usb_device *usb_dev, | ||
| 207 | struct pyra_settings const *settings) | ||
| 208 | { | ||
| 209 | int len; | ||
| 210 | len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
| 211 | USB_REQ_SET_CONFIGURATION, | ||
| 212 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | ||
| 213 | PYRA_USB_COMMAND_SETTINGS, 0, (char *)settings, | ||
| 214 | sizeof(struct pyra_settings), USB_CTRL_SET_TIMEOUT); | ||
| 215 | if (len != sizeof(struct pyra_settings)) | ||
| 216 | return -EIO; | ||
| 217 | if (pyra_receive_control_status(usb_dev)) | ||
| 218 | return -EIO; | ||
| 219 | return 0; | ||
| 220 | } | ||
| 221 | |||
| 222 | static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp, | ||
| 223 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 224 | loff_t off, size_t count, int number) | ||
| 225 | { | ||
| 226 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 227 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 228 | |||
| 229 | if (off >= sizeof(struct pyra_profile_settings)) | ||
| 230 | return 0; | ||
| 231 | |||
| 232 | if (off + count > sizeof(struct pyra_profile_settings)) | ||
| 233 | count = sizeof(struct pyra_profile_settings) - off; | ||
| 234 | |||
| 235 | mutex_lock(&pyra->pyra_lock); | ||
| 236 | memcpy(buf, ((char const *)&pyra->profile_settings[number]) + off, | ||
| 237 | count); | ||
| 238 | mutex_unlock(&pyra->pyra_lock); | ||
| 239 | |||
| 240 | return count; | ||
| 241 | } | ||
| 242 | |||
| 243 | static ssize_t pyra_sysfs_read_profile1_settings(struct file *fp, | ||
| 244 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 245 | loff_t off, size_t count) | ||
| 246 | { | ||
| 247 | return pyra_sysfs_read_profilex_settings(fp, kobj, | ||
| 248 | attr, buf, off, count, 0); | ||
| 249 | } | ||
| 250 | |||
| 251 | static ssize_t pyra_sysfs_read_profile2_settings(struct file *fp, | ||
| 252 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 253 | loff_t off, size_t count) | ||
| 254 | { | ||
| 255 | return pyra_sysfs_read_profilex_settings(fp, kobj, | ||
| 256 | attr, buf, off, count, 1); | ||
| 257 | } | ||
| 258 | |||
| 259 | static ssize_t pyra_sysfs_read_profile3_settings(struct file *fp, | ||
| 260 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 261 | loff_t off, size_t count) | ||
| 262 | { | ||
| 263 | return pyra_sysfs_read_profilex_settings(fp, kobj, | ||
| 264 | attr, buf, off, count, 2); | ||
| 265 | } | ||
| 266 | |||
| 267 | static ssize_t pyra_sysfs_read_profile4_settings(struct file *fp, | ||
| 268 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 269 | loff_t off, size_t count) | ||
| 270 | { | ||
| 271 | return pyra_sysfs_read_profilex_settings(fp, kobj, | ||
| 272 | attr, buf, off, count, 3); | ||
| 273 | } | ||
| 274 | |||
| 275 | static ssize_t pyra_sysfs_read_profile5_settings(struct file *fp, | ||
| 276 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 277 | loff_t off, size_t count) | ||
| 278 | { | ||
| 279 | return pyra_sysfs_read_profilex_settings(fp, kobj, | ||
| 280 | attr, buf, off, count, 4); | ||
| 281 | } | ||
| 282 | |||
| 283 | static ssize_t pyra_sysfs_read_profilex_buttons(struct file *fp, | ||
| 284 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 285 | loff_t off, size_t count, int number) | ||
| 286 | { | ||
| 287 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 288 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 289 | |||
| 290 | if (off >= sizeof(struct pyra_profile_buttons)) | ||
| 291 | return 0; | ||
| 292 | |||
| 293 | if (off + count > sizeof(struct pyra_profile_buttons)) | ||
| 294 | count = sizeof(struct pyra_profile_buttons) - off; | ||
| 295 | |||
| 296 | mutex_lock(&pyra->pyra_lock); | ||
| 297 | memcpy(buf, ((char const *)&pyra->profile_buttons[number]) + off, | ||
| 298 | count); | ||
| 299 | mutex_unlock(&pyra->pyra_lock); | ||
| 300 | |||
| 301 | return count; | ||
| 302 | } | ||
| 303 | |||
| 304 | static ssize_t pyra_sysfs_read_profile1_buttons(struct file *fp, | ||
| 305 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 306 | loff_t off, size_t count) | ||
| 307 | { | ||
| 308 | return pyra_sysfs_read_profilex_buttons(fp, kobj, | ||
| 309 | attr, buf, off, count, 0); | ||
| 310 | } | ||
| 311 | |||
| 312 | static ssize_t pyra_sysfs_read_profile2_buttons(struct file *fp, | ||
| 313 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 314 | loff_t off, size_t count) | ||
| 315 | { | ||
| 316 | return pyra_sysfs_read_profilex_buttons(fp, kobj, | ||
| 317 | attr, buf, off, count, 1); | ||
| 318 | } | ||
| 319 | |||
| 320 | static ssize_t pyra_sysfs_read_profile3_buttons(struct file *fp, | ||
| 321 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 322 | loff_t off, size_t count) | ||
| 323 | { | ||
| 324 | return pyra_sysfs_read_profilex_buttons(fp, kobj, | ||
| 325 | attr, buf, off, count, 2); | ||
| 326 | } | ||
| 327 | |||
| 328 | static ssize_t pyra_sysfs_read_profile4_buttons(struct file *fp, | ||
| 329 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 330 | loff_t off, size_t count) | ||
| 331 | { | ||
| 332 | return pyra_sysfs_read_profilex_buttons(fp, kobj, | ||
| 333 | attr, buf, off, count, 3); | ||
| 334 | } | ||
| 335 | |||
| 336 | static ssize_t pyra_sysfs_read_profile5_buttons(struct file *fp, | ||
| 337 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 338 | loff_t off, size_t count) | ||
| 339 | { | ||
| 340 | return pyra_sysfs_read_profilex_buttons(fp, kobj, | ||
| 341 | attr, buf, off, count, 4); | ||
| 342 | } | ||
| 343 | |||
| 344 | static ssize_t pyra_sysfs_write_profile_settings(struct file *fp, | ||
| 345 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 346 | loff_t off, size_t count) | ||
| 347 | { | ||
| 348 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 349 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 350 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
| 351 | int retval = 0; | ||
| 352 | int difference; | ||
| 353 | int profile_number; | ||
| 354 | struct pyra_profile_settings *profile_settings; | ||
| 355 | |||
| 356 | if (off != 0 || count != sizeof(struct pyra_profile_settings)) | ||
| 357 | return -EINVAL; | ||
| 358 | |||
| 359 | profile_number = ((struct pyra_profile_settings const *)buf)->number; | ||
| 360 | profile_settings = &pyra->profile_settings[profile_number]; | ||
| 361 | |||
| 362 | mutex_lock(&pyra->pyra_lock); | ||
| 363 | difference = memcmp(buf, profile_settings, | ||
| 364 | sizeof(struct pyra_profile_settings)); | ||
| 365 | if (difference) { | ||
| 366 | retval = pyra_set_profile_settings(usb_dev, | ||
| 367 | (struct pyra_profile_settings const *)buf); | ||
| 368 | if (!retval) | ||
| 369 | memcpy(profile_settings, buf, | ||
| 370 | sizeof(struct pyra_profile_settings)); | ||
| 371 | } | ||
| 372 | mutex_unlock(&pyra->pyra_lock); | ||
| 373 | |||
| 374 | if (retval) | ||
| 375 | return retval; | ||
| 376 | |||
| 377 | return sizeof(struct pyra_profile_settings); | ||
| 378 | } | ||
| 379 | |||
| 380 | static ssize_t pyra_sysfs_write_profile_buttons(struct file *fp, | ||
| 381 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 382 | loff_t off, size_t count) | ||
| 383 | { | ||
| 384 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 385 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 386 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
| 387 | int retval = 0; | ||
| 388 | int difference; | ||
| 389 | int profile_number; | ||
| 390 | struct pyra_profile_buttons *profile_buttons; | ||
| 391 | |||
| 392 | if (off != 0 || count != sizeof(struct pyra_profile_buttons)) | ||
| 393 | return -EINVAL; | ||
| 394 | |||
| 395 | profile_number = ((struct pyra_profile_buttons const *)buf)->number; | ||
| 396 | profile_buttons = &pyra->profile_buttons[profile_number]; | ||
| 397 | |||
| 398 | mutex_lock(&pyra->pyra_lock); | ||
| 399 | difference = memcmp(buf, profile_buttons, | ||
| 400 | sizeof(struct pyra_profile_buttons)); | ||
| 401 | if (difference) { | ||
| 402 | retval = pyra_set_profile_buttons(usb_dev, | ||
| 403 | (struct pyra_profile_buttons const *)buf); | ||
| 404 | if (!retval) | ||
| 405 | memcpy(profile_buttons, buf, | ||
| 406 | sizeof(struct pyra_profile_buttons)); | ||
| 407 | } | ||
| 408 | mutex_unlock(&pyra->pyra_lock); | ||
| 409 | |||
| 410 | if (retval) | ||
| 411 | return retval; | ||
| 412 | |||
| 413 | return sizeof(struct pyra_profile_buttons); | ||
| 414 | } | ||
| 415 | |||
| 416 | static ssize_t pyra_sysfs_read_settings(struct file *fp, | ||
| 417 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 418 | loff_t off, size_t count) | ||
| 419 | { | ||
| 420 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 421 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 422 | |||
| 423 | if (off >= sizeof(struct pyra_settings)) | ||
| 424 | return 0; | ||
| 425 | |||
| 426 | if (off + count > sizeof(struct pyra_settings)) | ||
| 427 | count = sizeof(struct pyra_settings) - off; | ||
| 428 | |||
| 429 | mutex_lock(&pyra->pyra_lock); | ||
| 430 | memcpy(buf, ((char const *)&pyra->settings) + off, count); | ||
| 431 | mutex_unlock(&pyra->pyra_lock); | ||
| 432 | |||
| 433 | return count; | ||
| 434 | } | ||
| 435 | |||
| 436 | static ssize_t pyra_sysfs_write_settings(struct file *fp, | ||
| 437 | struct kobject *kobj, struct bin_attribute *attr, char *buf, | ||
| 438 | loff_t off, size_t count) | ||
| 439 | { | ||
| 440 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 441 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 442 | struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev)); | ||
| 443 | int retval = 0; | ||
| 444 | int difference; | ||
| 445 | |||
| 446 | if (off != 0 || count != sizeof(struct pyra_settings)) | ||
| 447 | return -EINVAL; | ||
| 448 | |||
| 449 | mutex_lock(&pyra->pyra_lock); | ||
| 450 | difference = memcmp(buf, &pyra->settings, sizeof(struct pyra_settings)); | ||
| 451 | if (difference) { | ||
| 452 | retval = pyra_set_settings(usb_dev, | ||
| 453 | (struct pyra_settings const *)buf); | ||
| 454 | if (!retval) | ||
| 455 | memcpy(&pyra->settings, buf, | ||
| 456 | sizeof(struct pyra_settings)); | ||
| 457 | } | ||
| 458 | mutex_unlock(&pyra->pyra_lock); | ||
| 459 | |||
| 460 | if (retval) | ||
| 461 | return retval; | ||
| 462 | |||
| 463 | profile_activated(pyra, pyra->settings.startup_profile); | ||
| 464 | |||
| 465 | return sizeof(struct pyra_settings); | ||
| 466 | } | ||
| 467 | |||
| 468 | |||
| 469 | static ssize_t pyra_sysfs_show_actual_cpi(struct device *dev, | ||
| 470 | struct device_attribute *attr, char *buf) | ||
| 471 | { | ||
| 472 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 473 | return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_cpi); | ||
| 474 | } | ||
| 475 | |||
| 476 | static ssize_t pyra_sysfs_show_actual_profile(struct device *dev, | ||
| 477 | struct device_attribute *attr, char *buf) | ||
| 478 | { | ||
| 479 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 480 | return snprintf(buf, PAGE_SIZE, "%d\n", pyra->actual_profile); | ||
| 481 | } | ||
| 482 | |||
| 483 | static ssize_t pyra_sysfs_show_firmware_version(struct device *dev, | ||
| 484 | struct device_attribute *attr, char *buf) | ||
| 485 | { | ||
| 486 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 487 | return snprintf(buf, PAGE_SIZE, "%d\n", pyra->firmware_version); | ||
| 488 | } | ||
| 489 | |||
| 490 | static ssize_t pyra_sysfs_show_startup_profile(struct device *dev, | ||
| 491 | struct device_attribute *attr, char *buf) | ||
| 492 | { | ||
| 493 | struct pyra_device *pyra = hid_get_drvdata(dev_get_drvdata(dev)); | ||
| 494 | return snprintf(buf, PAGE_SIZE, "%d\n", pyra->settings.startup_profile); | ||
| 495 | } | ||
| 496 | |||
| 497 | static DEVICE_ATTR(actual_cpi, 0440, pyra_sysfs_show_actual_cpi, NULL); | ||
| 498 | |||
| 499 | static DEVICE_ATTR(actual_profile, 0440, pyra_sysfs_show_actual_profile, NULL); | ||
| 500 | |||
| 501 | static DEVICE_ATTR(firmware_version, 0440, | ||
| 502 | pyra_sysfs_show_firmware_version, NULL); | ||
| 503 | |||
| 504 | static DEVICE_ATTR(startup_profile, 0440, | ||
| 505 | pyra_sysfs_show_startup_profile, NULL); | ||
| 506 | |||
| 507 | static struct attribute *pyra_attributes[] = { | ||
| 508 | &dev_attr_actual_cpi.attr, | ||
| 509 | &dev_attr_actual_profile.attr, | ||
| 510 | &dev_attr_firmware_version.attr, | ||
| 511 | &dev_attr_startup_profile.attr, | ||
| 512 | NULL | ||
| 513 | }; | ||
| 514 | |||
| 515 | static struct attribute_group pyra_attribute_group = { | ||
| 516 | .attrs = pyra_attributes | ||
| 517 | }; | ||
| 518 | |||
| 519 | static struct bin_attribute pyra_profile_settings_attr = { | ||
| 520 | .attr = { .name = "profile_settings", .mode = 0220 }, | ||
| 521 | .size = sizeof(struct pyra_profile_settings), | ||
| 522 | .write = pyra_sysfs_write_profile_settings | ||
| 523 | }; | ||
| 524 | |||
| 525 | static struct bin_attribute pyra_profile1_settings_attr = { | ||
| 526 | .attr = { .name = "profile1_settings", .mode = 0440 }, | ||
| 527 | .size = sizeof(struct pyra_profile_settings), | ||
| 528 | .read = pyra_sysfs_read_profile1_settings | ||
| 529 | }; | ||
| 530 | |||
| 531 | static struct bin_attribute pyra_profile2_settings_attr = { | ||
| 532 | .attr = { .name = "profile2_settings", .mode = 0440 }, | ||
| 533 | .size = sizeof(struct pyra_profile_settings), | ||
| 534 | .read = pyra_sysfs_read_profile2_settings | ||
| 535 | }; | ||
| 536 | |||
| 537 | static struct bin_attribute pyra_profile3_settings_attr = { | ||
| 538 | .attr = { .name = "profile3_settings", .mode = 0440 }, | ||
| 539 | .size = sizeof(struct pyra_profile_settings), | ||
| 540 | .read = pyra_sysfs_read_profile3_settings | ||
| 541 | }; | ||
| 542 | |||
| 543 | static struct bin_attribute pyra_profile4_settings_attr = { | ||
| 544 | .attr = { .name = "profile4_settings", .mode = 0440 }, | ||
| 545 | .size = sizeof(struct pyra_profile_settings), | ||
| 546 | .read = pyra_sysfs_read_profile4_settings | ||
| 547 | }; | ||
| 548 | |||
| 549 | static struct bin_attribute pyra_profile5_settings_attr = { | ||
| 550 | .attr = { .name = "profile5_settings", .mode = 0440 }, | ||
| 551 | .size = sizeof(struct pyra_profile_settings), | ||
| 552 | .read = pyra_sysfs_read_profile5_settings | ||
| 553 | }; | ||
| 554 | |||
| 555 | static struct bin_attribute pyra_profile_buttons_attr = { | ||
| 556 | .attr = { .name = "profile_buttons", .mode = 0220 }, | ||
| 557 | .size = sizeof(struct pyra_profile_buttons), | ||
| 558 | .write = pyra_sysfs_write_profile_buttons | ||
| 559 | }; | ||
| 560 | |||
| 561 | static struct bin_attribute pyra_profile1_buttons_attr = { | ||
| 562 | .attr = { .name = "profile1_buttons", .mode = 0440 }, | ||
| 563 | .size = sizeof(struct pyra_profile_buttons), | ||
| 564 | .read = pyra_sysfs_read_profile1_buttons | ||
| 565 | }; | ||
| 566 | |||
| 567 | static struct bin_attribute pyra_profile2_buttons_attr = { | ||
| 568 | .attr = { .name = "profile2_buttons", .mode = 0440 }, | ||
| 569 | .size = sizeof(struct pyra_profile_buttons), | ||
| 570 | .read = pyra_sysfs_read_profile2_buttons | ||
| 571 | }; | ||
| 572 | |||
| 573 | static struct bin_attribute pyra_profile3_buttons_attr = { | ||
| 574 | .attr = { .name = "profile3_buttons", .mode = 0440 }, | ||
| 575 | .size = sizeof(struct pyra_profile_buttons), | ||
| 576 | .read = pyra_sysfs_read_profile3_buttons | ||
| 577 | }; | ||
| 578 | |||
| 579 | static struct bin_attribute pyra_profile4_buttons_attr = { | ||
| 580 | .attr = { .name = "profile4_buttons", .mode = 0440 }, | ||
| 581 | .size = sizeof(struct pyra_profile_buttons), | ||
| 582 | .read = pyra_sysfs_read_profile4_buttons | ||
| 583 | }; | ||
| 584 | |||
| 585 | static struct bin_attribute pyra_profile5_buttons_attr = { | ||
| 586 | .attr = { .name = "profile5_buttons", .mode = 0440 }, | ||
| 587 | .size = sizeof(struct pyra_profile_buttons), | ||
| 588 | .read = pyra_sysfs_read_profile5_buttons | ||
| 589 | }; | ||
| 590 | |||
| 591 | static struct bin_attribute pyra_settings_attr = { | ||
| 592 | .attr = { .name = "settings", .mode = 0660 }, | ||
| 593 | .size = sizeof(struct pyra_settings), | ||
| 594 | .read = pyra_sysfs_read_settings, | ||
| 595 | .write = pyra_sysfs_write_settings | ||
| 596 | }; | ||
| 597 | |||
| 598 | static int pyra_create_sysfs_attributes(struct usb_interface *intf) | ||
| 599 | { | ||
| 600 | int retval; | ||
| 601 | |||
| 602 | retval = sysfs_create_group(&intf->dev.kobj, &pyra_attribute_group); | ||
| 603 | if (retval) | ||
| 604 | goto exit_1; | ||
| 605 | |||
| 606 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 607 | &pyra_profile_settings_attr); | ||
| 608 | if (retval) | ||
| 609 | goto exit_2; | ||
| 610 | |||
| 611 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 612 | &pyra_profile1_settings_attr); | ||
| 613 | if (retval) | ||
| 614 | goto exit_3; | ||
| 615 | |||
| 616 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 617 | &pyra_profile2_settings_attr); | ||
| 618 | if (retval) | ||
| 619 | goto exit_4; | ||
| 620 | |||
| 621 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 622 | &pyra_profile3_settings_attr); | ||
| 623 | if (retval) | ||
| 624 | goto exit_5; | ||
| 625 | |||
| 626 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 627 | &pyra_profile4_settings_attr); | ||
| 628 | if (retval) | ||
| 629 | goto exit_6; | ||
| 630 | |||
| 631 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 632 | &pyra_profile5_settings_attr); | ||
| 633 | if (retval) | ||
| 634 | goto exit_7; | ||
| 635 | |||
| 636 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 637 | &pyra_profile_buttons_attr); | ||
| 638 | if (retval) | ||
| 639 | goto exit_8; | ||
| 640 | |||
| 641 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 642 | &pyra_profile1_buttons_attr); | ||
| 643 | if (retval) | ||
| 644 | goto exit_9; | ||
| 645 | |||
| 646 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 647 | &pyra_profile2_buttons_attr); | ||
| 648 | if (retval) | ||
| 649 | goto exit_10; | ||
| 650 | |||
| 651 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 652 | &pyra_profile3_buttons_attr); | ||
| 653 | if (retval) | ||
| 654 | goto exit_11; | ||
| 655 | |||
| 656 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 657 | &pyra_profile4_buttons_attr); | ||
| 658 | if (retval) | ||
| 659 | goto exit_12; | ||
| 660 | |||
| 661 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 662 | &pyra_profile5_buttons_attr); | ||
| 663 | if (retval) | ||
| 664 | goto exit_13; | ||
| 665 | |||
| 666 | retval = sysfs_create_bin_file(&intf->dev.kobj, | ||
| 667 | &pyra_settings_attr); | ||
| 668 | if (retval) | ||
| 669 | goto exit_14; | ||
| 670 | |||
| 671 | return 0; | ||
| 672 | |||
| 673 | exit_14: | ||
| 674 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_buttons_attr); | ||
| 675 | exit_13: | ||
| 676 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_buttons_attr); | ||
| 677 | exit_12: | ||
| 678 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_buttons_attr); | ||
| 679 | exit_11: | ||
| 680 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_buttons_attr); | ||
| 681 | exit_10: | ||
| 682 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_buttons_attr); | ||
| 683 | exit_9: | ||
| 684 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_buttons_attr); | ||
| 685 | exit_8: | ||
| 686 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_settings_attr); | ||
| 687 | exit_7: | ||
| 688 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_settings_attr); | ||
| 689 | exit_6: | ||
| 690 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_settings_attr); | ||
| 691 | exit_5: | ||
| 692 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_settings_attr); | ||
| 693 | exit_4: | ||
| 694 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_settings_attr); | ||
| 695 | exit_3: | ||
| 696 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_settings_attr); | ||
| 697 | exit_2: | ||
| 698 | sysfs_remove_group(&intf->dev.kobj, &pyra_attribute_group); | ||
| 699 | exit_1: | ||
| 700 | return retval; | ||
| 701 | } | ||
| 702 | |||
| 703 | static void pyra_remove_sysfs_attributes(struct usb_interface *intf) | ||
| 704 | { | ||
| 705 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_settings_attr); | ||
| 706 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_buttons_attr); | ||
| 707 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_buttons_attr); | ||
| 708 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_buttons_attr); | ||
| 709 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_buttons_attr); | ||
| 710 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_buttons_attr); | ||
| 711 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_buttons_attr); | ||
| 712 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile5_settings_attr); | ||
| 713 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile4_settings_attr); | ||
| 714 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile3_settings_attr); | ||
| 715 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile2_settings_attr); | ||
| 716 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile1_settings_attr); | ||
| 717 | sysfs_remove_bin_file(&intf->dev.kobj, &pyra_profile_settings_attr); | ||
| 718 | sysfs_remove_group(&intf->dev.kobj, &pyra_attribute_group); | ||
| 719 | } | ||
| 720 | |||
| 721 | static int pyra_init_pyra_device_struct(struct usb_device *usb_dev, | ||
| 722 | struct pyra_device *pyra) | ||
| 723 | { | ||
| 724 | struct pyra_info *info; | ||
| 725 | int retval, i; | ||
| 726 | |||
| 727 | mutex_init(&pyra->pyra_lock); | ||
| 728 | |||
| 729 | info = kmalloc(sizeof(struct pyra_info), GFP_KERNEL); | ||
| 730 | if (!info) | ||
| 731 | return -ENOMEM; | ||
| 732 | retval = pyra_get_info(usb_dev, info); | ||
| 733 | if (retval) { | ||
| 734 | kfree(info); | ||
| 735 | return retval; | ||
| 736 | } | ||
| 737 | pyra->firmware_version = info->firmware_version; | ||
| 738 | kfree(info); | ||
| 739 | |||
| 740 | retval = pyra_get_settings(usb_dev, &pyra->settings); | ||
| 741 | if (retval) | ||
| 742 | return retval; | ||
| 743 | |||
| 744 | for (i = 0; i < 5; ++i) { | ||
| 745 | retval = pyra_get_profile_settings(usb_dev, | ||
| 746 | &pyra->profile_settings[i], i); | ||
| 747 | if (retval) | ||
| 748 | return retval; | ||
| 749 | |||
| 750 | retval = pyra_get_profile_buttons(usb_dev, | ||
| 751 | &pyra->profile_buttons[i], i); | ||
| 752 | if (retval) | ||
| 753 | return retval; | ||
| 754 | } | ||
| 755 | |||
| 756 | profile_activated(pyra, pyra->settings.startup_profile); | ||
| 757 | |||
| 758 | return 0; | ||
| 759 | } | ||
| 760 | |||
| 761 | static int pyra_init_specials(struct hid_device *hdev) | ||
| 762 | { | ||
| 763 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
| 764 | struct usb_device *usb_dev = interface_to_usbdev(intf); | ||
| 765 | struct pyra_device *pyra; | ||
| 766 | int retval; | ||
| 767 | |||
| 768 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
| 769 | == USB_INTERFACE_PROTOCOL_MOUSE) { | ||
| 770 | |||
| 771 | pyra = kzalloc(sizeof(*pyra), GFP_KERNEL); | ||
| 772 | if (!pyra) { | ||
| 773 | dev_err(&hdev->dev, "can't alloc device descriptor\n"); | ||
| 774 | return -ENOMEM; | ||
| 775 | } | ||
| 776 | hid_set_drvdata(hdev, pyra); | ||
| 777 | |||
| 778 | retval = pyra_init_pyra_device_struct(usb_dev, pyra); | ||
| 779 | if (retval) { | ||
| 780 | dev_err(&hdev->dev, | ||
| 781 | "couldn't init struct pyra_device\n"); | ||
| 782 | goto exit_free; | ||
| 783 | } | ||
| 784 | |||
| 785 | retval = roccat_connect(hdev); | ||
| 786 | if (retval < 0) { | ||
| 787 | dev_err(&hdev->dev, "couldn't init char dev\n"); | ||
| 788 | } else { | ||
| 789 | pyra->chrdev_minor = retval; | ||
| 790 | pyra->roccat_claimed = 1; | ||
| 791 | } | ||
| 792 | |||
| 793 | retval = pyra_create_sysfs_attributes(intf); | ||
| 794 | if (retval) { | ||
| 795 | dev_err(&hdev->dev, "cannot create sysfs files\n"); | ||
| 796 | goto exit_free; | ||
| 797 | } | ||
| 798 | } else { | ||
| 799 | hid_set_drvdata(hdev, NULL); | ||
| 800 | } | ||
| 801 | |||
| 802 | return 0; | ||
| 803 | exit_free: | ||
| 804 | kfree(pyra); | ||
| 805 | return retval; | ||
| 806 | } | ||
| 807 | |||
| 808 | static void pyra_remove_specials(struct hid_device *hdev) | ||
| 809 | { | ||
| 810 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
| 811 | struct pyra_device *pyra; | ||
| 812 | |||
| 813 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
| 814 | == USB_INTERFACE_PROTOCOL_MOUSE) { | ||
| 815 | pyra_remove_sysfs_attributes(intf); | ||
| 816 | pyra = hid_get_drvdata(hdev); | ||
| 817 | if (pyra->roccat_claimed) | ||
| 818 | roccat_disconnect(pyra->chrdev_minor); | ||
| 819 | kfree(hid_get_drvdata(hdev)); | ||
| 820 | } | ||
| 821 | } | ||
| 822 | |||
| 823 | static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id) | ||
| 824 | { | ||
| 825 | int retval; | ||
| 826 | |||
| 827 | retval = hid_parse(hdev); | ||
| 828 | if (retval) { | ||
| 829 | dev_err(&hdev->dev, "parse failed\n"); | ||
| 830 | goto exit; | ||
| 831 | } | ||
| 832 | |||
| 833 | retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); | ||
| 834 | if (retval) { | ||
| 835 | dev_err(&hdev->dev, "hw start failed\n"); | ||
| 836 | goto exit; | ||
| 837 | } | ||
| 838 | |||
| 839 | retval = pyra_init_specials(hdev); | ||
| 840 | if (retval) { | ||
| 841 | dev_err(&hdev->dev, "couldn't install mouse\n"); | ||
| 842 | goto exit_stop; | ||
| 843 | } | ||
| 844 | return 0; | ||
| 845 | |||
| 846 | exit_stop: | ||
| 847 | hid_hw_stop(hdev); | ||
| 848 | exit: | ||
| 849 | return retval; | ||
| 850 | } | ||
| 851 | |||
| 852 | static void pyra_remove(struct hid_device *hdev) | ||
| 853 | { | ||
| 854 | pyra_remove_specials(hdev); | ||
| 855 | hid_hw_stop(hdev); | ||
| 856 | } | ||
| 857 | |||
| 858 | static void pyra_keep_values_up_to_date(struct pyra_device *pyra, | ||
| 859 | u8 const *data) | ||
| 860 | { | ||
| 861 | struct pyra_mouse_event_button const *button_event; | ||
| 862 | |||
| 863 | switch (data[0]) { | ||
| 864 | case PYRA_MOUSE_REPORT_NUMBER_BUTTON: | ||
| 865 | button_event = (struct pyra_mouse_event_button const *)data; | ||
| 866 | switch (button_event->type) { | ||
| 867 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2: | ||
| 868 | profile_activated(pyra, button_event->data1 - 1); | ||
| 869 | break; | ||
| 870 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI: | ||
| 871 | pyra->actual_cpi = button_event->data1; | ||
| 872 | break; | ||
| 873 | } | ||
| 874 | break; | ||
| 875 | } | ||
| 876 | } | ||
| 877 | |||
| 878 | static void pyra_report_to_chrdev(struct pyra_device const *pyra, | ||
| 879 | u8 const *data) | ||
| 880 | { | ||
| 881 | struct pyra_roccat_report roccat_report; | ||
| 882 | struct pyra_mouse_event_button const *button_event; | ||
| 883 | |||
| 884 | if (data[0] != PYRA_MOUSE_REPORT_NUMBER_BUTTON) | ||
| 885 | return; | ||
| 886 | |||
| 887 | button_event = (struct pyra_mouse_event_button const *)data; | ||
| 888 | |||
| 889 | switch (button_event->type) { | ||
| 890 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2: | ||
| 891 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI: | ||
| 892 | roccat_report.type = button_event->type; | ||
| 893 | roccat_report.value = button_event->data1; | ||
| 894 | roccat_report.key = 0; | ||
| 895 | roccat_report_event(pyra->chrdev_minor, | ||
| 896 | (uint8_t const *)&roccat_report, | ||
| 897 | sizeof(struct pyra_roccat_report)); | ||
| 898 | break; | ||
| 899 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO: | ||
| 900 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT: | ||
| 901 | case PYRA_MOUSE_EVENT_BUTTON_TYPE_QUICKLAUNCH: | ||
| 902 | if (button_event->data2 == PYRA_MOUSE_EVENT_BUTTON_PRESS) { | ||
| 903 | roccat_report.type = button_event->type; | ||
| 904 | roccat_report.key = button_event->data1; | ||
| 905 | /* | ||
| 906 | * pyra reports profile numbers with range 1-5. | ||
| 907 | * Keeping this behaviour. | ||
| 908 | */ | ||
| 909 | roccat_report.value = pyra->actual_profile + 1; | ||
| 910 | roccat_report_event(pyra->chrdev_minor, | ||
| 911 | (uint8_t const *)&roccat_report, | ||
| 912 | sizeof(struct pyra_roccat_report)); | ||
| 913 | } | ||
| 914 | break; | ||
| 915 | } | ||
| 916 | } | ||
| 917 | |||
| 918 | static int pyra_raw_event(struct hid_device *hdev, struct hid_report *report, | ||
| 919 | u8 *data, int size) | ||
| 920 | { | ||
| 921 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | ||
| 922 | struct pyra_device *pyra = hid_get_drvdata(hdev); | ||
| 923 | |||
| 924 | if (intf->cur_altsetting->desc.bInterfaceProtocol | ||
| 925 | != USB_INTERFACE_PROTOCOL_MOUSE) | ||
| 926 | return 0; | ||
| 927 | |||
| 928 | pyra_keep_values_up_to_date(pyra, data); | ||
| 929 | |||
| 930 | if (pyra->roccat_claimed) | ||
| 931 | pyra_report_to_chrdev(pyra, data); | ||
| 932 | |||
| 933 | return 0; | ||
| 934 | } | ||
| 935 | |||
| 936 | static const struct hid_device_id pyra_devices[] = { | ||
| 937 | { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, | ||
| 938 | USB_DEVICE_ID_ROCCAT_PYRA_WIRED) }, | ||
| 939 | /* TODO add USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS after testing */ | ||
| 940 | { } | ||
| 941 | }; | ||
| 942 | |||
| 943 | MODULE_DEVICE_TABLE(hid, pyra_devices); | ||
| 944 | |||
| 945 | static struct hid_driver pyra_driver = { | ||
| 946 | .name = "pyra", | ||
| 947 | .id_table = pyra_devices, | ||
| 948 | .probe = pyra_probe, | ||
| 949 | .remove = pyra_remove, | ||
| 950 | .raw_event = pyra_raw_event | ||
| 951 | }; | ||
| 952 | |||
| 953 | static int __init pyra_init(void) | ||
| 954 | { | ||
| 955 | return hid_register_driver(&pyra_driver); | ||
| 956 | } | ||
| 957 | |||
| 958 | static void __exit pyra_exit(void) | ||
| 959 | { | ||
| 960 | hid_unregister_driver(&pyra_driver); | ||
| 961 | } | ||
| 962 | |||
| 963 | module_init(pyra_init); | ||
| 964 | module_exit(pyra_exit); | ||
| 965 | |||
| 966 | MODULE_AUTHOR("Stefan Achatz"); | ||
| 967 | MODULE_DESCRIPTION("USB Roccat Pyra driver"); | ||
| 968 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hid/hid-roccat-pyra.h b/drivers/hid/hid-roccat-pyra.h new file mode 100644 index 000000000000..22f80a8f26f9 --- /dev/null +++ b/drivers/hid/hid-roccat-pyra.h | |||
| @@ -0,0 +1,186 @@ | |||
| 1 | #ifndef __HID_ROCCAT_PYRA_H | ||
| 2 | #define __HID_ROCCAT_PYRA_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 6 | */ | ||
| 7 | |||
| 8 | /* | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the Free | ||
| 11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 12 | * any later version. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/types.h> | ||
| 16 | |||
| 17 | #pragma pack(push) | ||
| 18 | #pragma pack(1) | ||
| 19 | |||
| 20 | struct pyra_b { | ||
| 21 | uint8_t command; /* PYRA_COMMAND_B */ | ||
| 22 | uint8_t size; /* always 3 */ | ||
| 23 | uint8_t unknown; /* 1 */ | ||
| 24 | }; | ||
| 25 | |||
| 26 | struct pyra_control { | ||
| 27 | uint8_t command; /* PYRA_COMMAND_CONTROL */ | ||
| 28 | /* | ||
| 29 | * value is profile number for request_settings and request_buttons | ||
| 30 | * 1 if status ok for request_status | ||
| 31 | */ | ||
| 32 | uint8_t value; /* Range 0-4 */ | ||
| 33 | uint8_t request; | ||
| 34 | }; | ||
| 35 | |||
| 36 | enum pyra_control_requests { | ||
| 37 | PYRA_CONTROL_REQUEST_STATUS = 0x00, | ||
| 38 | PYRA_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10, | ||
| 39 | PYRA_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20 | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct pyra_settings { | ||
| 43 | uint8_t command; /* PYRA_COMMAND_SETTINGS */ | ||
| 44 | uint8_t size; /* always 3 */ | ||
| 45 | uint8_t startup_profile; /* Range 0-4! */ | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct pyra_profile_settings { | ||
| 49 | uint8_t command; /* PYRA_COMMAND_PROFILE_SETTINGS */ | ||
| 50 | uint8_t size; /* always 0xd */ | ||
| 51 | uint8_t number; /* Range 0-4 */ | ||
| 52 | uint8_t xysync; | ||
| 53 | uint8_t x_sensitivity; /* 0x1-0xa */ | ||
| 54 | uint8_t y_sensitivity; | ||
| 55 | uint8_t x_cpi; /* unused */ | ||
| 56 | uint8_t y_cpi; /* this value is for x and y */ | ||
| 57 | uint8_t lightswitch; /* 0 = off, 1 = on */ | ||
| 58 | uint8_t light_effect; | ||
| 59 | uint8_t handedness; | ||
| 60 | uint16_t checksum; /* byte sum */ | ||
| 61 | }; | ||
| 62 | |||
| 63 | struct pyra_profile_buttons { | ||
| 64 | uint8_t command; /* PYRA_COMMAND_PROFILE_BUTTONS */ | ||
| 65 | uint8_t size; /* always 0x13 */ | ||
| 66 | uint8_t number; /* Range 0-4 */ | ||
| 67 | uint8_t buttons[14]; | ||
| 68 | uint16_t checksum; /* byte sum */ | ||
| 69 | }; | ||
| 70 | |||
| 71 | struct pyra_info { | ||
| 72 | uint8_t command; /* PYRA_COMMAND_INFO */ | ||
| 73 | uint8_t size; /* always 6 */ | ||
| 74 | uint8_t firmware_version; | ||
| 75 | uint8_t unknown1; /* always 0 */ | ||
| 76 | uint8_t unknown2; /* always 1 */ | ||
| 77 | uint8_t unknown3; /* always 0 */ | ||
| 78 | }; | ||
| 79 | |||
| 80 | enum pyra_commands { | ||
| 81 | PYRA_COMMAND_CONTROL = 0x4, | ||
| 82 | PYRA_COMMAND_SETTINGS = 0x5, | ||
| 83 | PYRA_COMMAND_PROFILE_SETTINGS = 0x6, | ||
| 84 | PYRA_COMMAND_PROFILE_BUTTONS = 0x7, | ||
| 85 | PYRA_COMMAND_INFO = 0x9, | ||
| 86 | PYRA_COMMAND_B = 0xb | ||
| 87 | }; | ||
| 88 | |||
| 89 | enum pyra_usb_commands { | ||
| 90 | PYRA_USB_COMMAND_CONTROL = 0x304, | ||
| 91 | PYRA_USB_COMMAND_SETTINGS = 0x305, | ||
| 92 | PYRA_USB_COMMAND_PROFILE_SETTINGS = 0x306, | ||
| 93 | PYRA_USB_COMMAND_PROFILE_BUTTONS = 0x307, | ||
| 94 | PYRA_USB_COMMAND_INFO = 0x309, | ||
| 95 | PYRA_USB_COMMAND_B = 0x30b /* writes 3 bytes */ | ||
| 96 | }; | ||
| 97 | |||
| 98 | enum pyra_mouse_report_numbers { | ||
| 99 | PYRA_MOUSE_REPORT_NUMBER_HID = 1, | ||
| 100 | PYRA_MOUSE_REPORT_NUMBER_AUDIO = 2, | ||
| 101 | PYRA_MOUSE_REPORT_NUMBER_BUTTON = 3, | ||
| 102 | }; | ||
| 103 | |||
| 104 | struct pyra_mouse_event_button { | ||
| 105 | uint8_t report_number; /* always 3 */ | ||
| 106 | uint8_t unknown; /* always 0 */ | ||
| 107 | uint8_t type; | ||
| 108 | uint8_t data1; | ||
| 109 | uint8_t data2; | ||
| 110 | }; | ||
| 111 | |||
| 112 | struct pyra_mouse_event_audio { | ||
| 113 | uint8_t report_number; /* always 2 */ | ||
| 114 | uint8_t type; | ||
| 115 | uint8_t unused; /* always 0 */ | ||
| 116 | }; | ||
| 117 | |||
| 118 | /* hid audio controls */ | ||
| 119 | enum pyra_mouse_event_audio_types { | ||
| 120 | PYRA_MOUSE_EVENT_AUDIO_TYPE_MUTE = 0xe2, | ||
| 121 | PYRA_MOUSE_EVENT_AUDIO_TYPE_VOLUME_UP = 0xe9, | ||
| 122 | PYRA_MOUSE_EVENT_AUDIO_TYPE_VOLUME_DOWN = 0xea, | ||
| 123 | }; | ||
| 124 | |||
| 125 | enum pyra_mouse_event_button_types { | ||
| 126 | /* | ||
| 127 | * Mouse sends tilt events on report_number 1 and 3 | ||
| 128 | * Tilt events are sent repeatedly with 0.94s between first and second | ||
| 129 | * event and 0.22s on subsequent | ||
| 130 | */ | ||
| 131 | PYRA_MOUSE_EVENT_BUTTON_TYPE_TILT = 0x10, | ||
| 132 | |||
| 133 | /* | ||
| 134 | * These are sent sequentially | ||
| 135 | * data1 contains new profile number in range 1-5 | ||
| 136 | */ | ||
| 137 | PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_1 = 0x20, | ||
| 138 | PYRA_MOUSE_EVENT_BUTTON_TYPE_PROFILE_2 = 0x30, | ||
| 139 | |||
| 140 | /* | ||
| 141 | * data1 = button_number (rmp index) | ||
| 142 | * data2 = pressed/released | ||
| 143 | */ | ||
| 144 | PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO = 0x40, | ||
| 145 | PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT = 0x50, | ||
| 146 | |||
| 147 | /* | ||
| 148 | * data1 = button_number (rmp index) | ||
| 149 | */ | ||
| 150 | PYRA_MOUSE_EVENT_BUTTON_TYPE_QUICKLAUNCH = 0x60, | ||
| 151 | |||
| 152 | /* data1 = new cpi */ | ||
| 153 | PYRA_MOUSE_EVENT_BUTTON_TYPE_CPI = 0xb0, | ||
| 154 | |||
| 155 | /* data1 and data2 = new sensitivity */ | ||
| 156 | PYRA_MOUSE_EVENT_BUTTON_TYPE_SENSITIVITY = 0xc0, | ||
| 157 | |||
| 158 | PYRA_MOUSE_EVENT_BUTTON_TYPE_MULTIMEDIA = 0xf0, | ||
| 159 | }; | ||
| 160 | |||
| 161 | enum { | ||
| 162 | PYRA_MOUSE_EVENT_BUTTON_PRESS = 0, | ||
| 163 | PYRA_MOUSE_EVENT_BUTTON_RELEASE = 1, | ||
| 164 | }; | ||
| 165 | |||
| 166 | struct pyra_roccat_report { | ||
| 167 | uint8_t type; | ||
| 168 | uint8_t value; | ||
| 169 | uint8_t key; | ||
| 170 | }; | ||
| 171 | |||
| 172 | #pragma pack(pop) | ||
| 173 | |||
| 174 | struct pyra_device { | ||
| 175 | int actual_profile; | ||
| 176 | int actual_cpi; | ||
| 177 | int firmware_version; | ||
| 178 | int roccat_claimed; | ||
| 179 | int chrdev_minor; | ||
| 180 | struct mutex pyra_lock; | ||
| 181 | struct pyra_settings settings; | ||
| 182 | struct pyra_profile_settings profile_settings[5]; | ||
| 183 | struct pyra_profile_buttons profile_buttons[5]; | ||
| 184 | }; | ||
| 185 | |||
| 186 | #endif | ||
diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c index bda0fd60c98d..35894444e000 100644 --- a/drivers/hid/hid-samsung.c +++ b/drivers/hid/hid-samsung.c | |||
| @@ -61,10 +61,10 @@ static inline void samsung_irda_dev_trace(struct hid_device *hdev, | |||
| 61 | "descriptor\n", rsize); | 61 | "descriptor\n", rsize); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static void samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 64 | static __u8 *samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 65 | unsigned int rsize) | 65 | unsigned int *rsize) |
| 66 | { | 66 | { |
| 67 | if (rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 && | 67 | if (*rsize == 184 && rdesc[175] == 0x25 && rdesc[176] == 0x40 && |
| 68 | rdesc[177] == 0x75 && rdesc[178] == 0x30 && | 68 | rdesc[177] == 0x75 && rdesc[178] == 0x30 && |
| 69 | rdesc[179] == 0x95 && rdesc[180] == 0x01 && | 69 | rdesc[179] == 0x95 && rdesc[180] == 0x01 && |
| 70 | rdesc[182] == 0x40) { | 70 | rdesc[182] == 0x40) { |
| @@ -74,24 +74,25 @@ static void samsung_irda_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 74 | rdesc[180] = 0x06; | 74 | rdesc[180] = 0x06; |
| 75 | rdesc[182] = 0x42; | 75 | rdesc[182] = 0x42; |
| 76 | } else | 76 | } else |
| 77 | if (rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 && | 77 | if (*rsize == 203 && rdesc[192] == 0x15 && rdesc[193] == 0x0 && |
| 78 | rdesc[194] == 0x25 && rdesc[195] == 0x12) { | 78 | rdesc[194] == 0x25 && rdesc[195] == 0x12) { |
| 79 | samsung_irda_dev_trace(hdev, 203); | 79 | samsung_irda_dev_trace(hdev, 203); |
| 80 | rdesc[193] = 0x1; | 80 | rdesc[193] = 0x1; |
| 81 | rdesc[195] = 0xf; | 81 | rdesc[195] = 0xf; |
| 82 | } else | 82 | } else |
| 83 | if (rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 && | 83 | if (*rsize == 135 && rdesc[124] == 0x15 && rdesc[125] == 0x0 && |
| 84 | rdesc[126] == 0x25 && rdesc[127] == 0x11) { | 84 | rdesc[126] == 0x25 && rdesc[127] == 0x11) { |
| 85 | samsung_irda_dev_trace(hdev, 135); | 85 | samsung_irda_dev_trace(hdev, 135); |
| 86 | rdesc[125] = 0x1; | 86 | rdesc[125] = 0x1; |
| 87 | rdesc[127] = 0xe; | 87 | rdesc[127] = 0xe; |
| 88 | } else | 88 | } else |
| 89 | if (rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 && | 89 | if (*rsize == 171 && rdesc[160] == 0x15 && rdesc[161] == 0x0 && |
| 90 | rdesc[162] == 0x25 && rdesc[163] == 0x01) { | 90 | rdesc[162] == 0x25 && rdesc[163] == 0x01) { |
| 91 | samsung_irda_dev_trace(hdev, 171); | 91 | samsung_irda_dev_trace(hdev, 171); |
| 92 | rdesc[161] = 0x1; | 92 | rdesc[161] = 0x1; |
| 93 | rdesc[163] = 0x3; | 93 | rdesc[163] = 0x3; |
| 94 | } | 94 | } |
| 95 | return rdesc; | ||
| 95 | } | 96 | } |
| 96 | 97 | ||
| 97 | #define samsung_kbd_mouse_map_key_clear(c) \ | 98 | #define samsung_kbd_mouse_map_key_clear(c) \ |
| @@ -130,11 +131,12 @@ static int samsung_kbd_mouse_input_mapping(struct hid_device *hdev, | |||
| 130 | return 1; | 131 | return 1; |
| 131 | } | 132 | } |
| 132 | 133 | ||
| 133 | static void samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 134 | static __u8 *samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 134 | unsigned int rsize) | 135 | unsigned int *rsize) |
| 135 | { | 136 | { |
| 136 | if (USB_DEVICE_ID_SAMSUNG_IR_REMOTE == hdev->product) | 137 | if (USB_DEVICE_ID_SAMSUNG_IR_REMOTE == hdev->product) |
| 137 | samsung_irda_report_fixup(hdev, rdesc, rsize); | 138 | rdesc = samsung_irda_report_fixup(hdev, rdesc, rsize); |
| 139 | return rdesc; | ||
| 138 | } | 140 | } |
| 139 | 141 | ||
| 140 | static int samsung_input_mapping(struct hid_device *hdev, struct hid_input *hi, | 142 | static int samsung_input_mapping(struct hid_device *hdev, struct hid_input *hi, |
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 402d5574b574..677bb3da10e8 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
| @@ -24,24 +24,46 @@ | |||
| 24 | 24 | ||
| 25 | #include "hid-ids.h" | 25 | #include "hid-ids.h" |
| 26 | 26 | ||
| 27 | #define VAIO_RDESC_CONSTANT 0x0001 | 27 | #define VAIO_RDESC_CONSTANT (1 << 0) |
| 28 | #define SIXAXIS_CONTROLLER_USB (1 << 1) | ||
| 29 | #define SIXAXIS_CONTROLLER_BT (1 << 2) | ||
| 28 | 30 | ||
| 29 | struct sony_sc { | 31 | struct sony_sc { |
| 30 | unsigned long quirks; | 32 | unsigned long quirks; |
| 31 | }; | 33 | }; |
| 32 | 34 | ||
| 33 | /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ | 35 | /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ |
| 34 | static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 36 | static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 35 | unsigned int rsize) | 37 | unsigned int *rsize) |
| 36 | { | 38 | { |
| 37 | struct sony_sc *sc = hid_get_drvdata(hdev); | 39 | struct sony_sc *sc = hid_get_drvdata(hdev); |
| 38 | 40 | ||
| 39 | if ((sc->quirks & VAIO_RDESC_CONSTANT) && | 41 | if ((sc->quirks & VAIO_RDESC_CONSTANT) && |
| 40 | rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) { | 42 | *rsize >= 56 && rdesc[54] == 0x81 && rdesc[55] == 0x07) { |
| 41 | dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report " | 43 | dev_info(&hdev->dev, "Fixing up Sony Vaio VGX report " |
| 42 | "descriptor\n"); | 44 | "descriptor\n"); |
| 43 | rdesc[55] = 0x06; | 45 | rdesc[55] = 0x06; |
| 44 | } | 46 | } |
| 47 | return rdesc; | ||
| 48 | } | ||
| 49 | |||
| 50 | static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf, | ||
| 51 | size_t count, unsigned char report_type) | ||
| 52 | { | ||
| 53 | struct usb_interface *intf = to_usb_interface(hid->dev.parent); | ||
| 54 | struct usb_device *dev = interface_to_usbdev(intf); | ||
| 55 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
| 56 | int report_id = buf[0]; | ||
| 57 | int ret; | ||
| 58 | |||
| 59 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
| 60 | HID_REQ_SET_REPORT, | ||
| 61 | USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, | ||
| 62 | ((report_type + 1) << 8) | report_id, | ||
| 63 | interface->desc.bInterfaceNumber, buf, count, | ||
| 64 | USB_CTRL_SET_TIMEOUT); | ||
| 65 | |||
| 66 | return ret; | ||
| 45 | } | 67 | } |
| 46 | 68 | ||
| 47 | /* | 69 | /* |
| @@ -49,7 +71,7 @@ static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 49 | * to "operational". Without this, the ps3 controller will not report any | 71 | * to "operational". Without this, the ps3 controller will not report any |
| 50 | * events. | 72 | * events. |
| 51 | */ | 73 | */ |
| 52 | static int sony_set_operational_usb(struct hid_device *hdev) | 74 | static int sixaxis_set_operational_usb(struct hid_device *hdev) |
| 53 | { | 75 | { |
| 54 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | 76 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); |
| 55 | struct usb_device *dev = interface_to_usbdev(intf); | 77 | struct usb_device *dev = interface_to_usbdev(intf); |
| @@ -74,7 +96,7 @@ static int sony_set_operational_usb(struct hid_device *hdev) | |||
| 74 | return ret; | 96 | return ret; |
| 75 | } | 97 | } |
| 76 | 98 | ||
| 77 | static int sony_set_operational_bt(struct hid_device *hdev) | 99 | static int sixaxis_set_operational_bt(struct hid_device *hdev) |
| 78 | { | 100 | { |
| 79 | unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; | 101 | unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; |
| 80 | return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); | 102 | return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); |
| @@ -108,16 +130,14 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 108 | goto err_free; | 130 | goto err_free; |
| 109 | } | 131 | } |
| 110 | 132 | ||
| 111 | switch (hdev->bus) { | 133 | if (sc->quirks & SIXAXIS_CONTROLLER_USB) { |
| 112 | case BUS_USB: | 134 | hdev->hid_output_raw_report = sixaxis_usb_output_raw_report; |
| 113 | ret = sony_set_operational_usb(hdev); | 135 | ret = sixaxis_set_operational_usb(hdev); |
| 114 | break; | ||
| 115 | case BUS_BLUETOOTH: | ||
| 116 | ret = sony_set_operational_bt(hdev); | ||
| 117 | break; | ||
| 118 | default: | ||
| 119 | ret = 0; | ||
| 120 | } | 136 | } |
| 137 | else if (sc->quirks & SIXAXIS_CONTROLLER_BT) | ||
| 138 | ret = sixaxis_set_operational_bt(hdev); | ||
| 139 | else | ||
| 140 | ret = 0; | ||
| 121 | 141 | ||
| 122 | if (ret < 0) | 142 | if (ret < 0) |
| 123 | goto err_stop; | 143 | goto err_stop; |
| @@ -137,8 +157,10 @@ static void sony_remove(struct hid_device *hdev) | |||
| 137 | } | 157 | } |
| 138 | 158 | ||
| 139 | static const struct hid_device_id sony_devices[] = { | 159 | static const struct hid_device_id sony_devices[] = { |
| 140 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, | 160 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), |
| 141 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, | 161 | .driver_data = SIXAXIS_CONTROLLER_USB }, |
| 162 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), | ||
| 163 | .driver_data = SIXAXIS_CONTROLLER_BT }, | ||
| 142 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), | 164 | { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), |
| 143 | .driver_data = VAIO_RDESC_CONSTANT }, | 165 | .driver_data = VAIO_RDESC_CONSTANT }, |
| 144 | { } | 166 | { } |
diff --git a/drivers/hid/hid-stantum.c b/drivers/hid/hid-stantum.c index 90df886c5e04..3171be28c3d5 100644 --- a/drivers/hid/hid-stantum.c +++ b/drivers/hid/hid-stantum.c | |||
| @@ -249,6 +249,8 @@ static void stantum_remove(struct hid_device *hdev) | |||
| 249 | 249 | ||
| 250 | static const struct hid_device_id stantum_devices[] = { | 250 | static const struct hid_device_id stantum_devices[] = { |
| 251 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, | 251 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) }, |
| 252 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM) }, | ||
| 253 | { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX) }, | ||
| 252 | { } | 254 | { } |
| 253 | }; | 255 | }; |
| 254 | MODULE_DEVICE_TABLE(hid, stantum_devices); | 256 | MODULE_DEVICE_TABLE(hid, stantum_devices); |
diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c index 438107d9f1b2..164ed568f6cf 100644 --- a/drivers/hid/hid-sunplus.c +++ b/drivers/hid/hid-sunplus.c | |||
| @@ -22,16 +22,17 @@ | |||
| 22 | 22 | ||
| 23 | #include "hid-ids.h" | 23 | #include "hid-ids.h" |
| 24 | 24 | ||
| 25 | static void sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 25 | static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 26 | unsigned int rsize) | 26 | unsigned int *rsize) |
| 27 | { | 27 | { |
| 28 | if (rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && | 28 | if (*rsize >= 107 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && |
| 29 | rdesc[106] == 0x03) { | 29 | rdesc[106] == 0x03) { |
| 30 | dev_info(&hdev->dev, "fixing up Sunplus Wireless Desktop " | 30 | dev_info(&hdev->dev, "fixing up Sunplus Wireless Desktop " |
| 31 | "report descriptor\n"); | 31 | "report descriptor\n"); |
| 32 | rdesc[105] = rdesc[110] = 0x03; | 32 | rdesc[105] = rdesc[110] = 0x03; |
| 33 | rdesc[106] = rdesc[111] = 0x21; | 33 | rdesc[106] = rdesc[111] = 0x21; |
| 34 | } | 34 | } |
| 35 | return rdesc; | ||
| 35 | } | 36 | } |
| 36 | 37 | ||
| 37 | #define sp_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 38 | #define sp_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c new file mode 100644 index 000000000000..05fdc85a76e5 --- /dev/null +++ b/drivers/hid/hid-uclogic.c | |||
| @@ -0,0 +1,623 @@ | |||
| 1 | /* | ||
| 2 | * HID driver for UC-Logic devices not fully compliant with HID standard | ||
| 3 | * | ||
| 4 | * Copyright (c) 2010 Nikolai Kondrashov | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 11 | * any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/hid.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | |||
| 18 | #include "hid-ids.h" | ||
| 19 | |||
| 20 | /* | ||
| 21 | * The original descriptors of WPXXXXU tablets have three report IDs, of | ||
| 22 | * which only two are used (8 and 9), and the remaining (7) seems to have | ||
| 23 | * the originally intended pen description which was abandoned for some | ||
| 24 | * reason. From this unused description it is possible to extract the | ||
| 25 | * actual physical extents and resolution. All the models use the same | ||
| 26 | * descriptor with different extents for the unused report ID. | ||
| 27 | * | ||
| 28 | * Here it is: | ||
| 29 | * | ||
| 30 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 31 | * Usage (Pen), ; Pen (02h, application collection) | ||
| 32 | * Collection (Application), | ||
| 33 | * Report ID (7), | ||
| 34 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
| 35 | * Collection (Physical), | ||
| 36 | * Usage (Tip Switch), ; Tip switch (42h, momentary control) | ||
| 37 | * Usage (Barrel Switch), ; Barrel switch (44h, momentary control) | ||
| 38 | * Usage (Eraser), ; Eraser (45h, momentary control) | ||
| 39 | * Logical Minimum (0), | ||
| 40 | * Logical Maximum (1), | ||
| 41 | * Report Size (1), | ||
| 42 | * Report Count (3), | ||
| 43 | * Input (Variable), | ||
| 44 | * Report Count (3), | ||
| 45 | * Input (Constant, Variable), | ||
| 46 | * Usage (In Range), ; In range (32h, momentary control) | ||
| 47 | * Report Count (1), | ||
| 48 | * Input (Variable), | ||
| 49 | * Report Count (1), | ||
| 50 | * Input (Constant, Variable), | ||
| 51 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 52 | * Usage (X), ; X (30h, dynamic value) | ||
| 53 | * Report Size (16), | ||
| 54 | * Report Count (1), | ||
| 55 | * Push, | ||
| 56 | * Unit Exponent (13), | ||
| 57 | * Unit (Inch^3), | ||
| 58 | * Physical Minimum (0), | ||
| 59 | * Physical Maximum (Xpm), | ||
| 60 | * Logical Maximum (Xlm), | ||
| 61 | * Input (Variable), | ||
| 62 | * Usage (Y), ; Y (31h, dynamic value) | ||
| 63 | * Physical Maximum (Ypm), | ||
| 64 | * Logical Maximum (Ylm), | ||
| 65 | * Input (Variable), | ||
| 66 | * Pop, | ||
| 67 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 68 | * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) | ||
| 69 | * Logical Maximum (1023), | ||
| 70 | * Input (Variable), | ||
| 71 | * Report Size (16), | ||
| 72 | * End Collection, | ||
| 73 | * End Collection, | ||
| 74 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 75 | * Usage (Mouse), ; Mouse (02h, application collection) | ||
| 76 | * Collection (Application), | ||
| 77 | * Report ID (8), | ||
| 78 | * Usage (Pointer), ; Pointer (01h, physical collection) | ||
| 79 | * Collection (Physical), | ||
| 80 | * Usage Page (Button), ; Button (09h) | ||
| 81 | * Usage Minimum (01h), | ||
| 82 | * Usage Maximum (03h), | ||
| 83 | * Logical Minimum (0), | ||
| 84 | * Logical Maximum (1), | ||
| 85 | * Report Count (3), | ||
| 86 | * Report Size (1), | ||
| 87 | * Input (Variable), | ||
| 88 | * Report Count (5), | ||
| 89 | * Input (Constant), | ||
| 90 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 91 | * Usage (X), ; X (30h, dynamic value) | ||
| 92 | * Usage (Y), ; Y (31h, dynamic value) | ||
| 93 | * Usage (Wheel), ; Wheel (38h, dynamic value) | ||
| 94 | * Usage (00h), | ||
| 95 | * Logical Minimum (-127), | ||
| 96 | * Logical Maximum (127), | ||
| 97 | * Report Size (8), | ||
| 98 | * Report Count (4), | ||
| 99 | * Input (Variable, Relative), | ||
| 100 | * End Collection, | ||
| 101 | * End Collection, | ||
| 102 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 103 | * Usage (Mouse), ; Mouse (02h, application collection) | ||
| 104 | * Collection (Application), | ||
| 105 | * Report ID (9), | ||
| 106 | * Usage (Pointer), ; Pointer (01h, physical collection) | ||
| 107 | * Collection (Physical), | ||
| 108 | * Usage Page (Button), ; Button (09h) | ||
| 109 | * Usage Minimum (01h), | ||
| 110 | * Usage Maximum (03h), | ||
| 111 | * Logical Minimum (0), | ||
| 112 | * Logical Maximum (1), | ||
| 113 | * Report Count (3), | ||
| 114 | * Report Size (1), | ||
| 115 | * Input (Variable), | ||
| 116 | * Report Count (5), | ||
| 117 | * Input (Constant), | ||
| 118 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 119 | * Usage (X), ; X (30h, dynamic value) | ||
| 120 | * Usage (Y), ; Y (31h, dynamic value) | ||
| 121 | * Logical Minimum (0), | ||
| 122 | * Logical Maximum (32767), | ||
| 123 | * Physical Minimum (0), | ||
| 124 | * Physical Maximum (32767), | ||
| 125 | * Report Count (2), | ||
| 126 | * Report Size (16), | ||
| 127 | * Input (Variable), | ||
| 128 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 129 | * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) | ||
| 130 | * Logical Maximum (1023), | ||
| 131 | * Report Count (1), | ||
| 132 | * Report Size (16), | ||
| 133 | * Input (Variable), | ||
| 134 | * End Collection, | ||
| 135 | * End Collection | ||
| 136 | * | ||
| 137 | * Here are the extents values for the WPXXXXU models: | ||
| 138 | * | ||
| 139 | * Xpm Xlm Ypm Ylm | ||
| 140 | * WP4030U 4000 8000 3000 6000 | ||
| 141 | * WP5540U 5500 11000 4000 8000 | ||
| 142 | * WP8060U 8000 16000 6000 12000 | ||
| 143 | * | ||
| 144 | * This suggests that all of them have 2000 LPI resolution, as advertised. | ||
| 145 | */ | ||
| 146 | |||
| 147 | /* Size of the original descriptor of WPXXXXU tablets */ | ||
| 148 | #define WPXXXXU_RDESC_ORIG_SIZE 212 | ||
| 149 | |||
| 150 | /* | ||
| 151 | * Fixed WP4030U report descriptor. | ||
| 152 | * Although the hardware might actually support it, the mouse description | ||
| 153 | * has been removed, since there seems to be no devices having one and it | ||
| 154 | * wouldn't make much sense because of the working area size. | ||
| 155 | */ | ||
| 156 | static __u8 wp4030u_rdesc_fixed[] = { | ||
| 157 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
| 158 | 0x09, 0x02, /* Usage (Pen), */ | ||
| 159 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 160 | 0x85, 0x09, /* Report ID (9), */ | ||
| 161 | 0x09, 0x20, /* Usage (Stylus), */ | ||
| 162 | 0xA0, /* Collection (Physical), */ | ||
| 163 | 0x75, 0x01, /* Report Size (1), */ | ||
| 164 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
| 165 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
| 166 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
| 167 | 0x14, /* Logical Minimum (0), */ | ||
| 168 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 169 | 0x95, 0x03, /* Report Count (3), */ | ||
| 170 | 0x81, 0x02, /* Input (Variable), */ | ||
| 171 | 0x95, 0x05, /* Report Count (5), */ | ||
| 172 | 0x81, 0x01, /* Input (Constant), */ | ||
| 173 | 0x75, 0x10, /* Report Size (16), */ | ||
| 174 | 0x95, 0x01, /* Report Count (1), */ | ||
| 175 | 0x14, /* Logical Minimum (0), */ | ||
| 176 | 0xA4, /* Push, */ | ||
| 177 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 178 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
| 179 | 0x65, 0x13, /* Unit (Inch), */ | ||
| 180 | 0x34, /* Physical Minimum (0), */ | ||
| 181 | 0x09, 0x30, /* Usage (X), */ | ||
| 182 | 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ | ||
| 183 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
| 184 | 0x81, 0x02, /* Input (Variable), */ | ||
| 185 | 0x09, 0x31, /* Usage (Y), */ | ||
| 186 | 0x46, 0xB8, 0x0B, /* Physical Maximum (3000), */ | ||
| 187 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
| 188 | 0x81, 0x02, /* Input (Variable), */ | ||
| 189 | 0xB4, /* Pop, */ | ||
| 190 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
| 191 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
| 192 | 0x81, 0x02, /* Input (Variable), */ | ||
| 193 | 0xC0, /* End Collection, */ | ||
| 194 | 0xC0 /* End Collection */ | ||
| 195 | }; | ||
| 196 | |||
| 197 | /* Fixed WP5540U report descriptor */ | ||
| 198 | static __u8 wp5540u_rdesc_fixed[] = { | ||
| 199 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
| 200 | 0x09, 0x02, /* Usage (Pen), */ | ||
| 201 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 202 | 0x85, 0x09, /* Report ID (9), */ | ||
| 203 | 0x09, 0x20, /* Usage (Stylus), */ | ||
| 204 | 0xA0, /* Collection (Physical), */ | ||
| 205 | 0x75, 0x01, /* Report Size (1), */ | ||
| 206 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
| 207 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
| 208 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
| 209 | 0x14, /* Logical Minimum (0), */ | ||
| 210 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 211 | 0x95, 0x03, /* Report Count (3), */ | ||
| 212 | 0x81, 0x02, /* Input (Variable), */ | ||
| 213 | 0x95, 0x05, /* Report Count (5), */ | ||
| 214 | 0x81, 0x01, /* Input (Constant), */ | ||
| 215 | 0x75, 0x10, /* Report Size (16), */ | ||
| 216 | 0x95, 0x01, /* Report Count (1), */ | ||
| 217 | 0x14, /* Logical Minimum (0), */ | ||
| 218 | 0xA4, /* Push, */ | ||
| 219 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 220 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
| 221 | 0x65, 0x13, /* Unit (Inch), */ | ||
| 222 | 0x34, /* Physical Minimum (0), */ | ||
| 223 | 0x09, 0x30, /* Usage (X), */ | ||
| 224 | 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */ | ||
| 225 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
| 226 | 0x81, 0x02, /* Input (Variable), */ | ||
| 227 | 0x09, 0x31, /* Usage (Y), */ | ||
| 228 | 0x46, 0xA0, 0x0F, /* Physical Maximum (4000), */ | ||
| 229 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
| 230 | 0x81, 0x02, /* Input (Variable), */ | ||
| 231 | 0xB4, /* Pop, */ | ||
| 232 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
| 233 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
| 234 | 0x81, 0x02, /* Input (Variable), */ | ||
| 235 | 0xC0, /* End Collection, */ | ||
| 236 | 0xC0, /* End Collection, */ | ||
| 237 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 238 | 0x09, 0x02, /* Usage (Mouse), */ | ||
| 239 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 240 | 0x85, 0x08, /* Report ID (8), */ | ||
| 241 | 0x09, 0x01, /* Usage (Pointer), */ | ||
| 242 | 0xA0, /* Collection (Physical), */ | ||
| 243 | 0x75, 0x01, /* Report Size (1), */ | ||
| 244 | 0x05, 0x09, /* Usage Page (Button), */ | ||
| 245 | 0x19, 0x01, /* Usage Minimum (01h), */ | ||
| 246 | 0x29, 0x03, /* Usage Maximum (03h), */ | ||
| 247 | 0x14, /* Logical Minimum (0), */ | ||
| 248 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 249 | 0x95, 0x03, /* Report Count (3), */ | ||
| 250 | 0x81, 0x02, /* Input (Variable), */ | ||
| 251 | 0x95, 0x05, /* Report Count (5), */ | ||
| 252 | 0x81, 0x01, /* Input (Constant), */ | ||
| 253 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 254 | 0x75, 0x08, /* Report Size (8), */ | ||
| 255 | 0x09, 0x30, /* Usage (X), */ | ||
| 256 | 0x09, 0x31, /* Usage (Y), */ | ||
| 257 | 0x15, 0x81, /* Logical Minimum (-127), */ | ||
| 258 | 0x25, 0x7F, /* Logical Maximum (127), */ | ||
| 259 | 0x95, 0x02, /* Report Count (2), */ | ||
| 260 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
| 261 | 0x09, 0x38, /* Usage (Wheel), */ | ||
| 262 | 0x15, 0xFF, /* Logical Minimum (-1), */ | ||
| 263 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 264 | 0x95, 0x01, /* Report Count (1), */ | ||
| 265 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
| 266 | 0x81, 0x01, /* Input (Constant), */ | ||
| 267 | 0xC0, /* End Collection, */ | ||
| 268 | 0xC0 /* End Collection */ | ||
| 269 | }; | ||
| 270 | |||
| 271 | /* Fixed WP8060U report descriptor */ | ||
| 272 | static __u8 wp8060u_rdesc_fixed[] = { | ||
| 273 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
| 274 | 0x09, 0x02, /* Usage (Pen), */ | ||
| 275 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 276 | 0x85, 0x09, /* Report ID (9), */ | ||
| 277 | 0x09, 0x20, /* Usage (Stylus), */ | ||
| 278 | 0xA0, /* Collection (Physical), */ | ||
| 279 | 0x75, 0x01, /* Report Size (1), */ | ||
| 280 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
| 281 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
| 282 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
| 283 | 0x14, /* Logical Minimum (0), */ | ||
| 284 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 285 | 0x95, 0x03, /* Report Count (3), */ | ||
| 286 | 0x81, 0x02, /* Input (Variable), */ | ||
| 287 | 0x95, 0x05, /* Report Count (5), */ | ||
| 288 | 0x81, 0x01, /* Input (Constant), */ | ||
| 289 | 0x75, 0x10, /* Report Size (16), */ | ||
| 290 | 0x95, 0x01, /* Report Count (1), */ | ||
| 291 | 0x14, /* Logical Minimum (0), */ | ||
| 292 | 0xA4, /* Push, */ | ||
| 293 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 294 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
| 295 | 0x65, 0x13, /* Unit (Inch), */ | ||
| 296 | 0x34, /* Physical Minimum (0), */ | ||
| 297 | 0x09, 0x30, /* Usage (X), */ | ||
| 298 | 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ | ||
| 299 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
| 300 | 0x81, 0x02, /* Input (Variable), */ | ||
| 301 | 0x09, 0x31, /* Usage (Y), */ | ||
| 302 | 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ | ||
| 303 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
| 304 | 0x81, 0x02, /* Input (Variable), */ | ||
| 305 | 0xB4, /* Pop, */ | ||
| 306 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
| 307 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
| 308 | 0x81, 0x02, /* Input (Variable), */ | ||
| 309 | 0xC0, /* End Collection, */ | ||
| 310 | 0xC0, /* End Collection, */ | ||
| 311 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 312 | 0x09, 0x02, /* Usage (Mouse), */ | ||
| 313 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 314 | 0x85, 0x08, /* Report ID (8), */ | ||
| 315 | 0x09, 0x01, /* Usage (Pointer), */ | ||
| 316 | 0xA0, /* Collection (Physical), */ | ||
| 317 | 0x75, 0x01, /* Report Size (1), */ | ||
| 318 | 0x05, 0x09, /* Usage Page (Button), */ | ||
| 319 | 0x19, 0x01, /* Usage Minimum (01h), */ | ||
| 320 | 0x29, 0x03, /* Usage Maximum (03h), */ | ||
| 321 | 0x14, /* Logical Minimum (0), */ | ||
| 322 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 323 | 0x95, 0x03, /* Report Count (3), */ | ||
| 324 | 0x81, 0x02, /* Input (Variable), */ | ||
| 325 | 0x95, 0x05, /* Report Count (5), */ | ||
| 326 | 0x81, 0x01, /* Input (Constant), */ | ||
| 327 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 328 | 0x75, 0x08, /* Report Size (8), */ | ||
| 329 | 0x09, 0x30, /* Usage (X), */ | ||
| 330 | 0x09, 0x31, /* Usage (Y), */ | ||
| 331 | 0x15, 0x81, /* Logical Minimum (-127), */ | ||
| 332 | 0x25, 0x7F, /* Logical Maximum (127), */ | ||
| 333 | 0x95, 0x02, /* Report Count (2), */ | ||
| 334 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
| 335 | 0x09, 0x38, /* Usage (Wheel), */ | ||
| 336 | 0x15, 0xFF, /* Logical Minimum (-1), */ | ||
| 337 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 338 | 0x95, 0x01, /* Report Count (1), */ | ||
| 339 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
| 340 | 0x81, 0x01, /* Input (Constant), */ | ||
| 341 | 0xC0, /* End Collection, */ | ||
| 342 | 0xC0 /* End Collection */ | ||
| 343 | }; | ||
| 344 | |||
| 345 | /* | ||
| 346 | * Original PF1209 report descriptor. | ||
| 347 | * | ||
| 348 | * The descriptor is similar to WPXXXXU descriptors, with an addition of a | ||
| 349 | * feature report (ID 4) of unknown purpose. | ||
| 350 | * | ||
| 351 | * Although the advertised resolution is 4000 LPI the unused report ID | ||
| 352 | * (taken from WPXXXXU, it seems) states 2000 LPI, but it is probably | ||
| 353 | * incorrect and is a result of blind copying without understanding. Anyway | ||
| 354 | * the real logical extents are always scaled to 0..32767, which IMHO spoils | ||
| 355 | * the precision. | ||
| 356 | * | ||
| 357 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 358 | * Usage (Pen), ; Pen (02h, application collection) | ||
| 359 | * Collection (Application), | ||
| 360 | * Report ID (7), | ||
| 361 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
| 362 | * Collection (Physical), | ||
| 363 | * Usage (Tip Switch), ; Tip switch (42h, momentary control) | ||
| 364 | * Usage (Barrel Switch), ; Barrel switch (44h, momentary control) | ||
| 365 | * Usage (Eraser), ; Eraser (45h, momentary control) | ||
| 366 | * Logical Minimum (0), | ||
| 367 | * Logical Maximum (1), | ||
| 368 | * Report Size (1), | ||
| 369 | * Report Count (3), | ||
| 370 | * Input (Variable), | ||
| 371 | * Report Count (3), | ||
| 372 | * Input (Constant, Variable), | ||
| 373 | * Usage (In Range), ; In range (32h, momentary control) | ||
| 374 | * Report Count (1), | ||
| 375 | * Input (Variable), | ||
| 376 | * Report Count (1), | ||
| 377 | * Input (Constant, Variable), | ||
| 378 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 379 | * Usage (X), ; X (30h, dynamic value) | ||
| 380 | * Report Size (16), | ||
| 381 | * Report Count (1), | ||
| 382 | * Push, | ||
| 383 | * Unit Exponent (13), | ||
| 384 | * Unit (Inch^3), | ||
| 385 | * Physical Minimum (0), | ||
| 386 | * Physical Maximum (12000), | ||
| 387 | * Logical Maximum (24000), | ||
| 388 | * Input (Variable), | ||
| 389 | * Usage (Y), ; Y (31h, dynamic value) | ||
| 390 | * Physical Maximum (9000), | ||
| 391 | * Logical Maximum (18000), | ||
| 392 | * Input (Variable), | ||
| 393 | * Pop, | ||
| 394 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 395 | * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) | ||
| 396 | * Logical Maximum (1023), | ||
| 397 | * Input (Variable), | ||
| 398 | * Report Size (16), | ||
| 399 | * End Collection, | ||
| 400 | * End Collection, | ||
| 401 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 402 | * Usage (Mouse), ; Mouse (02h, application collection) | ||
| 403 | * Collection (Application), | ||
| 404 | * Report ID (8), | ||
| 405 | * Usage (Pointer), ; Pointer (01h, physical collection) | ||
| 406 | * Collection (Physical), | ||
| 407 | * Usage Page (Button), ; Button (09h) | ||
| 408 | * Usage Minimum (01h), | ||
| 409 | * Usage Maximum (03h), | ||
| 410 | * Logical Minimum (0), | ||
| 411 | * Logical Maximum (1), | ||
| 412 | * Report Count (3), | ||
| 413 | * Report Size (1), | ||
| 414 | * Input (Variable), | ||
| 415 | * Report Count (5), | ||
| 416 | * Input (Constant), | ||
| 417 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 418 | * Usage (X), ; X (30h, dynamic value) | ||
| 419 | * Usage (Y), ; Y (31h, dynamic value) | ||
| 420 | * Usage (Wheel), ; Wheel (38h, dynamic value) | ||
| 421 | * Usage (00h), | ||
| 422 | * Logical Minimum (-127), | ||
| 423 | * Logical Maximum (127), | ||
| 424 | * Report Size (8), | ||
| 425 | * Report Count (4), | ||
| 426 | * Input (Variable, Relative), | ||
| 427 | * End Collection, | ||
| 428 | * End Collection, | ||
| 429 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 430 | * Usage (Mouse), ; Mouse (02h, application collection) | ||
| 431 | * Collection (Application), | ||
| 432 | * Report ID (9), | ||
| 433 | * Usage (Pointer), ; Pointer (01h, physical collection) | ||
| 434 | * Collection (Physical), | ||
| 435 | * Usage Page (Button), ; Button (09h) | ||
| 436 | * Usage Minimum (01h), | ||
| 437 | * Usage Maximum (03h), | ||
| 438 | * Logical Minimum (0), | ||
| 439 | * Logical Maximum (1), | ||
| 440 | * Report Count (3), | ||
| 441 | * Report Size (1), | ||
| 442 | * Input (Variable), | ||
| 443 | * Report Count (5), | ||
| 444 | * Input (Constant), | ||
| 445 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 446 | * Usage (X), ; X (30h, dynamic value) | ||
| 447 | * Usage (Y), ; Y (31h, dynamic value) | ||
| 448 | * Logical Minimum (0), | ||
| 449 | * Logical Maximum (32767), | ||
| 450 | * Physical Minimum (0), | ||
| 451 | * Physical Maximum (32767), | ||
| 452 | * Report Count (2), | ||
| 453 | * Report Size (16), | ||
| 454 | * Input (Variable), | ||
| 455 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 456 | * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) | ||
| 457 | * Logical Maximum (1023), | ||
| 458 | * Report Count (1), | ||
| 459 | * Report Size (16), | ||
| 460 | * Input (Variable), | ||
| 461 | * End Collection, | ||
| 462 | * End Collection, | ||
| 463 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 464 | * Usage (00h), | ||
| 465 | * Collection (Application), | ||
| 466 | * Report ID (4), | ||
| 467 | * Logical Minimum (0), | ||
| 468 | * Logical Maximum (255), | ||
| 469 | * Usage (00h), | ||
| 470 | * Report Size (8), | ||
| 471 | * Report Count (3), | ||
| 472 | * Feature (Variable), | ||
| 473 | * End Collection | ||
| 474 | */ | ||
| 475 | |||
| 476 | /* Size of the original descriptor of PF1209 tablet */ | ||
| 477 | #define PF1209_RDESC_ORIG_SIZE 234 | ||
| 478 | |||
| 479 | /* | ||
| 480 | * Fixed PF1209 report descriptor | ||
| 481 | * | ||
| 482 | * The descriptor is fixed similarly to WP5540U and WP8060U, plus the | ||
| 483 | * feature report is removed, because its purpose is unknown and it is of no | ||
| 484 | * use to the generic HID driver anyway for now. | ||
| 485 | */ | ||
| 486 | static __u8 pf1209_rdesc_fixed[] = { | ||
| 487 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
| 488 | 0x09, 0x02, /* Usage (Pen), */ | ||
| 489 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 490 | 0x85, 0x09, /* Report ID (9), */ | ||
| 491 | 0x09, 0x20, /* Usage (Stylus), */ | ||
| 492 | 0xA0, /* Collection (Physical), */ | ||
| 493 | 0x75, 0x01, /* Report Size (1), */ | ||
| 494 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
| 495 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
| 496 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
| 497 | 0x14, /* Logical Minimum (0), */ | ||
| 498 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 499 | 0x95, 0x03, /* Report Count (3), */ | ||
| 500 | 0x81, 0x02, /* Input (Variable), */ | ||
| 501 | 0x95, 0x05, /* Report Count (5), */ | ||
| 502 | 0x81, 0x01, /* Input (Constant), */ | ||
| 503 | 0x75, 0x10, /* Report Size (16), */ | ||
| 504 | 0x95, 0x01, /* Report Count (1), */ | ||
| 505 | 0x14, /* Logical Minimum (0), */ | ||
| 506 | 0xA4, /* Push, */ | ||
| 507 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 508 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
| 509 | 0x65, 0x13, /* Unit (Inch), */ | ||
| 510 | 0x34, /* Physical Minimum (0), */ | ||
| 511 | 0x09, 0x30, /* Usage (X), */ | ||
| 512 | 0x46, 0xE0, 0x2E, /* Physical Maximum (12000), */ | ||
| 513 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
| 514 | 0x81, 0x02, /* Input (Variable), */ | ||
| 515 | 0x09, 0x31, /* Usage (Y), */ | ||
| 516 | 0x46, 0x28, 0x23, /* Physical Maximum (9000), */ | ||
| 517 | 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ | ||
| 518 | 0x81, 0x02, /* Input (Variable), */ | ||
| 519 | 0xB4, /* Pop, */ | ||
| 520 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
| 521 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
| 522 | 0x81, 0x02, /* Input (Variable), */ | ||
| 523 | 0xC0, /* End Collection, */ | ||
| 524 | 0xC0, /* End Collection, */ | ||
| 525 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 526 | 0x09, 0x02, /* Usage (Mouse), */ | ||
| 527 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 528 | 0x85, 0x08, /* Report ID (8), */ | ||
| 529 | 0x09, 0x01, /* Usage (Pointer), */ | ||
| 530 | 0xA0, /* Collection (Physical), */ | ||
| 531 | 0x75, 0x01, /* Report Size (1), */ | ||
| 532 | 0x05, 0x09, /* Usage Page (Button), */ | ||
| 533 | 0x19, 0x01, /* Usage Minimum (01h), */ | ||
| 534 | 0x29, 0x03, /* Usage Maximum (03h), */ | ||
| 535 | 0x14, /* Logical Minimum (0), */ | ||
| 536 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 537 | 0x95, 0x03, /* Report Count (3), */ | ||
| 538 | 0x81, 0x02, /* Input (Variable), */ | ||
| 539 | 0x95, 0x05, /* Report Count (5), */ | ||
| 540 | 0x81, 0x01, /* Input (Constant), */ | ||
| 541 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 542 | 0x75, 0x08, /* Report Size (8), */ | ||
| 543 | 0x09, 0x30, /* Usage (X), */ | ||
| 544 | 0x09, 0x31, /* Usage (Y), */ | ||
| 545 | 0x15, 0x81, /* Logical Minimum (-127), */ | ||
| 546 | 0x25, 0x7F, /* Logical Maximum (127), */ | ||
| 547 | 0x95, 0x02, /* Report Count (2), */ | ||
| 548 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
| 549 | 0x09, 0x38, /* Usage (Wheel), */ | ||
| 550 | 0x15, 0xFF, /* Logical Minimum (-1), */ | ||
| 551 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 552 | 0x95, 0x01, /* Report Count (1), */ | ||
| 553 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
| 554 | 0x81, 0x01, /* Input (Constant), */ | ||
| 555 | 0xC0, /* End Collection, */ | ||
| 556 | 0xC0 /* End Collection */ | ||
| 557 | }; | ||
| 558 | |||
| 559 | static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
| 560 | unsigned int *rsize) | ||
| 561 | { | ||
| 562 | switch (hdev->product) { | ||
| 563 | case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209: | ||
| 564 | if (*rsize == PF1209_RDESC_ORIG_SIZE) { | ||
| 565 | rdesc = pf1209_rdesc_fixed; | ||
| 566 | *rsize = sizeof(pf1209_rdesc_fixed); | ||
| 567 | } | ||
| 568 | break; | ||
| 569 | case USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U: | ||
| 570 | if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { | ||
| 571 | rdesc = wp4030u_rdesc_fixed; | ||
| 572 | *rsize = sizeof(wp4030u_rdesc_fixed); | ||
| 573 | } | ||
| 574 | break; | ||
| 575 | case USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U: | ||
| 576 | if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { | ||
| 577 | rdesc = wp5540u_rdesc_fixed; | ||
| 578 | *rsize = sizeof(wp5540u_rdesc_fixed); | ||
| 579 | } | ||
| 580 | break; | ||
| 581 | case USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U: | ||
| 582 | if (*rsize == WPXXXXU_RDESC_ORIG_SIZE) { | ||
| 583 | rdesc = wp8060u_rdesc_fixed; | ||
| 584 | *rsize = sizeof(wp8060u_rdesc_fixed); | ||
| 585 | } | ||
| 586 | break; | ||
| 587 | } | ||
| 588 | |||
| 589 | return rdesc; | ||
| 590 | } | ||
| 591 | |||
| 592 | static const struct hid_device_id uclogic_devices[] = { | ||
| 593 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, | ||
| 594 | USB_DEVICE_ID_UCLOGIC_TABLET_PF1209) }, | ||
| 595 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, | ||
| 596 | USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, | ||
| 597 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, | ||
| 598 | USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, | ||
| 599 | { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, | ||
| 600 | USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, | ||
| 601 | { } | ||
| 602 | }; | ||
| 603 | MODULE_DEVICE_TABLE(hid, uclogic_devices); | ||
| 604 | |||
| 605 | static struct hid_driver uclogic_driver = { | ||
| 606 | .name = "uclogic", | ||
| 607 | .id_table = uclogic_devices, | ||
| 608 | .report_fixup = uclogic_report_fixup, | ||
| 609 | }; | ||
| 610 | |||
| 611 | static int __init uclogic_init(void) | ||
| 612 | { | ||
| 613 | return hid_register_driver(&uclogic_driver); | ||
| 614 | } | ||
| 615 | |||
| 616 | static void __exit uclogic_exit(void) | ||
| 617 | { | ||
| 618 | hid_unregister_driver(&uclogic_driver); | ||
| 619 | } | ||
| 620 | |||
| 621 | module_init(uclogic_init); | ||
| 622 | module_exit(uclogic_exit); | ||
| 623 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-waltop.c b/drivers/hid/hid-waltop.c new file mode 100644 index 000000000000..b3a4163f2e67 --- /dev/null +++ b/drivers/hid/hid-waltop.c | |||
| @@ -0,0 +1,1099 @@ | |||
| 1 | /* | ||
| 2 | * HID driver for Waltop devices not fully compliant with HID standard | ||
| 3 | * | ||
| 4 | * Copyright (c) 2010 Nikolai Kondrashov | ||
| 5 | */ | ||
| 6 | |||
| 7 | /* | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the Free | ||
| 10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 11 | * any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/hid.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | |||
| 18 | #include "hid-ids.h" | ||
| 19 | |||
| 20 | /* | ||
| 21 | * There exists an official driver on the manufacturer's website, which | ||
| 22 | * wasn't submitted to the kernel, for some reason. The official driver | ||
| 23 | * doesn't seem to support extra features of some tablets, like wheels. | ||
| 24 | * | ||
| 25 | * It shows that the feature report ID 2 could be used to control any waltop | ||
| 26 | * tablet input mode, switching it between "default", "tablet" and "ink". | ||
| 27 | * | ||
| 28 | * This driver only uses "default" mode for all the supported tablets. This | ||
| 29 | * mode tries to be HID-compatible (not very successfully), but cripples the | ||
| 30 | * resolution of some tablets. | ||
| 31 | * | ||
| 32 | * The "tablet" mode uses some proprietary, yet decipherable protocol, which | ||
| 33 | * represents the correct resolution, but is possibly HID-incompatible (i.e. | ||
| 34 | * indescribable by a report descriptor). | ||
| 35 | * | ||
| 36 | * The purpose of the "ink" mode is unknown. | ||
| 37 | * | ||
| 38 | * The feature reports needed for switching to each mode are these: | ||
| 39 | * | ||
| 40 | * 02 16 00 default | ||
| 41 | * 02 16 01 tablet | ||
| 42 | * 02 16 02 ink | ||
| 43 | */ | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Original Slim Tablet 5.8 inch report descriptor. | ||
| 47 | * | ||
| 48 | * All the reports except the report with ID 16 (the stylus) are unused, | ||
| 49 | * possibly because the tablet is not configured to, or because they were | ||
| 50 | * just copied from a more capable model. The full purpose of features | ||
| 51 | * described for report ID 2 is unknown. | ||
| 52 | * | ||
| 53 | * The stylus buttons are described as three bit fields, whereas actually | ||
| 54 | * it's an "array", i.e. they're reported as button numbers (1, 2 and 3). | ||
| 55 | * The "eraser" field is not used. There is also a "push" without a "pop" in | ||
| 56 | * the stylus description. | ||
| 57 | * | ||
| 58 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 59 | * Usage (Mouse), ; Mouse (02h, application collection) | ||
| 60 | * Collection (Application), | ||
| 61 | * Report ID (1), | ||
| 62 | * Usage (Pointer), ; Pointer (01h, physical collection) | ||
| 63 | * Collection (Physical), | ||
| 64 | * Usage Page (Button), ; Button (09h) | ||
| 65 | * Usage Minimum (01h), | ||
| 66 | * Usage Maximum (05h), | ||
| 67 | * Logical Minimum (0), | ||
| 68 | * Logical Maximum (1), | ||
| 69 | * Report Size (1), | ||
| 70 | * Report Count (5), | ||
| 71 | * Input (Variable), | ||
| 72 | * Report Size (3), | ||
| 73 | * Report Count (1), | ||
| 74 | * Input (Constant, Variable), | ||
| 75 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 76 | * Usage (X), ; X (30h, dynamic value) | ||
| 77 | * Usage (Y), ; Y (31h, dynamic value) | ||
| 78 | * Usage (Wheel), ; Wheel (38h, dynamic value) | ||
| 79 | * Logical Minimum (-127), | ||
| 80 | * Logical Maximum (127), | ||
| 81 | * Report Size (8), | ||
| 82 | * Report Count (3), | ||
| 83 | * Input (Variable, Relative), | ||
| 84 | * End Collection, | ||
| 85 | * End Collection, | ||
| 86 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 87 | * Usage (Pen), ; Pen (02h, application collection) | ||
| 88 | * Collection (Application), | ||
| 89 | * Report ID (2), | ||
| 90 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
| 91 | * Collection (Physical), | ||
| 92 | * Usage (00h), | ||
| 93 | * Logical Minimum (0), | ||
| 94 | * Logical Maximum (255), | ||
| 95 | * Report Size (8), | ||
| 96 | * Report Count (7), | ||
| 97 | * Input (Variable), | ||
| 98 | * Usage (Azimuth), ; Azimuth (3Fh, dynamic value) | ||
| 99 | * Usage (Altitude), ; Altitude (40h, dynamic value) | ||
| 100 | * Logical Minimum (0), | ||
| 101 | * Logical Maximum (255), | ||
| 102 | * Report Size (8), | ||
| 103 | * Report Count (2), | ||
| 104 | * Feature (Variable), | ||
| 105 | * End Collection, | ||
| 106 | * Report ID (5), | ||
| 107 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 108 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
| 109 | * Collection (Physical), | ||
| 110 | * Usage (00h), | ||
| 111 | * Logical Minimum (0), | ||
| 112 | * Logical Maximum (255), | ||
| 113 | * Report Size (8), | ||
| 114 | * Report Count (7), | ||
| 115 | * Input (Variable), | ||
| 116 | * End Collection, | ||
| 117 | * Report ID (10), | ||
| 118 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 119 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
| 120 | * Collection (Physical), | ||
| 121 | * Usage (00h), | ||
| 122 | * Logical Minimum (0), | ||
| 123 | * Logical Maximum (255), | ||
| 124 | * Report Size (8), | ||
| 125 | * Report Count (3), | ||
| 126 | * Input (Variable), | ||
| 127 | * End Collection, | ||
| 128 | * Report ID (16), | ||
| 129 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
| 130 | * Collection (Physical), | ||
| 131 | * Usage (Tip Switch), ; Tip switch (42h, momentary control) | ||
| 132 | * Usage (Barrel Switch), ; Barrel switch (44h, momentary control) | ||
| 133 | * Usage (Invert), ; Invert (3Ch, momentary control) | ||
| 134 | * Usage (Eraser), ; Eraser (45h, momentary control) | ||
| 135 | * Usage (In Range), ; In range (32h, momentary control) | ||
| 136 | * Logical Minimum (0), | ||
| 137 | * Logical Maximum (1), | ||
| 138 | * Report Size (1), | ||
| 139 | * Report Count (5), | ||
| 140 | * Input (Variable), | ||
| 141 | * Report Count (3), | ||
| 142 | * Input (Constant, Variable), | ||
| 143 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 144 | * Usage (X), ; X (30h, dynamic value) | ||
| 145 | * Report Size (16), | ||
| 146 | * Report Count (1), | ||
| 147 | * Push, | ||
| 148 | * Unit Exponent (13), | ||
| 149 | * Unit (Inch^3), | ||
| 150 | * Logical Minimum (0), | ||
| 151 | * Logical Maximum (10000), | ||
| 152 | * Physical Minimum (0), | ||
| 153 | * Physical Maximum (10000), | ||
| 154 | * Input (Variable), | ||
| 155 | * Usage (Y), ; Y (31h, dynamic value) | ||
| 156 | * Logical Maximum (6000), | ||
| 157 | * Physical Maximum (6000), | ||
| 158 | * Input (Variable), | ||
| 159 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 160 | * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) | ||
| 161 | * Logical Minimum (0), | ||
| 162 | * Logical Maximum (1023), | ||
| 163 | * Physical Minimum (0), | ||
| 164 | * Physical Maximum (1023), | ||
| 165 | * Input (Variable), | ||
| 166 | * End Collection, | ||
| 167 | * End Collection | ||
| 168 | */ | ||
| 169 | |||
| 170 | /* Size of the original report descriptor of Slim Tablet 5.8 inch */ | ||
| 171 | #define SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE 222 | ||
| 172 | |||
| 173 | /* | ||
| 174 | * Fixed Slim Tablet 5.8 inch descriptor. | ||
| 175 | * | ||
| 176 | * All the reports except the stylus report (ID 16) were removed as unused. | ||
| 177 | * The stylus buttons description was fixed. | ||
| 178 | */ | ||
| 179 | static __u8 slim_tablet_5_8_inch_rdesc_fixed[] = { | ||
| 180 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
| 181 | 0x09, 0x02, /* Usage (Pen), */ | ||
| 182 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 183 | 0x85, 0x10, /* Report ID (16), */ | ||
| 184 | 0x09, 0x20, /* Usage (Stylus), */ | ||
| 185 | 0xA0, /* Collection (Physical), */ | ||
| 186 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
| 187 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
| 188 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
| 189 | 0x15, 0x01, /* Logical Minimum (1), */ | ||
| 190 | 0x25, 0x03, /* Logical Maximum (3), */ | ||
| 191 | 0x75, 0x04, /* Report Size (4), */ | ||
| 192 | 0x95, 0x01, /* Report Count (1), */ | ||
| 193 | 0x80, /* Input, */ | ||
| 194 | 0x09, 0x32, /* Usage (In Range), */ | ||
| 195 | 0x14, /* Logical Minimum (0), */ | ||
| 196 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 197 | 0x75, 0x01, /* Report Size (1), */ | ||
| 198 | 0x95, 0x01, /* Report Count (1), */ | ||
| 199 | 0x81, 0x02, /* Input (Variable), */ | ||
| 200 | 0x95, 0x03, /* Report Count (3), */ | ||
| 201 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 202 | 0x75, 0x10, /* Report Size (16), */ | ||
| 203 | 0x95, 0x01, /* Report Count (1), */ | ||
| 204 | 0x14, /* Logical Minimum (0), */ | ||
| 205 | 0xA4, /* Push, */ | ||
| 206 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 207 | 0x65, 0x13, /* Unit (Inch), */ | ||
| 208 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
| 209 | 0x34, /* Physical Minimum (0), */ | ||
| 210 | 0x09, 0x30, /* Usage (X), */ | ||
| 211 | 0x46, 0x88, 0x13, /* Physical Maximum (5000), */ | ||
| 212 | 0x26, 0x10, 0x27, /* Logical Maximum (10000), */ | ||
| 213 | 0x81, 0x02, /* Input (Variable), */ | ||
| 214 | 0x09, 0x31, /* Usage (Y), */ | ||
| 215 | 0x46, 0xB8, 0x0B, /* Physical Maximum (3000), */ | ||
| 216 | 0x26, 0x70, 0x17, /* Logical Maximum (6000), */ | ||
| 217 | 0x81, 0x02, /* Input (Variable), */ | ||
| 218 | 0xB4, /* Pop, */ | ||
| 219 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
| 220 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
| 221 | 0x81, 0x02, /* Input (Variable), */ | ||
| 222 | 0xC0, /* End Collection, */ | ||
| 223 | 0xC0 /* End Collection */ | ||
| 224 | }; | ||
| 225 | |||
| 226 | /* | ||
| 227 | * Original Slim Tablet 12.1 inch report descriptor. | ||
| 228 | * | ||
| 229 | * The descriptor is similar to the Slim Tablet 5.8 inch descriptor with the | ||
| 230 | * addition of a keyboard report, seemingly unused. It may have get here | ||
| 231 | * from a Media Tablet - probably an unimplemented feature. | ||
| 232 | * | ||
| 233 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 234 | * Usage (Mouse), ; Mouse (02h, application collection) | ||
| 235 | * Collection (Application), | ||
| 236 | * Report ID (1), | ||
| 237 | * Usage (Pointer), ; Pointer (01h, physical collection) | ||
| 238 | * Collection (Physical), | ||
| 239 | * Usage Page (Button), ; Button (09h) | ||
| 240 | * Usage Minimum (01h), | ||
| 241 | * Usage Maximum (05h), | ||
| 242 | * Logical Minimum (0), | ||
| 243 | * Logical Maximum (1), | ||
| 244 | * Report Size (1), | ||
| 245 | * Report Count (5), | ||
| 246 | * Input (Variable), | ||
| 247 | * Report Size (3), | ||
| 248 | * Report Count (1), | ||
| 249 | * Input (Constant, Variable), | ||
| 250 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 251 | * Usage (X), ; X (30h, dynamic value) | ||
| 252 | * Usage (Y), ; Y (31h, dynamic value) | ||
| 253 | * Usage (Wheel), ; Wheel (38h, dynamic value) | ||
| 254 | * Logical Minimum (-127), | ||
| 255 | * Logical Maximum (127), | ||
| 256 | * Report Size (8), | ||
| 257 | * Report Count (3), | ||
| 258 | * Input (Variable, Relative), | ||
| 259 | * End Collection, | ||
| 260 | * End Collection, | ||
| 261 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 262 | * Usage (Pen), ; Pen (02h, application collection) | ||
| 263 | * Collection (Application), | ||
| 264 | * Report ID (2), | ||
| 265 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
| 266 | * Collection (Physical), | ||
| 267 | * Usage (00h), | ||
| 268 | * Logical Minimum (0), | ||
| 269 | * Logical Maximum (255), | ||
| 270 | * Report Size (8), | ||
| 271 | * Report Count (7), | ||
| 272 | * Input (Variable), | ||
| 273 | * Usage (Azimuth), ; Azimuth (3Fh, dynamic value) | ||
| 274 | * Usage (Altitude), ; Altitude (40h, dynamic value) | ||
| 275 | * Logical Minimum (0), | ||
| 276 | * Logical Maximum (255), | ||
| 277 | * Report Size (8), | ||
| 278 | * Report Count (2), | ||
| 279 | * Feature (Variable), | ||
| 280 | * End Collection, | ||
| 281 | * Report ID (5), | ||
| 282 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 283 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
| 284 | * Collection (Physical), | ||
| 285 | * Usage (00h), | ||
| 286 | * Logical Minimum (0), | ||
| 287 | * Logical Maximum (255), | ||
| 288 | * Report Size (8), | ||
| 289 | * Report Count (7), | ||
| 290 | * Input (Variable), | ||
| 291 | * End Collection, | ||
| 292 | * Report ID (10), | ||
| 293 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 294 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
| 295 | * Collection (Physical), | ||
| 296 | * Usage (00h), | ||
| 297 | * Logical Minimum (0), | ||
| 298 | * Logical Maximum (255), | ||
| 299 | * Report Size (8), | ||
| 300 | * Report Count (3), | ||
| 301 | * Input (Variable), | ||
| 302 | * End Collection, | ||
| 303 | * Report ID (16), | ||
| 304 | * Usage (Stylus), ; Stylus (20h, logical collection) | ||
| 305 | * Collection (Physical), | ||
| 306 | * Usage (Tip Switch), ; Tip switch (42h, momentary control) | ||
| 307 | * Usage (Barrel Switch), ; Barrel switch (44h, momentary control) | ||
| 308 | * Usage (Invert), ; Invert (3Ch, momentary control) | ||
| 309 | * Usage (Eraser), ; Eraser (45h, momentary control) | ||
| 310 | * Usage (In Range), ; In range (32h, momentary control) | ||
| 311 | * Logical Minimum (0), | ||
| 312 | * Logical Maximum (1), | ||
| 313 | * Report Size (1), | ||
| 314 | * Report Count (5), | ||
| 315 | * Input (Variable), | ||
| 316 | * Report Count (3), | ||
| 317 | * Input (Constant, Variable), | ||
| 318 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 319 | * Usage (X), ; X (30h, dynamic value) | ||
| 320 | * Report Size (16), | ||
| 321 | * Report Count (1), | ||
| 322 | * Push, | ||
| 323 | * Unit Exponent (13), | ||
| 324 | * Unit (Inch^3), | ||
| 325 | * Logical Minimum (0), | ||
| 326 | * Logical Maximum (20000), | ||
| 327 | * Physical Minimum (0), | ||
| 328 | * Physical Maximum (20000), | ||
| 329 | * Input (Variable), | ||
| 330 | * Usage (Y), ; Y (31h, dynamic value) | ||
| 331 | * Logical Maximum (12500), | ||
| 332 | * Physical Maximum (12500), | ||
| 333 | * Input (Variable), | ||
| 334 | * Usage Page (Digitizer), ; Digitizer (0Dh) | ||
| 335 | * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) | ||
| 336 | * Logical Minimum (0), | ||
| 337 | * Logical Maximum (1023), | ||
| 338 | * Physical Minimum (0), | ||
| 339 | * Physical Maximum (1023), | ||
| 340 | * Input (Variable), | ||
| 341 | * End Collection, | ||
| 342 | * End Collection, | ||
| 343 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
| 344 | * Usage (Keyboard), ; Keyboard (06h, application collection) | ||
| 345 | * Collection (Application), | ||
| 346 | * Report ID (13), | ||
| 347 | * Usage Page (Keyboard), ; Keyboard/keypad (07h) | ||
| 348 | * Usage Minimum (KB Leftcontrol), ; Keyboard left control | ||
| 349 | * ; (E0h, dynamic value) | ||
| 350 | * Usage Maximum (KB Right GUI), ; Keyboard right GUI (E7h, dynamic value) | ||
| 351 | * Logical Minimum (0), | ||
| 352 | * Logical Maximum (1), | ||
| 353 | * Report Size (1), | ||
| 354 | * Report Count (8), | ||
| 355 | * Input (Variable), | ||
| 356 | * Report Size (8), | ||
| 357 | * Report Count (1), | ||
| 358 | * Input (Constant), | ||
| 359 | * Usage Page (Keyboard), ; Keyboard/keypad (07h) | ||
| 360 | * Usage Minimum (None), ; No event (00h, selector) | ||
| 361 | * Usage Maximum (KB Application), ; Keyboard Application (65h, selector) | ||
| 362 | * Logical Minimum (0), | ||
| 363 | * Logical Maximum (101), | ||
| 364 | * Report Size (8), | ||
| 365 | * Report Count (5), | ||
| 366 | * Input, | ||
| 367 | * End Collection | ||
| 368 | */ | ||
| 369 | |||
| 370 | /* Size of the original report descriptor of Slim Tablet 12.1 inch */ | ||
| 371 | #define SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE 269 | ||
| 372 | |||
| 373 | /* | ||
| 374 | * Fixed Slim Tablet 12.1 inch descriptor. | ||
| 375 | * | ||
| 376 | * All the reports except the stylus report (ID 16) were removed as unused. | ||
| 377 | * The stylus buttons description was fixed. | ||
| 378 | */ | ||
| 379 | static __u8 slim_tablet_12_1_inch_rdesc_fixed[] = { | ||
| 380 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
| 381 | 0x09, 0x02, /* Usage (Pen), */ | ||
| 382 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 383 | 0x85, 0x10, /* Report ID (16), */ | ||
| 384 | 0x09, 0x20, /* Usage (Stylus), */ | ||
| 385 | 0xA0, /* Collection (Physical), */ | ||
| 386 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
| 387 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
| 388 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
| 389 | 0x15, 0x01, /* Logical Minimum (1), */ | ||
| 390 | 0x25, 0x03, /* Logical Maximum (3), */ | ||
| 391 | 0x75, 0x04, /* Report Size (4), */ | ||
| 392 | 0x95, 0x01, /* Report Count (1), */ | ||
| 393 | 0x80, /* Input, */ | ||
| 394 | 0x09, 0x32, /* Usage (In Range), */ | ||
| 395 | 0x14, /* Logical Minimum (0), */ | ||
| 396 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 397 | 0x75, 0x01, /* Report Size (1), */ | ||
| 398 | 0x95, 0x01, /* Report Count (1), */ | ||
| 399 | 0x81, 0x02, /* Input (Variable), */ | ||
| 400 | 0x95, 0x03, /* Report Count (3), */ | ||
| 401 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 402 | 0x75, 0x10, /* Report Size (16), */ | ||
| 403 | 0x95, 0x01, /* Report Count (1), */ | ||
| 404 | 0x14, /* Logical Minimum (0), */ | ||
| 405 | 0xA4, /* Push, */ | ||
| 406 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 407 | 0x65, 0x13, /* Unit (Inch), */ | ||
| 408 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
| 409 | 0x34, /* Physical Minimum (0), */ | ||
| 410 | 0x09, 0x30, /* Usage (X), */ | ||
| 411 | 0x46, 0x10, 0x27, /* Physical Maximum (10000), */ | ||
| 412 | 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */ | ||
| 413 | 0x81, 0x02, /* Input (Variable), */ | ||
| 414 | 0x09, 0x31, /* Usage (Y), */ | ||
| 415 | 0x46, 0x6A, 0x18, /* Physical Maximum (6250), */ | ||
| 416 | 0x26, 0xD4, 0x30, /* Logical Maximum (12500), */ | ||
| 417 | 0x81, 0x02, /* Input (Variable), */ | ||
| 418 | 0xB4, /* Pop, */ | ||
| 419 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
| 420 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
| 421 | 0x81, 0x02, /* Input (Variable), */ | ||
| 422 | 0xC0, /* End Collection, */ | ||
| 423 | 0xC0 /* End Collection */ | ||
| 424 | }; | ||
| 425 | |||
| 426 | /* | ||
| 427 | * Original Media Tablet 10.6 inch report descriptor. | ||
| 428 | * | ||
| 429 | * There are at least two versions of this model in the wild. They are | ||
| 430 | * represented by Genius G-Pen M609 (older version) and Genius G-Pen M609X | ||
| 431 | * (newer version). | ||
| 432 | * | ||
| 433 | * Both versions have the usual pen with two barrel buttons and two | ||
| 434 | * identical wheels with center buttons in the top corners of the tablet | ||
| 435 | * base. They also have buttons on the top, between the wheels, for | ||
| 436 | * selecting the wheels' functions and wide/standard mode. In the wide mode | ||
| 437 | * the whole working surface is sensed, in the standard mode a narrower area | ||
| 438 | * is sensed, but the logical report extents remain the same. These modes | ||
| 439 | * correspond roughly to 16:9 and 4:3 aspect ratios respectively. | ||
| 440 | * | ||
| 441 | * The older version has three wheel function buttons ("scroll", "zoom" and | ||
| 442 | * "volume") and two separate buttons for wide and standard mode. The newer | ||
| 443 | * version has four wheel function buttons (plus "brush") and only one | ||
| 444 | * button is used for selecting wide/standard mode. So, the total number of | ||
| 445 | * buttons remains the same, but one of the mode buttons is repurposed as a | ||
| 446 | * wheels' function button in the newer version. | ||
| 447 | * | ||
| 448 | * The wheel functions are: | ||
| 449 | * scroll - the wheels act as scroll wheels, the center buttons switch | ||
| 450 | * between vertical and horizontal scrolling; | ||
| 451 | * zoom - the wheels zoom in/out, the buttons supposedly reset to 100%; | ||
| 452 | * volume - the wheels control the sound volume, the buttons mute; | ||
| 453 | * brush - the wheels are supposed to control brush width in a graphics | ||
| 454 | * editor, the buttons do nothing. | ||
| 455 | * | ||
| 456 | * Below is the newer version's report descriptor. It may very well be that | ||
| 457 | * the older version's descriptor is different and thus it won't be | ||
| 458 | * supported. | ||
| 459 | * | ||
| 460 | * The mouse report (ID 1) only uses the wheel field for reporting the tablet | ||
| 461 | * wheels' scroll mode. The keyboard report (ID 13) is used to report the | ||
| 462 | * wheels' zoom and brush control functions as key presses. The report ID 12 | ||
| 463 | * is used to report the wheels' volume control functions. The stylus report | ||
| 464 | * (ID 16) has the same problems as the Slim Tablet 5.8 inch report has. | ||
| 465 | * | ||
| 466 | * The rest of the reports are unused, at least in the default configuration. | ||
| 467 | * The purpose of the features is unknown. | ||
| 468 | * | ||
| 469 | * Usage Page (Desktop), | ||
| 470 | * Usage (Mouse), | ||
| 471 | * Collection (Application), | ||
| 472 | * Report ID (1), | ||
| 473 | * Usage (Pointer), | ||
| 474 | * Collection (Physical), | ||
| 475 | * Usage Page (Button), | ||
| 476 | * Usage Minimum (01h), | ||
| 477 | * Usage Maximum (05h), | ||
| 478 | * Logical Minimum (0), | ||
| 479 | * Logical Maximum (1), | ||
| 480 | * Report Size (1), | ||
| 481 | * Report Count (5), | ||
| 482 | * Input (Variable), | ||
| 483 | * Report Size (3), | ||
| 484 | * Report Count (1), | ||
| 485 | * Input (Constant, Variable), | ||
| 486 | * Usage Page (Desktop), | ||
| 487 | * Usage (X), | ||
| 488 | * Usage (Y), | ||
| 489 | * Usage (Wheel), | ||
| 490 | * Logical Minimum (-127), | ||
| 491 | * Logical Maximum (127), | ||
| 492 | * Report Size (8), | ||
| 493 | * Report Count (3), | ||
| 494 | * Input (Variable, Relative), | ||
| 495 | * End Collection, | ||
| 496 | * End Collection, | ||
| 497 | * Usage Page (Digitizer), | ||
| 498 | * Usage (Pen), | ||
| 499 | * Collection (Application), | ||
| 500 | * Report ID (2), | ||
| 501 | * Usage (Stylus), | ||
| 502 | * Collection (Physical), | ||
| 503 | * Usage (00h), | ||
| 504 | * Logical Minimum (0), | ||
| 505 | * Logical Maximum (255), | ||
| 506 | * Report Size (8), | ||
| 507 | * Report Count (7), | ||
| 508 | * Input (Variable), | ||
| 509 | * Usage (Azimuth), | ||
| 510 | * Usage (Altitude), | ||
| 511 | * Logical Minimum (0), | ||
| 512 | * Logical Maximum (255), | ||
| 513 | * Report Size (8), | ||
| 514 | * Report Count (2), | ||
| 515 | * Feature (Variable), | ||
| 516 | * End Collection, | ||
| 517 | * Report ID (5), | ||
| 518 | * Usage Page (Digitizer), | ||
| 519 | * Usage (Stylus), | ||
| 520 | * Collection (Physical), | ||
| 521 | * Usage (00h), | ||
| 522 | * Logical Minimum (0), | ||
| 523 | * Logical Maximum (255), | ||
| 524 | * Report Size (8), | ||
| 525 | * Report Count (7), | ||
| 526 | * Input (Variable), | ||
| 527 | * End Collection, | ||
| 528 | * Report ID (10), | ||
| 529 | * Usage Page (Digitizer), | ||
| 530 | * Usage (Stylus), | ||
| 531 | * Collection (Physical), | ||
| 532 | * Usage (00h), | ||
| 533 | * Logical Minimum (0), | ||
| 534 | * Logical Maximum (255), | ||
| 535 | * Report Size (8), | ||
| 536 | * Report Count (7), | ||
| 537 | * Input (Variable), | ||
| 538 | * End Collection, | ||
| 539 | * Report ID (16), | ||
| 540 | * Usage (Stylus), | ||
| 541 | * Collection (Physical), | ||
| 542 | * Usage (Tip Switch), | ||
| 543 | * Usage (Barrel Switch), | ||
| 544 | * Usage (Invert), | ||
| 545 | * Usage (Eraser), | ||
| 546 | * Usage (In Range), | ||
| 547 | * Logical Minimum (0), | ||
| 548 | * Logical Maximum (1), | ||
| 549 | * Report Size (1), | ||
| 550 | * Report Count (5), | ||
| 551 | * Input (Variable), | ||
| 552 | * Report Count (3), | ||
| 553 | * Input (Constant, Variable), | ||
| 554 | * Usage Page (Desktop), | ||
| 555 | * Usage (X), | ||
| 556 | * Report Size (16), | ||
| 557 | * Report Count (1), | ||
| 558 | * Push, | ||
| 559 | * Unit Exponent (13), | ||
| 560 | * Unit (Inch^3), | ||
| 561 | * Logical Minimum (0), | ||
| 562 | * Logical Maximum (18000), | ||
| 563 | * Physical Minimum (0), | ||
| 564 | * Physical Maximum (18000), | ||
| 565 | * Input (Variable), | ||
| 566 | * Usage (Y), | ||
| 567 | * Logical Maximum (11000), | ||
| 568 | * Physical Maximum (11000), | ||
| 569 | * Input (Variable), | ||
| 570 | * Usage Page (Digitizer), | ||
| 571 | * Usage (Tip Pressure), | ||
| 572 | * Logical Minimum (0), | ||
| 573 | * Logical Maximum (1023), | ||
| 574 | * Physical Minimum (0), | ||
| 575 | * Physical Maximum (1023), | ||
| 576 | * Input (Variable), | ||
| 577 | * End Collection, | ||
| 578 | * End Collection, | ||
| 579 | * Usage Page (Desktop), | ||
| 580 | * Usage (Keyboard), | ||
| 581 | * Collection (Application), | ||
| 582 | * Report ID (13), | ||
| 583 | * Usage Page (Keyboard), | ||
| 584 | * Usage Minimum (KB Leftcontrol), | ||
| 585 | * Usage Maximum (KB Right GUI), | ||
| 586 | * Logical Minimum (0), | ||
| 587 | * Logical Maximum (1), | ||
| 588 | * Report Size (1), | ||
| 589 | * Report Count (8), | ||
| 590 | * Input (Variable), | ||
| 591 | * Report Size (8), | ||
| 592 | * Report Count (1), | ||
| 593 | * Input (Constant), | ||
| 594 | * Usage Page (Keyboard), | ||
| 595 | * Usage Minimum (None), | ||
| 596 | * Usage Maximum (KB Application), | ||
| 597 | * Logical Minimum (0), | ||
| 598 | * Logical Maximum (101), | ||
| 599 | * Report Size (8), | ||
| 600 | * Report Count (5), | ||
| 601 | * Input, | ||
| 602 | * End Collection, | ||
| 603 | * Usage Page (Consumer), | ||
| 604 | * Usage (Consumer Control), | ||
| 605 | * Collection (Application), | ||
| 606 | * Report ID (12), | ||
| 607 | * Usage (Volume Inc), | ||
| 608 | * Usage (Volume Dec), | ||
| 609 | * Usage (Mute), | ||
| 610 | * Logical Minimum (0), | ||
| 611 | * Logical Maximum (1), | ||
| 612 | * Report Size (1), | ||
| 613 | * Report Count (3), | ||
| 614 | * Input (Variable, Relative), | ||
| 615 | * Report Size (5), | ||
| 616 | * Report Count (1), | ||
| 617 | * Input (Constant, Variable, Relative), | ||
| 618 | * End Collection | ||
| 619 | */ | ||
| 620 | |||
| 621 | /* Size of the original report descriptor of Media Tablet 10.6 inch */ | ||
| 622 | #define MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE 300 | ||
| 623 | |||
| 624 | /* | ||
| 625 | * Fixed Media Tablet 10.6 inch descriptor. | ||
| 626 | * | ||
| 627 | * The descriptions of reports unused in the default configuration are | ||
| 628 | * removed. The stylus report (ID 16) is fixed similarly to Slim Tablet 5.8 | ||
| 629 | * inch. The unused mouse report (ID 1) fields are replaced with constant | ||
| 630 | * padding. | ||
| 631 | * | ||
| 632 | * The keyboard report (ID 13) is hacked to instead have an "array" field | ||
| 633 | * reporting consumer page controls, and all the unused bits are masked out | ||
| 634 | * with constant padding. The "brush" wheels' function is represented as "Scan | ||
| 635 | * Previous/Next Track" controls due to the lack of brush controls in the | ||
| 636 | * usage tables specification. | ||
| 637 | */ | ||
| 638 | static __u8 media_tablet_10_6_inch_rdesc_fixed[] = { | ||
| 639 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
| 640 | 0x09, 0x02, /* Usage (Pen), */ | ||
| 641 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 642 | 0x85, 0x10, /* Report ID (16), */ | ||
| 643 | 0x09, 0x20, /* Usage (Stylus), */ | ||
| 644 | 0xA0, /* Collection (Physical), */ | ||
| 645 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
| 646 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
| 647 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
| 648 | 0x15, 0x01, /* Logical Minimum (1), */ | ||
| 649 | 0x25, 0x03, /* Logical Maximum (3), */ | ||
| 650 | 0x75, 0x04, /* Report Size (4), */ | ||
| 651 | 0x95, 0x01, /* Report Count (1), */ | ||
| 652 | 0x80, /* Input, */ | ||
| 653 | 0x75, 0x01, /* Report Size (1), */ | ||
| 654 | 0x09, 0x32, /* Usage (In Range), */ | ||
| 655 | 0x14, /* Logical Minimum (0), */ | ||
| 656 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 657 | 0x95, 0x01, /* Report Count (1), */ | ||
| 658 | 0x81, 0x02, /* Input (Variable), */ | ||
| 659 | 0x95, 0x03, /* Report Count (3), */ | ||
| 660 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 661 | 0x75, 0x10, /* Report Size (16), */ | ||
| 662 | 0x95, 0x01, /* Report Count (1), */ | ||
| 663 | 0x14, /* Logical Minimum (0), */ | ||
| 664 | 0xA4, /* Push, */ | ||
| 665 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 666 | 0x65, 0x13, /* Unit (Inch), */ | ||
| 667 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
| 668 | 0x34, /* Physical Minimum (0), */ | ||
| 669 | 0x09, 0x30, /* Usage (X), */ | ||
| 670 | 0x46, 0x28, 0x23, /* Physical Maximum (9000), */ | ||
| 671 | 0x26, 0x50, 0x46, /* Logical Maximum (18000), */ | ||
| 672 | 0x81, 0x02, /* Input (Variable), */ | ||
| 673 | 0x09, 0x31, /* Usage (Y), */ | ||
| 674 | 0x46, 0x7C, 0x15, /* Physical Maximum (5500), */ | ||
| 675 | 0x26, 0xF8, 0x2A, /* Logical Maximum (11000), */ | ||
| 676 | 0x81, 0x02, /* Input (Variable), */ | ||
| 677 | 0xB4, /* Pop, */ | ||
| 678 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
| 679 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
| 680 | 0x81, 0x02, /* Input (Variable), */ | ||
| 681 | 0xC0, /* End Collection, */ | ||
| 682 | 0xC0, /* End Collection, */ | ||
| 683 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 684 | 0x09, 0x02, /* Usage (Mouse), */ | ||
| 685 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 686 | 0x85, 0x01, /* Report ID (1), */ | ||
| 687 | 0x09, 0x01, /* Usage (Pointer), */ | ||
| 688 | 0xA0, /* Collection (Physical), */ | ||
| 689 | 0x75, 0x08, /* Report Size (8), */ | ||
| 690 | 0x95, 0x03, /* Report Count (3), */ | ||
| 691 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 692 | 0x95, 0x02, /* Report Count (2), */ | ||
| 693 | 0x15, 0xFF, /* Logical Minimum (-1), */ | ||
| 694 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 695 | 0x09, 0x38, /* Usage (Wheel), */ | ||
| 696 | 0x0B, 0x38, 0x02, /* Usage (Consumer AC Pan), */ | ||
| 697 | 0x0C, 0x00, | ||
| 698 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
| 699 | 0x95, 0x02, /* Report Count (2), */ | ||
| 700 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 701 | 0xC0, /* End Collection, */ | ||
| 702 | 0xC0, /* End Collection, */ | ||
| 703 | 0x05, 0x0C, /* Usage Page (Consumer), */ | ||
| 704 | 0x09, 0x01, /* Usage (Consumer Control), */ | ||
| 705 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 706 | 0x85, 0x0D, /* Report ID (13), */ | ||
| 707 | 0x95, 0x01, /* Report Count (1), */ | ||
| 708 | 0x75, 0x10, /* Report Size (16), */ | ||
| 709 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 710 | 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */ | ||
| 711 | 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ | ||
| 712 | 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ | ||
| 713 | 0x09, 0xB6, /* Usage (Scan Previous Track), */ | ||
| 714 | 0x09, 0xB5, /* Usage (Scan Next Track), */ | ||
| 715 | 0x08, /* Usage (00h), */ | ||
| 716 | 0x08, /* Usage (00h), */ | ||
| 717 | 0x08, /* Usage (00h), */ | ||
| 718 | 0x08, /* Usage (00h), */ | ||
| 719 | 0x08, /* Usage (00h), */ | ||
| 720 | 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ | ||
| 721 | 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ | ||
| 722 | 0x15, 0x0C, /* Logical Minimum (12), */ | ||
| 723 | 0x25, 0x17, /* Logical Maximum (23), */ | ||
| 724 | 0x75, 0x05, /* Report Size (5), */ | ||
| 725 | 0x80, /* Input, */ | ||
| 726 | 0x75, 0x03, /* Report Size (3), */ | ||
| 727 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 728 | 0x75, 0x20, /* Report Size (32), */ | ||
| 729 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 730 | 0xC0, /* End Collection, */ | ||
| 731 | 0x09, 0x01, /* Usage (Consumer Control), */ | ||
| 732 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 733 | 0x85, 0x0C, /* Report ID (12), */ | ||
| 734 | 0x75, 0x01, /* Report Size (1), */ | ||
| 735 | 0x09, 0xE9, /* Usage (Volume Inc), */ | ||
| 736 | 0x09, 0xEA, /* Usage (Volume Dec), */ | ||
| 737 | 0x09, 0xE2, /* Usage (Mute), */ | ||
| 738 | 0x14, /* Logical Minimum (0), */ | ||
| 739 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 740 | 0x95, 0x03, /* Report Count (3), */ | ||
| 741 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
| 742 | 0x95, 0x35, /* Report Count (53), */ | ||
| 743 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 744 | 0xC0 /* End Collection */ | ||
| 745 | }; | ||
| 746 | |||
| 747 | /* | ||
| 748 | * Original Media Tablet 14.1 inch report descriptor. | ||
| 749 | * | ||
| 750 | * There are at least two versions of this model in the wild. They are | ||
| 751 | * represented by Genius G-Pen M712 (older version) and Genius G-Pen M712X | ||
| 752 | * (newer version). The hardware difference between these versions is the same | ||
| 753 | * as between older and newer versions of Media Tablet 10.6 inch. The report | ||
| 754 | * descriptors are identical for both versions. | ||
| 755 | * | ||
| 756 | * The function, behavior and report descriptor of this tablet is similar to | ||
| 757 | * that of Media Tablet 10.6 inch. However, there is one more field (with | ||
| 758 | * Consumer AC Pan usage) in the mouse description. Then the tablet X and Y | ||
| 759 | * logical extents both get scaled to 0..16383 range (a hardware limit?), | ||
| 760 | * which kind of defeats the advertised 4000 LPI resolution, considering the | ||
| 761 | * physical extents of 12x7.25 inches. Plus, reports 5, 10 and 255 are used | ||
| 762 | * sometimes (while moving the pen) with unknown purpose. Also, the key codes | ||
| 763 | * generated for zoom in/out are different. | ||
| 764 | * | ||
| 765 | * Usage Page (Desktop), | ||
| 766 | * Usage (Mouse), | ||
| 767 | * Collection (Application), | ||
| 768 | * Report ID (1), | ||
| 769 | * Usage (Pointer), | ||
| 770 | * Collection (Physical), | ||
| 771 | * Usage Page (Button), | ||
| 772 | * Usage Minimum (01h), | ||
| 773 | * Usage Maximum (05h), | ||
| 774 | * Logical Minimum (0), | ||
| 775 | * Logical Maximum (1), | ||
| 776 | * Report Size (1), | ||
| 777 | * Report Count (5), | ||
| 778 | * Input (Variable), | ||
| 779 | * Report Size (3), | ||
| 780 | * Report Count (1), | ||
| 781 | * Input (Constant, Variable), | ||
| 782 | * Usage Page (Desktop), | ||
| 783 | * Usage (X), | ||
| 784 | * Usage (Y), | ||
| 785 | * Usage (Wheel), | ||
| 786 | * Logical Minimum (-127), | ||
| 787 | * Logical Maximum (127), | ||
| 788 | * Report Size (8), | ||
| 789 | * Report Count (3), | ||
| 790 | * Input (Variable, Relative), | ||
| 791 | * Usage Page (Consumer), | ||
| 792 | * Logical Minimum (-127), | ||
| 793 | * Logical Maximum (127), | ||
| 794 | * Report Size (8), | ||
| 795 | * Report Count (1), | ||
| 796 | * Usage (AC Pan), | ||
| 797 | * Input (Variable, Relative), | ||
| 798 | * End Collection, | ||
| 799 | * End Collection, | ||
| 800 | * Usage Page (Digitizer), | ||
| 801 | * Usage (Pen), | ||
| 802 | * Collection (Application), | ||
| 803 | * Report ID (2), | ||
| 804 | * Usage (Stylus), | ||
| 805 | * Collection (Physical), | ||
| 806 | * Usage (00h), | ||
| 807 | * Logical Minimum (0), | ||
| 808 | * Logical Maximum (255), | ||
| 809 | * Report Size (8), | ||
| 810 | * Report Count (7), | ||
| 811 | * Input (Variable), | ||
| 812 | * Usage (Azimuth), | ||
| 813 | * Usage (Altitude), | ||
| 814 | * Logical Minimum (0), | ||
| 815 | * Logical Maximum (255), | ||
| 816 | * Report Size (8), | ||
| 817 | * Report Count (2), | ||
| 818 | * Feature (Variable), | ||
| 819 | * End Collection, | ||
| 820 | * Report ID (5), | ||
| 821 | * Usage Page (Digitizer), | ||
| 822 | * Usage (Stylus), | ||
| 823 | * Collection (Physical), | ||
| 824 | * Usage (00h), | ||
| 825 | * Logical Minimum (0), | ||
| 826 | * Logical Maximum (255), | ||
| 827 | * Report Size (8), | ||
| 828 | * Report Count (7), | ||
| 829 | * Input (Variable), | ||
| 830 | * End Collection, | ||
| 831 | * Report ID (10), | ||
| 832 | * Usage Page (Digitizer), | ||
| 833 | * Usage (Stylus), | ||
| 834 | * Collection (Physical), | ||
| 835 | * Usage (00h), | ||
| 836 | * Logical Minimum (0), | ||
| 837 | * Logical Maximum (255), | ||
| 838 | * Report Size (8), | ||
| 839 | * Report Count (7), | ||
| 840 | * Input (Variable), | ||
| 841 | * End Collection, | ||
| 842 | * Report ID (16), | ||
| 843 | * Usage (Stylus), | ||
| 844 | * Collection (Physical), | ||
| 845 | * Usage (Tip Switch), | ||
| 846 | * Usage (Barrel Switch), | ||
| 847 | * Usage (Invert), | ||
| 848 | * Usage (Eraser), | ||
| 849 | * Usage (In Range), | ||
| 850 | * Logical Minimum (0), | ||
| 851 | * Logical Maximum (1), | ||
| 852 | * Report Size (1), | ||
| 853 | * Report Count (5), | ||
| 854 | * Input (Variable), | ||
| 855 | * Report Count (3), | ||
| 856 | * Input (Constant, Variable), | ||
| 857 | * Usage Page (Desktop), | ||
| 858 | * Usage (X), | ||
| 859 | * Report Size (16), | ||
| 860 | * Report Count (1), | ||
| 861 | * Push, | ||
| 862 | * Unit Exponent (13), | ||
| 863 | * Unit (Inch^3), | ||
| 864 | * Logical Minimum (0), | ||
| 865 | * Logical Maximum (16383), | ||
| 866 | * Physical Minimum (0), | ||
| 867 | * Physical Maximum (16383), | ||
| 868 | * Input (Variable), | ||
| 869 | * Usage (Y), | ||
| 870 | * Input (Variable), | ||
| 871 | * Usage Page (Digitizer), | ||
| 872 | * Usage (Tip Pressure), | ||
| 873 | * Logical Minimum (0), | ||
| 874 | * Logical Maximum (1023), | ||
| 875 | * Physical Minimum (0), | ||
| 876 | * Physical Maximum (1023), | ||
| 877 | * Input (Variable), | ||
| 878 | * End Collection, | ||
| 879 | * End Collection, | ||
| 880 | * Usage Page (Desktop), | ||
| 881 | * Usage (Keyboard), | ||
| 882 | * Collection (Application), | ||
| 883 | * Report ID (13), | ||
| 884 | * Usage Page (Keyboard), | ||
| 885 | * Usage Minimum (KB Leftcontrol), | ||
| 886 | * Usage Maximum (KB Right GUI), | ||
| 887 | * Logical Minimum (0), | ||
| 888 | * Logical Maximum (1), | ||
| 889 | * Report Size (1), | ||
| 890 | * Report Count (8), | ||
| 891 | * Input (Variable), | ||
| 892 | * Report Size (8), | ||
| 893 | * Report Count (1), | ||
| 894 | * Input (Constant), | ||
| 895 | * Usage Page (Keyboard), | ||
| 896 | * Usage Minimum (None), | ||
| 897 | * Usage Maximum (KB Application), | ||
| 898 | * Logical Minimum (0), | ||
| 899 | * Logical Maximum (101), | ||
| 900 | * Report Size (8), | ||
| 901 | * Report Count (5), | ||
| 902 | * Input, | ||
| 903 | * End Collection, | ||
| 904 | * Usage Page (Consumer), | ||
| 905 | * Usage (Consumer Control), | ||
| 906 | * Collection (Application), | ||
| 907 | * Report ID (12), | ||
| 908 | * Usage (Volume Inc), | ||
| 909 | * Usage (Volume Dec), | ||
| 910 | * Usage (Mute), | ||
| 911 | * Logical Minimum (0), | ||
| 912 | * Logical Maximum (1), | ||
| 913 | * Report Size (1), | ||
| 914 | * Report Count (3), | ||
| 915 | * Input (Variable, Relative), | ||
| 916 | * Report Size (5), | ||
| 917 | * Report Count (1), | ||
| 918 | * Input (Constant, Variable, Relative), | ||
| 919 | * End Collection | ||
| 920 | */ | ||
| 921 | |||
| 922 | /* Size of the original report descriptor of Media Tablet 14.1 inch */ | ||
| 923 | #define MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE 309 | ||
| 924 | |||
| 925 | /* | ||
| 926 | * Fixed Media Tablet 14.1 inch descriptor. | ||
| 927 | * It is fixed similarly to the Media Tablet 10.6 inch descriptor. | ||
| 928 | */ | ||
| 929 | static __u8 media_tablet_14_1_inch_rdesc_fixed[] = { | ||
| 930 | 0x05, 0x0D, /* Usage Page (Digitizer), */ | ||
| 931 | 0x09, 0x02, /* Usage (Pen), */ | ||
| 932 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 933 | 0x85, 0x10, /* Report ID (16), */ | ||
| 934 | 0x09, 0x20, /* Usage (Stylus), */ | ||
| 935 | 0xA0, /* Collection (Physical), */ | ||
| 936 | 0x09, 0x42, /* Usage (Tip Switch), */ | ||
| 937 | 0x09, 0x44, /* Usage (Barrel Switch), */ | ||
| 938 | 0x09, 0x46, /* Usage (Tablet Pick), */ | ||
| 939 | 0x15, 0x01, /* Logical Minimum (1), */ | ||
| 940 | 0x25, 0x03, /* Logical Maximum (3), */ | ||
| 941 | 0x75, 0x04, /* Report Size (4), */ | ||
| 942 | 0x95, 0x01, /* Report Count (1), */ | ||
| 943 | 0x80, /* Input, */ | ||
| 944 | 0x75, 0x01, /* Report Size (1), */ | ||
| 945 | 0x09, 0x32, /* Usage (In Range), */ | ||
| 946 | 0x14, /* Logical Minimum (0), */ | ||
| 947 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 948 | 0x95, 0x01, /* Report Count (1), */ | ||
| 949 | 0x81, 0x02, /* Input (Variable), */ | ||
| 950 | 0x95, 0x03, /* Report Count (3), */ | ||
| 951 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 952 | 0x75, 0x10, /* Report Size (16), */ | ||
| 953 | 0x95, 0x01, /* Report Count (1), */ | ||
| 954 | 0x14, /* Logical Minimum (0), */ | ||
| 955 | 0xA4, /* Push, */ | ||
| 956 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 957 | 0x65, 0x13, /* Unit (Inch), */ | ||
| 958 | 0x55, 0xFD, /* Unit Exponent (-3), */ | ||
| 959 | 0x34, /* Physical Minimum (0), */ | ||
| 960 | 0x09, 0x30, /* Usage (X), */ | ||
| 961 | 0x46, 0xE0, 0x2E, /* Physical Maximum (12000), */ | ||
| 962 | 0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */ | ||
| 963 | 0x81, 0x02, /* Input (Variable), */ | ||
| 964 | 0x09, 0x31, /* Usage (Y), */ | ||
| 965 | 0x46, 0x52, 0x1C, /* Physical Maximum (7250), */ | ||
| 966 | 0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */ | ||
| 967 | 0x81, 0x02, /* Input (Variable), */ | ||
| 968 | 0xB4, /* Pop, */ | ||
| 969 | 0x09, 0x30, /* Usage (Tip Pressure), */ | ||
| 970 | 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ | ||
| 971 | 0x81, 0x02, /* Input (Variable), */ | ||
| 972 | 0xC0, /* End Collection, */ | ||
| 973 | 0xC0, /* End Collection, */ | ||
| 974 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
| 975 | 0x09, 0x02, /* Usage (Mouse), */ | ||
| 976 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 977 | 0x85, 0x01, /* Report ID (1), */ | ||
| 978 | 0x09, 0x01, /* Usage (Pointer), */ | ||
| 979 | 0xA0, /* Collection (Physical), */ | ||
| 980 | 0x75, 0x08, /* Report Size (8), */ | ||
| 981 | 0x95, 0x03, /* Report Count (3), */ | ||
| 982 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 983 | 0x95, 0x02, /* Report Count (2), */ | ||
| 984 | 0x15, 0xFF, /* Logical Minimum (-1), */ | ||
| 985 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 986 | 0x09, 0x38, /* Usage (Wheel), */ | ||
| 987 | 0x0B, 0x38, 0x02, /* Usage (Consumer AC Pan), */ | ||
| 988 | 0x0C, 0x00, | ||
| 989 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
| 990 | 0xC0, /* End Collection, */ | ||
| 991 | 0xC0, /* End Collection, */ | ||
| 992 | 0x05, 0x0C, /* Usage Page (Consumer), */ | ||
| 993 | 0x09, 0x01, /* Usage (Consumer Control), */ | ||
| 994 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 995 | 0x85, 0x0D, /* Report ID (13), */ | ||
| 996 | 0x95, 0x01, /* Report Count (1), */ | ||
| 997 | 0x75, 0x10, /* Report Size (16), */ | ||
| 998 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 999 | 0x0A, 0x2F, 0x02, /* Usage (AC Zoom), */ | ||
| 1000 | 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ | ||
| 1001 | 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ | ||
| 1002 | 0x09, 0xB6, /* Usage (Scan Previous Track), */ | ||
| 1003 | 0x09, 0xB5, /* Usage (Scan Next Track), */ | ||
| 1004 | 0x08, /* Usage (00h), */ | ||
| 1005 | 0x08, /* Usage (00h), */ | ||
| 1006 | 0x08, /* Usage (00h), */ | ||
| 1007 | 0x08, /* Usage (00h), */ | ||
| 1008 | 0x08, /* Usage (00h), */ | ||
| 1009 | 0x0A, 0x2E, 0x02, /* Usage (AC Zoom Out), */ | ||
| 1010 | 0x0A, 0x2D, 0x02, /* Usage (AC Zoom In), */ | ||
| 1011 | 0x15, 0x0C, /* Logical Minimum (12), */ | ||
| 1012 | 0x25, 0x17, /* Logical Maximum (23), */ | ||
| 1013 | 0x75, 0x05, /* Report Size (5), */ | ||
| 1014 | 0x80, /* Input, */ | ||
| 1015 | 0x75, 0x03, /* Report Size (3), */ | ||
| 1016 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 1017 | 0x75, 0x20, /* Report Size (32), */ | ||
| 1018 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 1019 | 0xC0, /* End Collection, */ | ||
| 1020 | 0x09, 0x01, /* Usage (Consumer Control), */ | ||
| 1021 | 0xA1, 0x01, /* Collection (Application), */ | ||
| 1022 | 0x85, 0x0C, /* Report ID (12), */ | ||
| 1023 | 0x75, 0x01, /* Report Size (1), */ | ||
| 1024 | 0x09, 0xE9, /* Usage (Volume Inc), */ | ||
| 1025 | 0x09, 0xEA, /* Usage (Volume Dec), */ | ||
| 1026 | 0x09, 0xE2, /* Usage (Mute), */ | ||
| 1027 | 0x14, /* Logical Minimum (0), */ | ||
| 1028 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
| 1029 | 0x95, 0x03, /* Report Count (3), */ | ||
| 1030 | 0x81, 0x06, /* Input (Variable, Relative), */ | ||
| 1031 | 0x75, 0x05, /* Report Size (5), */ | ||
| 1032 | 0x81, 0x03, /* Input (Constant, Variable), */ | ||
| 1033 | 0xC0 /* End Collection */ | ||
| 1034 | }; | ||
| 1035 | |||
| 1036 | static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
| 1037 | unsigned int *rsize) | ||
| 1038 | { | ||
| 1039 | switch (hdev->product) { | ||
| 1040 | case USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH: | ||
| 1041 | if (*rsize == SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE) { | ||
| 1042 | rdesc = slim_tablet_5_8_inch_rdesc_fixed; | ||
| 1043 | *rsize = sizeof(slim_tablet_5_8_inch_rdesc_fixed); | ||
| 1044 | } | ||
| 1045 | break; | ||
| 1046 | case USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH: | ||
| 1047 | if (*rsize == SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE) { | ||
| 1048 | rdesc = slim_tablet_12_1_inch_rdesc_fixed; | ||
| 1049 | *rsize = sizeof(slim_tablet_12_1_inch_rdesc_fixed); | ||
| 1050 | } | ||
| 1051 | break; | ||
| 1052 | case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH: | ||
| 1053 | if (*rsize == MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE) { | ||
| 1054 | rdesc = media_tablet_10_6_inch_rdesc_fixed; | ||
| 1055 | *rsize = sizeof(media_tablet_10_6_inch_rdesc_fixed); | ||
| 1056 | } | ||
| 1057 | break; | ||
| 1058 | case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH: | ||
| 1059 | if (*rsize == MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE) { | ||
| 1060 | rdesc = media_tablet_14_1_inch_rdesc_fixed; | ||
| 1061 | *rsize = sizeof(media_tablet_14_1_inch_rdesc_fixed); | ||
| 1062 | } | ||
| 1063 | break; | ||
| 1064 | } | ||
| 1065 | return rdesc; | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | static const struct hid_device_id waltop_devices[] = { | ||
| 1069 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | ||
| 1070 | USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, | ||
| 1071 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | ||
| 1072 | USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, | ||
| 1073 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | ||
| 1074 | USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH) }, | ||
| 1075 | { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, | ||
| 1076 | USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, | ||
| 1077 | { } | ||
| 1078 | }; | ||
| 1079 | MODULE_DEVICE_TABLE(hid, waltop_devices); | ||
| 1080 | |||
| 1081 | static struct hid_driver waltop_driver = { | ||
| 1082 | .name = "waltop", | ||
| 1083 | .id_table = waltop_devices, | ||
| 1084 | .report_fixup = waltop_report_fixup, | ||
| 1085 | }; | ||
| 1086 | |||
| 1087 | static int __init waltop_init(void) | ||
| 1088 | { | ||
| 1089 | return hid_register_driver(&waltop_driver); | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | static void __exit waltop_exit(void) | ||
| 1093 | { | ||
| 1094 | hid_unregister_driver(&waltop_driver); | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | module_init(waltop_init); | ||
| 1098 | module_exit(waltop_exit); | ||
| 1099 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hid/hid-zydacron.c b/drivers/hid/hid-zydacron.c index 9e8d35a203e4..aac1f9273149 100644 --- a/drivers/hid/hid-zydacron.c +++ b/drivers/hid/hid-zydacron.c | |||
| @@ -27,10 +27,10 @@ struct zc_device { | |||
| 27 | * Zydacron remote control has an invalid HID report descriptor, | 27 | * Zydacron remote control has an invalid HID report descriptor, |
| 28 | * that needs fixing before we can parse it. | 28 | * that needs fixing before we can parse it. |
| 29 | */ | 29 | */ |
| 30 | static void zc_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 30 | static __u8 *zc_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 31 | unsigned int rsize) | 31 | unsigned int *rsize) |
| 32 | { | 32 | { |
| 33 | if (rsize >= 253 && | 33 | if (*rsize >= 253 && |
| 34 | rdesc[0x96] == 0xbc && rdesc[0x97] == 0xff && | 34 | rdesc[0x96] == 0xbc && rdesc[0x97] == 0xff && |
| 35 | rdesc[0xca] == 0xbc && rdesc[0xcb] == 0xff && | 35 | rdesc[0xca] == 0xbc && rdesc[0xcb] == 0xff && |
| 36 | rdesc[0xe1] == 0xbc && rdesc[0xe2] == 0xff) { | 36 | rdesc[0xe1] == 0xbc && rdesc[0xe2] == 0xff) { |
| @@ -40,6 +40,7 @@ static void zc_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 40 | rdesc[0x96] = rdesc[0xca] = rdesc[0xe1] = 0x0c; | 40 | rdesc[0x96] = rdesc[0xca] = rdesc[0xe1] = 0x0c; |
| 41 | rdesc[0x97] = rdesc[0xcb] = rdesc[0xe2] = 0x00; | 41 | rdesc[0x97] = rdesc[0xcb] = rdesc[0xe2] = 0x00; |
| 42 | } | 42 | } |
| 43 | return rdesc; | ||
| 43 | } | 44 | } |
| 44 | 45 | ||
| 45 | #define zc_map_key_clear(c) \ | 46 | #define zc_map_key_clear(c) \ |
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 925992f549f0..8a4b32dca9f7 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
| @@ -218,9 +218,13 @@ static int hidraw_release(struct inode * inode, struct file * file) | |||
| 218 | unsigned int minor = iminor(inode); | 218 | unsigned int minor = iminor(inode); |
| 219 | struct hidraw *dev; | 219 | struct hidraw *dev; |
| 220 | struct hidraw_list *list = file->private_data; | 220 | struct hidraw_list *list = file->private_data; |
| 221 | int ret; | ||
| 221 | 222 | ||
| 222 | if (!hidraw_table[minor]) | 223 | mutex_lock(&minors_lock); |
| 223 | return -ENODEV; | 224 | if (!hidraw_table[minor]) { |
| 225 | ret = -ENODEV; | ||
| 226 | goto unlock; | ||
| 227 | } | ||
| 224 | 228 | ||
| 225 | list_del(&list->node); | 229 | list_del(&list->node); |
| 226 | dev = hidraw_table[minor]; | 230 | dev = hidraw_table[minor]; |
| @@ -233,10 +237,12 @@ static int hidraw_release(struct inode * inode, struct file * file) | |||
| 233 | kfree(list->hidraw); | 237 | kfree(list->hidraw); |
| 234 | } | 238 | } |
| 235 | } | 239 | } |
| 236 | |||
| 237 | kfree(list); | 240 | kfree(list); |
| 241 | ret = 0; | ||
| 242 | unlock: | ||
| 243 | mutex_unlock(&minors_lock); | ||
| 238 | 244 | ||
| 239 | return 0; | 245 | return ret; |
| 240 | } | 246 | } |
| 241 | 247 | ||
| 242 | static long hidraw_ioctl(struct file *file, unsigned int cmd, | 248 | static long hidraw_ioctl(struct file *file, unsigned int cmd, |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 599041a7f670..5489eab3a6bd 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -807,9 +807,10 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co | |||
| 807 | struct usb_host_interface *interface = intf->cur_altsetting; | 807 | struct usb_host_interface *interface = intf->cur_altsetting; |
| 808 | int ret; | 808 | int ret; |
| 809 | 809 | ||
| 810 | if (usbhid->urbout) { | 810 | if (usbhid->urbout && report_type != HID_FEATURE_REPORT) { |
| 811 | int actual_length; | 811 | int actual_length; |
| 812 | int skipped_report_id = 0; | 812 | int skipped_report_id = 0; |
| 813 | |||
| 813 | if (buf[0] == 0x0) { | 814 | if (buf[0] == 0x0) { |
| 814 | /* Don't send the Report ID */ | 815 | /* Don't send the Report ID */ |
| 815 | buf++; | 816 | buf++; |
| @@ -1469,9 +1470,6 @@ static int __init hid_init(void) | |||
| 1469 | retval = usbhid_quirks_init(quirks_param); | 1470 | retval = usbhid_quirks_init(quirks_param); |
| 1470 | if (retval) | 1471 | if (retval) |
| 1471 | goto usbhid_quirks_init_fail; | 1472 | goto usbhid_quirks_init_fail; |
| 1472 | retval = hiddev_init(); | ||
| 1473 | if (retval) | ||
| 1474 | goto hiddev_init_fail; | ||
| 1475 | retval = usb_register(&hid_driver); | 1473 | retval = usb_register(&hid_driver); |
| 1476 | if (retval) | 1474 | if (retval) |
| 1477 | goto usb_register_fail; | 1475 | goto usb_register_fail; |
| @@ -1479,8 +1477,6 @@ static int __init hid_init(void) | |||
| 1479 | 1477 | ||
| 1480 | return 0; | 1478 | return 0; |
| 1481 | usb_register_fail: | 1479 | usb_register_fail: |
| 1482 | hiddev_exit(); | ||
| 1483 | hiddev_init_fail: | ||
| 1484 | usbhid_quirks_exit(); | 1480 | usbhid_quirks_exit(); |
| 1485 | usbhid_quirks_init_fail: | 1481 | usbhid_quirks_init_fail: |
| 1486 | hid_unregister_driver(&hid_usb_driver); | 1482 | hid_unregister_driver(&hid_usb_driver); |
| @@ -1493,7 +1489,6 @@ no_queue: | |||
| 1493 | static void __exit hid_exit(void) | 1489 | static void __exit hid_exit(void) |
| 1494 | { | 1490 | { |
| 1495 | usb_deregister(&hid_driver); | 1491 | usb_deregister(&hid_driver); |
| 1496 | hiddev_exit(); | ||
| 1497 | usbhid_quirks_exit(); | 1492 | usbhid_quirks_exit(); |
| 1498 | hid_unregister_driver(&hid_usb_driver); | 1493 | hid_unregister_driver(&hid_usb_driver); |
| 1499 | destroy_workqueue(resumption_waker); | 1494 | destroy_workqueue(resumption_waker); |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index f0260c699adb..2c185477eeb3 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
| @@ -34,7 +34,6 @@ static const struct hid_blacklist { | |||
| 34 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, | 34 | { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, |
| 35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, | 35 | { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, |
| 36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, | 36 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, |
| 37 | { USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH, HID_QUIRK_MULTI_INPUT }, | ||
| 38 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, | 37 | { USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER, HID_QUIRK_MULTI_INPUT }, |
| 39 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART, HID_QUIRK_MULTI_INPUT }, | 38 | { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART, HID_QUIRK_MULTI_INPUT }, |
| 40 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, | 39 | { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, |
| @@ -63,6 +62,7 @@ static const struct hid_blacklist { | |||
| 63 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET }, | 62 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET }, |
| 64 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET }, | 63 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET }, |
| 65 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET }, | 64 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET }, |
| 65 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, | ||
| 66 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, | 66 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, |
| 67 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, | 67 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, |
| 68 | { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, | 68 | { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, |
| @@ -72,6 +72,10 @@ static const struct hid_blacklist { | |||
| 72 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, | 72 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, |
| 73 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, | 73 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, |
| 74 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, | 74 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, |
| 75 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT }, | ||
| 76 | { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, | ||
| 77 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, | ||
| 78 | { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH, HID_QUIRK_MULTI_INPUT }, | ||
| 75 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | 79 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, |
| 76 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, | 80 | { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT }, |
| 77 | 81 | ||
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index dfcb27613ec5..fedd88df9a18 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
| @@ -67,8 +67,6 @@ struct hiddev_list { | |||
| 67 | struct mutex thread_lock; | 67 | struct mutex thread_lock; |
| 68 | }; | 68 | }; |
| 69 | 69 | ||
| 70 | static struct usb_driver hiddev_driver; | ||
| 71 | |||
| 72 | /* | 70 | /* |
| 73 | * Find a report, given the report's type and ID. The ID can be specified | 71 | * Find a report, given the report's type and ID. The ID can be specified |
| 74 | * indirectly by REPORT_ID_FIRST (which returns the first report of the given | 72 | * indirectly by REPORT_ID_FIRST (which returns the first report of the given |
| @@ -926,41 +924,3 @@ void hiddev_disconnect(struct hid_device *hid) | |||
| 926 | kfree(hiddev); | 924 | kfree(hiddev); |
| 927 | } | 925 | } |
| 928 | } | 926 | } |
| 929 | |||
| 930 | /* Currently this driver is a USB driver. It's not a conventional one in | ||
| 931 | * the sense that it doesn't probe at the USB level. Instead it waits to | ||
| 932 | * be connected by HID through the hiddev_connect / hiddev_disconnect | ||
| 933 | * routines. The reason to register as a USB device is to gain part of the | ||
| 934 | * minor number space from the USB major. | ||
| 935 | * | ||
| 936 | * In theory, should the HID code be generalized to more than one physical | ||
| 937 | * medium (say, IEEE 1384), this driver will probably need to register its | ||
| 938 | * own major number, and in doing so, no longer need to register with USB. | ||
| 939 | * At that point the probe routine and hiddev_driver struct below will no | ||
| 940 | * longer be useful. | ||
| 941 | */ | ||
| 942 | |||
| 943 | |||
| 944 | /* We never attach in this manner, and rely on HID to connect us. This | ||
| 945 | * is why there is no disconnect routine defined in the usb_driver either. | ||
| 946 | */ | ||
| 947 | static int hiddev_usbd_probe(struct usb_interface *intf, | ||
| 948 | const struct usb_device_id *hiddev_info) | ||
| 949 | { | ||
| 950 | return -ENODEV; | ||
| 951 | } | ||
| 952 | |||
| 953 | static /* const */ struct usb_driver hiddev_driver = { | ||
| 954 | .name = "hiddev", | ||
| 955 | .probe = hiddev_usbd_probe, | ||
| 956 | }; | ||
| 957 | |||
| 958 | int __init hiddev_init(void) | ||
| 959 | { | ||
| 960 | return usb_register(&hiddev_driver); | ||
| 961 | } | ||
| 962 | |||
| 963 | void hiddev_exit(void) | ||
| 964 | { | ||
| 965 | usb_deregister(&hiddev_driver); | ||
| 966 | } | ||
diff --git a/include/linux/hid.h b/include/linux/hid.h index 42a0f1d11365..bb0f56f5c01e 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -316,6 +316,7 @@ struct hid_item { | |||
| 316 | #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 | 316 | #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 |
| 317 | #define HID_QUIRK_NO_INIT_REPORTS 0x20000000 | 317 | #define HID_QUIRK_NO_INIT_REPORTS 0x20000000 |
| 318 | #define HID_QUIRK_NO_IGNORE 0x40000000 | 318 | #define HID_QUIRK_NO_IGNORE 0x40000000 |
| 319 | #define HID_QUIRK_NO_INPUT_SYNC 0x80000000 | ||
| 319 | 320 | ||
| 320 | /* | 321 | /* |
| 321 | * This is the global environment of the parser. This information is | 322 | * This is the global environment of the parser. This information is |
| @@ -626,8 +627,8 @@ struct hid_driver { | |||
| 626 | int (*event)(struct hid_device *hdev, struct hid_field *field, | 627 | int (*event)(struct hid_device *hdev, struct hid_field *field, |
| 627 | struct hid_usage *usage, __s32 value); | 628 | struct hid_usage *usage, __s32 value); |
| 628 | 629 | ||
| 629 | void (*report_fixup)(struct hid_device *hdev, __u8 *buf, | 630 | __u8 *(*report_fixup)(struct hid_device *hdev, __u8 *buf, |
| 630 | unsigned int size); | 631 | unsigned int *size); |
| 631 | 632 | ||
| 632 | int (*input_mapping)(struct hid_device *hdev, | 633 | int (*input_mapping)(struct hid_device *hdev, |
| 633 | struct hid_input *hidinput, struct hid_field *field, | 634 | struct hid_input *hidinput, struct hid_field *field, |
diff --git a/include/linux/hiddev.h b/include/linux/hiddev.h index bb6f58baf319..a3f481a3063b 100644 --- a/include/linux/hiddev.h +++ b/include/linux/hiddev.h | |||
| @@ -226,8 +226,6 @@ void hiddev_disconnect(struct hid_device *); | |||
| 226 | void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, | 226 | void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, |
| 227 | struct hid_usage *usage, __s32 value); | 227 | struct hid_usage *usage, __s32 value); |
| 228 | void hiddev_report_event(struct hid_device *hid, struct hid_report *report); | 228 | void hiddev_report_event(struct hid_device *hid, struct hid_report *report); |
| 229 | int __init hiddev_init(void); | ||
| 230 | void hiddev_exit(void); | ||
| 231 | #else | 229 | #else |
| 232 | static inline int hiddev_connect(struct hid_device *hid, | 230 | static inline int hiddev_connect(struct hid_device *hid, |
| 233 | unsigned int force) | 231 | unsigned int force) |
| @@ -236,8 +234,6 @@ static inline void hiddev_disconnect(struct hid_device *hid) { } | |||
| 236 | static inline void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, | 234 | static inline void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, |
| 237 | struct hid_usage *usage, __s32 value) { } | 235 | struct hid_usage *usage, __s32 value) { } |
| 238 | static inline void hiddev_report_event(struct hid_device *hid, struct hid_report *report) { } | 236 | static inline void hiddev_report_event(struct hid_device *hid, struct hid_report *report) { } |
| 239 | static inline int hiddev_init(void) { return 0; } | ||
| 240 | static inline void hiddev_exit(void) { } | ||
| 241 | #endif | 237 | #endif |
| 242 | 238 | ||
| 243 | #endif | 239 | #endif |
