Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
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
Hide 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
:
goto
ignore
;
/* 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
},
{
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
},
{
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_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