aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPete Zaitcev <zaitcev@redhat.com>2007-04-06 08:33:18 -0400
committerJiri Kosina <jkosina@suse.cz>2007-04-11 04:36:03 -0400
commit713c8aad6b7202671ce1ac6109f6b48d8223e938 (patch)
tree71409ad76728573d34d07aaf0d528df7d4ae5065
parent85cbea3952135ecad4b47cb6cc57e25279129e2d (diff)
USB HID: numlock quirk for dell W7658 keyboard
On Dell W7658 keyboard, when BIOS sets NumLock LED on, it survives the takeover by kernel and thus confuses users. Eating of an increasibly scarce quirk bit is unfortunate. We do it for safety, given the history of nervous input devices which crash if anything unusual happens. Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/usbhid/hid-core.c45
-rw-r--r--include/linux/hid.h1
2 files changed, 46 insertions, 0 deletions
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 762cb35e769b..cec3bffa0a9a 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -129,6 +129,9 @@ MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
129#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500 129#define USB_DEVICE_ID_CYPRESS_HIDCOM 0x5500
130#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417 130#define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE 0x7417
131 131
132#define USB_VENDOR_ID_DELL 0x413c
133#define USB_DEVICE_ID_DELL_W7658 0x2005
134
132#define USB_VENDOR_ID_DELORME 0x1163 135#define USB_VENDOR_ID_DELORME 0x1163
133#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 136#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
134#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200 137#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
@@ -469,6 +472,8 @@ static const struct hid_blacklist {
469 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, 472 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
470 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, 473 { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
471 474
475 { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
476
472 { 0, 0 } 477 { 0, 0 }
473}; 478};
474 479
@@ -964,6 +969,44 @@ void usbhid_init_reports(struct hid_device *hid)
964} 969}
965 970
966/* 971/*
972 * Reset LEDs which BIOS might have left on. For now, just NumLock (0x01).
973 */
974static int hid_find_field_early(struct hid_device *hid, unsigned int page,
975 unsigned int hid_code, struct hid_field **pfield)
976{
977 struct hid_report *report;
978 struct hid_field *field;
979 struct hid_usage *usage;
980 int i, j;
981
982 list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) {
983 for (i = 0; i < report->maxfield; i++) {
984 field = report->field[i];
985 for (j = 0; j < field->maxusage; j++) {
986 usage = &field->usage[j];
987 if ((usage->hid & HID_USAGE_PAGE) == page &&
988 (usage->hid & 0xFFFF) == hid_code) {
989 *pfield = field;
990 return j;
991 }
992 }
993 }
994 }
995 return -1;
996}
997
998static void usbhid_set_leds(struct hid_device *hid)
999{
1000 struct hid_field *field;
1001 int offset;
1002
1003 if ((offset = hid_find_field_early(hid, HID_UP_LED, 0x01, &field)) != -1) {
1004 hid_set_field(field, offset, 0);
1005 usbhid_submit_report(hid, field->report, USB_DIR_OUT);
1006 }
1007}
1008
1009/*
967 * Traverse the supplied list of reports and find the longest 1010 * Traverse the supplied list of reports and find the longest
968 */ 1011 */
969static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max) 1012static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *max)
@@ -1348,6 +1391,8 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
1348 1391
1349 usbhid_init_reports(hid); 1392 usbhid_init_reports(hid);
1350 hid_dump_device(hid); 1393 hid_dump_device(hid);
1394 if (hid->quirks & HID_QUIRK_RESET_LEDS)
1395 usbhid_set_leds(hid);
1351 1396
1352 if (!hidinput_connect(hid)) 1397 if (!hidinput_connect(hid))
1353 hid->claimed |= HID_CLAIMED_INPUT; 1398 hid->claimed |= HID_CLAIMED_INPUT;
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 55184415fd6b..d73b24b1e265 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -269,6 +269,7 @@ struct hid_item {
269#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000 269#define HID_QUIRK_SONY_PS3_CONTROLLER 0x00080000
270#define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000 270#define HID_QUIRK_LOGITECH_DESCRIPTOR 0x00100000
271#define HID_QUIRK_DUPLICATE_USAGES 0x00200000 271#define HID_QUIRK_DUPLICATE_USAGES 0x00200000
272#define HID_QUIRK_RESET_LEDS 0x00400000
272 273
273/* 274/*
274 * This is the global environment of the parser. This information is 275 * This is the global environment of the parser. This information is