Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
feb485d4
Commit
feb485d4
authored
Jul 09, 2007
by
Jiri Kosina
Browse files
Options
Browse Files
Download
Plain Diff
Merge branches 'debug-module-param' and 'upstream' into for-linus
parents
58037eb9
2c1d8aea
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
303 additions
and
92 deletions
+303
-92
drivers/hid/Kconfig
drivers/hid/Kconfig
+6
-3
drivers/hid/hid-input.c
drivers/hid/hid-input.c
+94
-5
drivers/hid/usbhid/hid-core.c
drivers/hid/usbhid/hid-core.c
+10
-63
drivers/hid/usbhid/hid-pidff.c
drivers/hid/usbhid/hid-pidff.c
+1
-0
drivers/hid/usbhid/hid-quirks.c
drivers/hid/usbhid/hid-quirks.c
+169
-8
include/linux/hid.h
include/linux/hid.h
+23
-13
No files found.
drivers/hid/Kconfig
View file @
feb485d4
#
# HID driver configuration
#
menu "HID Devices"
menuconfig HID_SUPPORT
bool "HID Devices"
depends on INPUT
default y
if HID_SUPPORT
config HID
tristate "Generic HID support"
...
...
@@ -39,5 +43,4 @@ config HID_DEBUG
source "drivers/hid/usbhid/Kconfig"
endmenu
endif # HID_SUPPORT
drivers/hid/hid-input.c
View file @
feb485d4
...
...
@@ -60,6 +60,19 @@ static const unsigned char hid_keyboard[256] = {
150
,
158
,
159
,
128
,
136
,
177
,
178
,
176
,
142
,
152
,
173
,
140
,
unk
,
unk
,
unk
,
unk
};
/* extended mapping for certain Logitech hardware (Logitech cordless desktop LX500) */
#define LOGITECH_EXPANDED_KEYMAP_SIZE 80
static
int
logitech_expanded_keymap
[
LOGITECH_EXPANDED_KEYMAP_SIZE
]
=
{
0
,
216
,
0
,
213
,
175
,
156
,
0
,
0
,
0
,
0
,
144
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
212
,
174
,
167
,
152
,
161
,
112
,
0
,
0
,
0
,
154
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
183
,
184
,
185
,
186
,
187
,
188
,
189
,
190
,
191
,
192
,
193
,
194
,
0
,
0
,
0
};
static
const
struct
{
__s32
x
;
__s32
y
;
...
...
@@ -374,6 +387,21 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
}
/* Special handling for Logitech Cordless Desktop */
if
(
field
->
application
!=
HID_GD_MOUSE
)
{
if
(
device
->
quirks
&
HID_QUIRK_LOGITECH_EXPANDED_KEYMAP
)
{
int
hid
=
usage
->
hid
&
HID_USAGE
;
if
(
hid
<
LOGITECH_EXPANDED_KEYMAP_SIZE
&&
logitech_expanded_keymap
[
hid
]
!=
0
)
code
=
logitech_expanded_keymap
[
hid
];
}
}
else
{
if
(
device
->
quirks
&
HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL
)
{
int
hid
=
usage
->
hid
&
HID_USAGE
;
if
(
hid
==
7
||
hid
==
8
)
goto
ignore
;
}
}
map_key
(
code
);
break
;
...
...
@@ -562,6 +590,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case
0x0e5
:
map_key_clear
(
KEY_BASSBOOST
);
break
;
case
0x0e9
:
map_key_clear
(
KEY_VOLUMEUP
);
break
;
case
0x0ea
:
map_key_clear
(
KEY_VOLUMEDOWN
);
break
;
/* reserved in HUT 1.12. Reported on Petalynx remote */
case
0x0f6
:
map_key_clear
(
KEY_NEXT
);
break
;
case
0x0fa
:
map_key_clear
(
KEY_BACK
);
break
;
case
0x183
:
map_key_clear
(
KEY_CONFIG
);
break
;
case
0x184
:
map_key_clear
(
KEY_WORDPROCESSOR
);
break
;
case
0x185
:
map_key_clear
(
KEY_EDITOR
);
break
;
...
...
@@ -594,7 +627,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case
0x21b
:
map_key_clear
(
KEY_COPY
);
break
;
case
0x21c
:
map_key_clear
(
KEY_CUT
);
break
;
case
0x21d
:
map_key_clear
(
KEY_PASTE
);
break
;
case
0x221
:
map_key_clear
(
KEY_FIND
);
break
;
case
0x21f
:
map_key_clear
(
KEY_FIND
);
break
;
case
0x221
:
map_key_clear
(
KEY_SEARCH
);
break
;
case
0x222
:
map_key_clear
(
KEY_GOTO
);
break
;
case
0x223
:
map_key_clear
(
KEY_HOMEPAGE
);
break
;
case
0x224
:
map_key_clear
(
KEY_BACK
);
break
;
case
0x225
:
map_key_clear
(
KEY_FORWARD
);
break
;
...
...
@@ -684,7 +719,28 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
break
;
case
HID_UP_MSVENDOR
:
/* special case - Chicony Chicony KU-0418 tactical pad */
if
(
device
->
vendor
==
0x04f2
&&
device
->
product
==
0x0418
)
{
set_bit
(
EV_REP
,
input
->
evbit
);
switch
(
usage
->
hid
&
HID_USAGE
)
{
case
0xff01
:
map_key_clear
(
BTN_1
);
break
;
case
0xff02
:
map_key_clear
(
BTN_2
);
break
;
case
0xff03
:
map_key_clear
(
BTN_3
);
break
;
case
0xff04
:
map_key_clear
(
BTN_4
);
break
;
case
0xff05
:
map_key_clear
(
BTN_5
);
break
;
case
0xff06
:
map_key_clear
(
BTN_6
);
break
;
case
0xff07
:
map_key_clear
(
BTN_7
);
break
;
case
0xff08
:
map_key_clear
(
BTN_8
);
break
;
case
0xff09
:
map_key_clear
(
BTN_9
);
break
;
case
0xff0a
:
map_key_clear
(
BTN_A
);
break
;
case
0xff0b
:
map_key_clear
(
BTN_B
);
break
;
default:
goto
ignore
;
}
}
else
{
goto
ignore
;
}
break
;
case
HID_UP_CUSTOM
:
/* Reported on Logitech and Powerbook USB keyboards */
...
...
@@ -700,10 +756,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
}
break
;
case
HID_UP_LOGIVENDOR
:
/* Reported on Logitech Ultra X Media Remote */
case
HID_UP_LOGIVENDOR
:
set_bit
(
EV_REP
,
input
->
evbit
);
switch
(
usage
->
hid
&
HID_USAGE
)
{
/* Reported on Logitech Ultra X Media Remote */
case
0x004
:
map_key_clear
(
KEY_AGAIN
);
break
;
case
0x00d
:
map_key_clear
(
KEY_HOME
);
break
;
case
0x024
:
map_key_clear
(
KEY_SHUFFLE
);
break
;
...
...
@@ -721,6 +777,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
case
0x04d
:
map_key_clear
(
KEY_SUBTITLE
);
break
;
case
0x051
:
map_key_clear
(
KEY_RED
);
break
;
case
0x052
:
map_key_clear
(
KEY_CLOSE
);
break
;
/* Reported on Petalynx Maxter remote */
case
0x05a
:
map_key_clear
(
KEY_TEXT
);
break
;
case
0x05b
:
map_key_clear
(
KEY_RED
);
break
;
case
0x05c
:
map_key_clear
(
KEY_GREEN
);
break
;
case
0x05d
:
map_key_clear
(
KEY_YELLOW
);
break
;
case
0x05e
:
map_key_clear
(
KEY_BLUE
);
break
;
default:
goto
ignore
;
}
break
;
...
...
@@ -814,6 +878,16 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
field
->
dpad
=
usage
->
code
;
}
/* for those devices which produce Consumer volume usage as relative,
* we emulate pressing volumeup/volumedown appropriate number of times
* in hidinput_hid_event()
*/
if
((
usage
->
type
==
EV_ABS
)
&&
(
field
->
flags
&
HID_MAIN_ITEM_RELATIVE
)
&&
(
usage
->
code
==
ABS_VOLUME
))
{
set_bit
(
KEY_VOLUMEUP
,
input
->
keybit
);
set_bit
(
KEY_VOLUMEDOWN
,
input
->
keybit
);
}
hid_resolv_event
(
usage
->
type
,
usage
->
code
);
dbg_hid_line
(
"
\n
"
);
...
...
@@ -902,6 +976,21 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
if
((
usage
->
type
==
EV_KEY
)
&&
(
usage
->
code
==
0
))
/* Key 0 is "unassigned", not KEY_UNKNOWN */
return
;
if
((
usage
->
type
==
EV_ABS
)
&&
(
field
->
flags
&
HID_MAIN_ITEM_RELATIVE
)
&&
(
usage
->
code
==
ABS_VOLUME
))
{
int
count
=
abs
(
value
);
int
direction
=
value
>
0
?
KEY_VOLUMEUP
:
KEY_VOLUMEDOWN
;
int
i
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
input_event
(
input
,
EV_KEY
,
direction
,
1
);
input_sync
(
input
);
input_event
(
input
,
EV_KEY
,
direction
,
0
);
input_sync
(
input
);
}
return
;
}
input_event
(
input
,
usage
->
type
,
usage
->
code
,
value
);
if
((
field
->
flags
&
HID_MAIN_ITEM_RELATIVE
)
&&
(
usage
->
type
==
EV_KEY
))
...
...
@@ -970,7 +1059,7 @@ int hidinput_connect(struct hid_device *hid)
if
(
IS_INPUT_APPLICATION
(
hid
->
collection
[
i
].
usage
))
break
;
if
(
i
==
hid
->
maxcollection
)
if
(
i
==
hid
->
maxcollection
&&
(
hid
->
quirks
&
HID_QUIRK_HIDINPUT
)
==
0
)
return
-
1
;
if
(
hid
->
quirks
&
HID_QUIRK_SKIP_OUTPUT_REPORTS
)
...
...
drivers/hid/usbhid/hid-core.c
View file @
feb485d4
...
...
@@ -60,6 +60,12 @@ MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
" quirks=vendorID:productID:quirks"
" where vendorID, productID, and quirks are all in"
" 0x-prefixed hex"
);
static
char
*
rdesc_quirks_param
[
MAX_USBHID_BOOT_QUIRKS
]
=
{
[
0
...
(
MAX_USBHID_BOOT_QUIRKS
-
1
)
]
=
NULL
};
module_param_array_named
(
rdesc_quirks
,
rdesc_quirks_param
,
charp
,
NULL
,
0444
);
MODULE_PARM_DESC
(
rdesc_quirks
,
"Add/modify report descriptor quirks by specifying "
" rdesc_quirks=vendorID:productID:rdesc_quirks"
" where vendorID, productID, and rdesc_quirks are all in"
" 0x-prefixed hex"
);
/*
* Input submission and I/O error handler.
*/
...
...
@@ -632,20 +638,6 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
usb_buffer_free
(
dev
,
usbhid
->
bufsize
,
usbhid
->
ctrlbuf
,
usbhid
->
ctrlbuf_dma
);
}
/*
* Cherry Cymotion keyboard have an invalid HID report descriptor,
* that needs fixing before we can parse it.
*/
static
void
hid_fixup_cymotion_descriptor
(
char
*
rdesc
,
int
rsize
)
{
if
(
rsize
>=
17
&&
rdesc
[
11
]
==
0x3c
&&
rdesc
[
12
]
==
0x02
)
{
info
(
"Fixing up Cherry Cymotion report descriptor"
);
rdesc
[
11
]
=
rdesc
[
16
]
=
0xff
;
rdesc
[
12
]
=
rdesc
[
17
]
=
0x03
;
}
}
/*
* Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
* to "operational". Without this, the ps3 controller will not report any
...
...
@@ -672,46 +664,6 @@ static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
kfree
(
buf
);
}
/*
* Certain Logitech keyboards send in report #3 keys which are far
* above the logical maximum described in descriptor. This extends
* the original value of 0x28c of logical maximum to 0x104d
*/
static
void
hid_fixup_logitech_descriptor
(
unsigned
char
*
rdesc
,
int
rsize
)
{
if
(
rsize
>=
90
&&
rdesc
[
83
]
==
0x26
&&
rdesc
[
84
]
==
0x8c
&&
rdesc
[
85
]
==
0x02
)
{
info
(
"Fixing up Logitech keyboard report descriptor"
);
rdesc
[
84
]
=
rdesc
[
89
]
=
0x4d
;
rdesc
[
85
]
=
rdesc
[
90
]
=
0x10
;
}
}
/*
* Some USB barcode readers from cypress have usage min and usage max in
* the wrong order
*/
static
void
hid_fixup_cypress_descriptor
(
unsigned
char
*
rdesc
,
int
rsize
)
{
short
fixed
=
0
;
int
i
;
for
(
i
=
0
;
i
<
rsize
-
4
;
i
++
)
{
if
(
rdesc
[
i
]
==
0x29
&&
rdesc
[
i
+
2
]
==
0x19
)
{
unsigned
char
tmp
;
rdesc
[
i
]
=
0x19
;
rdesc
[
i
+
2
]
=
0x29
;
tmp
=
rdesc
[
i
+
3
];
rdesc
[
i
+
3
]
=
rdesc
[
i
+
1
];
rdesc
[
i
+
1
]
=
tmp
;
}
}
if
(
fixed
)
info
(
"Fixing up Cypress report descriptor"
);
}
static
struct
hid_device
*
usb_hid_configure
(
struct
usb_interface
*
intf
)
{
struct
usb_host_interface
*
interface
=
intf
->
cur_altsetting
;
...
...
@@ -772,14 +724,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
return
NULL
;
}
if
((
quirks
&
HID_QUIRK_CYMOTION
))
hid_fixup_cymotion_descriptor
(
rdesc
,
rsize
);
if
(
quirks
&
HID_QUIRK_LOGITECH_DESCRIPTOR
)
hid_fixup_logitech_descriptor
(
rdesc
,
rsize
);
if
(
quirks
&
HID_QUIRK_SWAPPED_MIN_MAX
)
hid_fixup_cypress_descriptor
(
rdesc
,
rsize
);
usbhid_fixup_report_descriptor
(
le16_to_cpu
(
dev
->
descriptor
.
idVendor
),
le16_to_cpu
(
dev
->
descriptor
.
idProduct
),
rdesc
,
rsize
,
rdesc_quirks_param
);
dbg_hid
(
"report descriptor (size %u, read %d) = "
,
rsize
,
n
);
for
(
n
=
0
;
n
<
rsize
;
n
++
)
...
...
@@ -954,7 +901,7 @@ static void hid_disconnect(struct usb_interface *intf)
usb_kill_urb
(
usbhid
->
urbctrl
);
del_timer_sync
(
&
usbhid
->
io_retry
);
flush_scheduled_work
(
);
cancel_work_sync
(
&
usbhid
->
reset_work
);
if
(
hid
->
claimed
&
HID_CLAIMED_INPUT
)
hidinput_disconnect
(
hid
);
...
...
drivers/hid/usbhid/hid-pidff.c
View file @
feb485d4
...
...
@@ -738,6 +738,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
pidff
->
set_effect
[
PID_TRIGGER_BUTTON
].
value
[
0
]
=
0
;
pidff
->
set_effect
[
PID_TRIGGER_REPEAT_INT
].
value
[
0
]
=
0
;
pidff_set
(
&
pidff
->
set_effect
[
PID_GAIN
],
magnitude
);
pidff
->
set_effect
[
PID_DIRECTION_ENABLE
].
value
[
0
]
=
1
;
pidff
->
set_effect
[
PID_START_DELAY
].
value
[
0
]
=
0
;
usbhid_submit_report
(
pidff
->
hid
,
pidff
->
reports
[
PID_SET_EFFECT
],
...
...
drivers/hid/usbhid/hid-quirks.c
View file @
feb485d4
...
...
@@ -105,6 +105,9 @@
#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f
#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
#define USB_VENDOR_ID_GAMERON 0x0810
#define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001
#define USB_VENDOR_ID_GLAB 0x06c2
#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
...
...
@@ -196,8 +199,10 @@
#define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
#define USB_DEVICE_ID_LOGITECH_KBD 0xc311
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
#define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500 0xc512
#define USB_DEVICE_ID_MX3000_RECEIVER 0xc513
#define USB_DEVICE_ID_DINOVO_EDGE 0xc714
...
...
@@ -209,6 +214,13 @@
#define USB_DEVICE_ID_MGE_UPS 0xffff
#define USB_DEVICE_ID_MGE_UPS1 0x0001
#define USB_VENDOR_ID_MICROSOFT 0x045e
#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
#define USB_VENDOR_ID_NCR 0x0404
#define USB_DEVICE_ID_NCR_FIRST 0x0300
#define USB_DEVICE_ID_NCR_LAST 0x03ff
#define USB_VENDOR_ID_NEC 0x073e
#define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
...
...
@@ -220,6 +232,9 @@
#define USB_VENDOR_ID_PANTHERLORD 0x0810
#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001
#define USB_VENDOR_ID_PETALYNX 0x18b1
#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
...
...
@@ -278,6 +293,7 @@ static const struct hid_blacklist {
{
USB_VENDOR_ID_AASHIMA
,
USB_DEVICE_ID_AASHIMA_PREDATOR
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_ALPS
,
USB_DEVICE_ID_IBM_GAMEPAD
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_CHIC
,
USB_DEVICE_ID_CHIC_GAMEPAD
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_GAMERON
,
USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR
,
HID_QUIRK_MULTI_INPUT
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_DRIVING
,
HID_QUIRK_BADPAD
|
HID_QUIRK_MULTI_INPUT
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_FLYING
,
HID_QUIRK_BADPAD
|
HID_QUIRK_MULTI_INPUT
},
{
USB_VENDOR_ID_HAPP
,
USB_DEVICE_ID_UGCI_FIGHTING
,
HID_QUIRK_BADPAD
|
HID_QUIRK_MULTI_INPUT
},
...
...
@@ -285,11 +301,10 @@ static const struct hid_blacklist {
{
USB_VENDOR_ID_SAITEK
,
USB_DEVICE_ID_SAITEK_RUMBLEPAD
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_TOPMAX
,
USB_DEVICE_ID_TOPMAX_COBRAPAD
,
HID_QUIRK_BADPAD
},
{
USB_VENDOR_ID_CHERRY
,
USB_DEVICE_ID_CHERRY_CYMOTION
,
HID_QUIRK_CYMOTION
},
{
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_DINOVO_EDGE
,
HID_QUIRK_DUPLICATE_USAGES
},
{
USB_VENDOR_ID_BELKIN
,
USB_DEVICE_ID_FLIP_KVM
,
HID_QUIRK_HIDDEV
},
{
USB_VENDOR_ID_MICROSOFT
,
USB_DEVICE_ID_SIDEWINDER_GV
,
HID_QUIRK_HIDINPUT
},
{
USB_VENDOR_ID_AIPTEK
,
USB_DEVICE_ID_AIPTEK_01
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_AIPTEK
,
USB_DEVICE_ID_AIPTEK_10
,
HID_QUIRK_IGNORE
},
...
...
@@ -409,9 +424,7 @@ static const struct hid_blacklist {
{
USB_VENDOR_ID_ACECAD
,
USB_DEVICE_ID_ACECAD_FLAIR
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_ACECAD
,
USB_DEVICE_ID_ACECAD_302
,
HID_QUIRK_IGNORE
},
{
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_MX3000_RECEIVER
,
HID_QUIRK_LOGITECH_DESCRIPTOR
},
{
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_S510_RECEIVER
,
HID_QUIRK_LOGITECH_DESCRIPTOR
},
{
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_S510_RECEIVER_2
,
HID_QUIRK_LOGITECH_DESCRIPTOR
},
{
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500
,
HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL
|
HID_QUIRK_LOGITECH_EXPANDED_KEYMAP
},
{
USB_VENDOR_ID_APPLE
,
USB_DEVICE_ID_APPLE_MIGHTYMOUSE
,
HID_QUIRK_MIGHTYMOUSE
|
HID_QUIRK_INVERT_HWHEEL
},
...
...
@@ -426,6 +439,7 @@ static const struct hid_blacklist {
{
USB_VENDOR_ID_ATEN
,
USB_DEVICE_ID_ATEN_4PORTKVM
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_ATEN
,
USB_DEVICE_ID_ATEN_4PORTKVMC
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_LOGITECH_WHEEL
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_PETALYNX
,
USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_SUN
,
USB_DEVICE_ID_RARITAN_KVM_DONGLE
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_TURBOX
,
USB_DEVICE_ID_TURBOX_KEYBOARD
,
HID_QUIRK_NOGET
},
{
USB_VENDOR_ID_WISEGROUP
,
USB_DEVICE_ID_DUAL_USB_JOYPAD
,
HID_QUIRK_NOGET
|
HID_QUIRK_MULTI_INPUT
},
...
...
@@ -448,9 +462,28 @@ static const struct hid_blacklist {
{
USB_VENDOR_ID_APPLE
,
USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY
,
HID_QUIRK_POWERBOOK_HAS_FN
|
HID_QUIRK_IGNORE_MOUSE
},
{
USB_VENDOR_ID_DELL
,
USB_DEVICE_ID_DELL_W7658
,
HID_QUIRK_RESET_LEDS
},
{
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_LOGITECH_KBD
,
HID_QUIRK_RESET_LEDS
},
{
0
,
0
}
};
/* Quirks for devices which require report descriptor fixup go here */
static
const
struct
hid_rdesc_blacklist
{
__u16
idVendor
;
__u16
idProduct
;
__u32
quirks
;
}
hid_rdesc_blacklist
[]
=
{
{
USB_VENDOR_ID_CHERRY
,
USB_DEVICE_ID_CHERRY_CYMOTION
,
HID_QUIRK_RDESC_CYMOTION
},
{
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_MX3000_RECEIVER
,
HID_QUIRK_RDESC_LOGITECH
},
{
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_S510_RECEIVER
,
HID_QUIRK_RDESC_LOGITECH
},
{
USB_VENDOR_ID_LOGITECH
,
USB_DEVICE_ID_S510_RECEIVER_2
,
HID_QUIRK_RDESC_LOGITECH
},
{
USB_VENDOR_ID_CYPRESS
,
USB_DEVICE_ID_CYPRESS_BARCODE_1
,
HID_QUIRK_SWAPPED_MIN_MAX
},
{
USB_VENDOR_ID_CYPRESS
,
USB_DEVICE_ID_CYPRESS_BARCODE_2
,
HID_QUIRK_SWAPPED_MIN_MAX
},
{
USB_VENDOR_ID_PETALYNX
,
USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE
,
HID_QUIRK_RDESC_PETALYNX
},
{
USB_VENDOR_ID_CYPRESS
,
USB_DEVICE_ID_CYPRESS_BARCODE_1
,
HID_QUIRK_RDESC_SWAPPED_MIN_MAX
},
{
USB_VENDOR_ID_CYPRESS
,
USB_DEVICE_ID_CYPRESS_BARCODE_2
,
HID_QUIRK_RDESC_SWAPPED_MIN_MAX
},
{
0
,
0
}
};
...
...
@@ -559,7 +592,6 @@ int usbhid_modify_dquirk(const u16 idVendor, const u16 idProduct,
return
0
;
}
/**
* usbhid_remove_all_dquirks: remove all runtime HID quirks from memory
*
...
...
@@ -675,6 +707,12 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
idProduct
<=
USB_DEVICE_ID_CODEMERCS_IOW_LAST
)
return
HID_QUIRK_IGNORE
;
/* NCR devices must not be queried for reports */
if
(
idVendor
==
USB_VENDOR_ID_NCR
&&
idProduct
>=
USB_DEVICE_ID_NCR_FIRST
&&
idProduct
<=
USB_DEVICE_ID_NCR_LAST
)
return
HID_QUIRK_NOGET
;
down_read
(
&
dquirks_rwsem
);
bl_entry
=
usbhid_exists_dquirk
(
idVendor
,
idProduct
);
if
(
!
bl_entry
)
...
...
@@ -686,3 +724,126 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
return
quirks
;
}
/*
* Cherry Cymotion keyboard have an invalid HID report descriptor,
* that needs fixing before we can parse it.
*/
static
void
usbhid_fixup_cymotion_descriptor
(
char
*
rdesc
,
int
rsize
)
{
if
(
rsize
>=
17
&&
rdesc
[
11
]
==
0x3c
&&
rdesc
[
12
]
==
0x02
)
{
printk
(
KERN_INFO
"Fixing up Cherry Cymotion report descriptor
\n
"
);
rdesc
[
11
]
=
rdesc
[
16
]
=
0xff
;
rdesc
[
12
]
=
rdesc
[
17
]
=
0x03
;
}
}
/*
* Certain Logitech keyboards send in report #3 keys which are far
* above the logical maximum described in descriptor. This extends
* the original value of 0x28c of logical maximum to 0x104d
*/
static
void
usbhid_fixup_logitech_descriptor
(
unsigned
char
*
rdesc
,
int
rsize
)
{
if
(
rsize
>=
90
&&
rdesc
[
83
]
==
0x26
&&
rdesc
[
84
]
==
0x8c
&&
rdesc
[
85
]
==
0x02
)
{
printk
(
KERN_INFO
"Fixing up Logitech keyboard report descriptor
\n
"
);
rdesc
[
84
]
=
rdesc
[
89
]
=
0x4d
;
rdesc
[
85
]
=
rdesc
[
90
]
=
0x10
;
}
}
/* Petalynx Maxter Remote has maximum for consumer page set too low */
static
void
usbhid_fixup_petalynx_descriptor
(
unsigned
char
*
rdesc
,
int
rsize
)
{
if
(
rsize
>=
60
&&
rdesc
[
39
]
==
0x2a
&&
rdesc
[
40
]
==
0xf5
&&
rdesc
[
41
]
==
0x00
&&
rdesc
[
59
]
==
0x26
&&
rdesc
[
60
]
==
0xf9
&&
rdesc
[
61
]
==
0x00
)
{
printk
(
KERN_INFO
"Fixing up Petalynx Maxter Remote report descriptor
\n
"
);
rdesc
[
60
]
=
0xfa
;
rdesc
[
40
]
=
0xfa
;
}
}
/*
* Some USB barcode readers from cypress have usage min and usage max in
* the wrong order
*/
static
void
usbhid_fixup_cypress_descriptor
(
unsigned
char
*
rdesc
,
int
rsize
)
{
short
fixed
=
0
;
int
i
;
for
(
i
=
0
;
i
<
rsize
-
4
;
i
++
)
{
if
(
rdesc
[
i
]
==
0x29
&&
rdesc
[
i
+
2
]
==
0x19
)
{
unsigned
char
tmp
;
rdesc
[
i
]
=
0x19
;
rdesc
[
i
+
2
]
=
0x29
;
tmp
=
rdesc
[
i
+
3
];
rdesc
[
i
+
3
]
=
rdesc
[
i
+
1
];
rdesc
[
i
+
1
]
=
tmp
;
}
}
if
(
fixed
)
printk
(
KERN_INFO
"Fixing up Cypress report descriptor
\n
"
);
}
static
void
__usbhid_fixup_report_descriptor
(
__u32
quirks
,
char
*
rdesc
,
unsigned
rsize
)
{
if
((
quirks
&
HID_QUIRK_RDESC_CYMOTION
))
usbhid_fixup_cymotion_descriptor
(
rdesc
,
rsize
);
if
(
quirks
&
HID_QUIRK_RDESC_LOGITECH
)
usbhid_fixup_logitech_descriptor
(
rdesc
,
rsize
);
if
(
quirks
&
HID_QUIRK_RDESC_SWAPPED_MIN_MAX
)
usbhid_fixup_cypress_descriptor
(
rdesc
,
rsize
);
if
(
quirks
&
HID_QUIRK_RDESC_PETALYNX
)
usbhid_fixup_petalynx_descriptor
(
rdesc
,
rsize
);
}
/**
* usbhid_fixup_report_descriptor: check if report descriptor needs fixup
*
* Description:
* Walks the hid_rdesc_blacklist[] array and checks whether the device
* is known to have broken report descriptor that needs to be fixed up
* prior to entering the HID parser
*
* Returns: nothing
*/
void
usbhid_fixup_report_descriptor
(
const
u16
idVendor
,
const
u16
idProduct
,
char
*
rdesc
,
unsigned
rsize
,
char
**
quirks_param
)
{
int
n
,
m
;
u16
paramVendor
,
paramProduct
;
u32
quirks
;
/* static rdesc quirk entries */
for
(
n
=
0
;
hid_rdesc_blacklist
[
n
].
idVendor
;
n
++
)
if
(
hid_rdesc_blacklist
[
n
].
idVendor
==
idVendor
&&
hid_rdesc_blacklist
[
n
].
idProduct
==
idProduct
)
__usbhid_fixup_report_descriptor
(
hid_rdesc_blacklist
[
n
].
quirks
,
rdesc
,
rsize
);
/* runtime rdesc quirk entries handling */
for
(
n
=
0
;
quirks_param
[
n
]
&&
n
<
MAX_USBHID_BOOT_QUIRKS
;
n
++
)
{
m
=
sscanf
(
quirks_param
[
n
],
"0x%hx:0x%hx:0x%x"
,
&
paramVendor
,
&
paramProduct
,
&
quirks
);
if
(
m
!=
3
)
printk
(
KERN_WARNING
"Could not parse HID quirk module param %s
\n
"
,
quirks_param
[
n
]);
else
if
(
paramVendor
==
idVendor
&&
paramProduct
==
idProduct
)
__usbhid_fixup_report_descriptor
(
quirks
,
rdesc
,
rsize
);
}
}
include/linux/hid.h
View file @
feb485d4
...
...
@@ -263,19 +263,28 @@ struct hid_item {
#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
#define HID_QUIRK_MIGHTYMOUSE 0x00000400
#define HID_QUIRK_CYMOTION 0x00000800
#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000
#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000
#define HID_QUIRK_INVERT_HWHEEL 0x00004000
#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000
#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00010000
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00020000
#define HID_QUIRK_IGNORE_MOUSE 0x00040000
#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000
#define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000
#define HID_QUIRK_DUPLICATE_USAGES 0x00200000
#define HID_QUIRK_RESET_LEDS 0x00400000
#define HID_QUIRK_SWAPPED_MIN_MAX 0x00800000
#define HID_QUIRK_POWERBOOK_HAS_FN 0x00000800
#define HID_QUIRK_POWERBOOK_FN_ON 0x00001000
#define HID_QUIRK_INVERT_HWHEEL 0x00002000
#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00004000
#define HID_QUIRK_BAD_RELATIVE_KEYS 0x00008000
#define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000
#define HID_QUIRK_IGNORE_MOUSE 0x00020000
#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00040000
#define HID_QUIRK_DUPLICATE_USAGES 0x00080000
#define HID_QUIRK_RESET_LEDS 0x00100000
#define HID_QUIRK_HIDINPUT 0x00200000
#define HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL 0x00400000
#define HID_QUIRK_LOGITECH_EXPANDED_KEYMAP 0x00800000
/*
* Separate quirks for runtime report descriptor fixup
*/
#define HID_QUIRK_RDESC_CYMOTION 0x00000001
#define HID_QUIRK_RDESC_LOGITECH 0x00000002
#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX 0x00000004
#define HID_QUIRK_RDESC_PETALYNX 0x00000008
/*
* This is the global environment of the parser. This information is
...
...
@@ -511,6 +520,7 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct);
int
usbhid_modify_dquirk
(
const
u16
idVendor
,
const
u16
idProduct
,
const
u32
quirks
);
int
usbhid_quirks_init
(
char
**
quirks_param
);
void
usbhid_quirks_exit
(
void
);
void
usbhid_fixup_report_descriptor
(
const
u16
,
const
u16
,
char
*
,
unsigned
,
char
**
);
#ifdef CONFIG_HID_FF
int
hid_ff_init
(
struct
hid_device
*
hid
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment