Robert Schedel
2007-12-22 13:15:12 UTC
From: Robert Schedel <***@yahoo.de>
Samsung USB remotes (0419:0001) are rejected by kernel
2.6.23, because the report descriptor from the remote
contains a 48 bit HID report field. HID 1.11 states:
Fields may span at most 4 bytes.
This patch, based on 2.6.23, fixes this by modifying
the internal report descriptor in hid-quirks.c.
Additional user space support (e.g. LIRC) is required
to fetch the information from the hiddev interface.
Signed-off-by: Robert Schedel <***@yahoo.de>
---
drivers/hid/usbhid/hid-quirks.c | 38
++++++++++++++++++++++++++++++++++++++
include/linux/hid.h | 1 +
2 files changed, 39 insertions(+)
On vanilla kernel 2.6.23 the USB remote bundled with
Satelco EasyWatch DVBs
(idVendor/Product 0419:0001 "Samsung IrDA", device
name "Cypress USB Mouse") does not work correctly. On
plugin the kernel rejects the device immediately, see
trace below:
drivers/hid/usbhid/hid-core.c: HID probe called for
ifnum 0
drivers/hid/usbhid/hid-core.c: report descriptor (size
184, read 184) = 05 01 09 06 a1 01 85 01 05 07 19 e0
29 e7 15 00 25 01 95 08 75 01 81 02 95 01 75 08 81 01
95 05 75 01 05 08 19 01 29 05 91 02 95 01 75 03 91 01
95 05 75 08 15 00 25 65 05 07 19 00 29 65 81 00 c0 05
01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 03 15
00 25 01 95 03 75 01 81 02 95 01 75 05 81 01 05 01 09
30 09 31 09 38 15 81 25 7f 75 08 95 03 81 06 c0 c0 05
01 09 80 a1 01 85 03 05 01 19 81 29 88 15 00 25 01 95
08 75 01 81 02 c0 06 cc ff 09 88 a1 01 85 04 09 01 09
02 09 03 09 04 09 05 09 06 09 07 09 08 09 09 09 0a 15
00 25 40 75 30 95 01 81 40 c0
drivers/hid/hid-core.c: invalid report_size 48
drivers/hid/hid-core.c: item 0 1 1 7 parsing failed
drivers/hid/usbhid/hid-core.c: parsing report
descriptor failed
I have also attached the decoded "lsusb" output for
this device. As it shows, the proprietary usage page
(used for indicating most keys) indicates a single 48
bit array field. In my understanding of HID 1.11,
section "Report Constraints", fields may not span more
than 4 bytes, so it sounds like a device quirk rather
than a kernel deficiency.
The patch introduces a workaround to the quirk by
fixing up the report descriptor in hid-quirks.c.
Some side notes:
- As the device also has output applications (which
are unused by the remote though), an hiddev interface
is already created. So the flag "HID_QUIRK_HIDDEV" is
not set in the patch.
- Note, the new "hidraw" from 2.6.24 also will not
solve the issue because the device is rejected either
before hidraw has a chance to access the device.
- A LIRC patch to fetch all keys from the hiddev
interface has been posted to the LIRC developer list.
- I am aware that the merge window for 2.6.24 is
closed, so please consider whether this can be
included in later kernels or provide feedback
meanwhile.
Regards,
Robert Schedel
diff -uprN
linux-2.6.23-orig/drivers/hid/usbhid/hid-quirks.c
linux-2.6.23/drivers/hid/usbhid/hid-quirks.c
--- linux-2.6.23-orig/drivers/hid/usbhid/hid-quirks.c
2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23/drivers/hid/usbhid/hid-quirks.c
2007-12-22 08:57:46.000000000 +0100
@@ -310,6 +310,9 @@
#define USB_VENDOR_ID_SAITEK 0x06a3
#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
+#define USB_VENDOR_ID_SAMSUNG 0x0419
+#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
+
#define USB_VENDOR_ID_SONY 0x054c
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
@@ -616,6 +619,8 @@ static const struct
hid_rdesc_blacklist
{ USB_VENDOR_ID_PETALYNX,
USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE,
HID_QUIRK_RDESC_PETALYNX },
+ { USB_VENDOR_ID_SAMSUNG,
USB_DEVICE_ID_SAMSUNG_IR_REMOTE,
HID_QUIRK_RDESC_SAMSUNG_REMOTE },
+
{ 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 },
@@ -888,6 +893,36 @@ static void
usbhid_fixup_logitech_descri
}
}
+/*
+ * Samsung IrDA remote controller (reports as Cypress
USB Mouse).
+ *
+ * Unfortunately, the vendor specific report #4 has a
size of 48 bit,
+ * and therefore is not accepted when inspecting the
descriptors on plugin.
+ * According to the USB HID 1.11, section "Report
Constraints", a field
+ * should span at most 4 bytes (=current Linux USB
HID implementation).
+ * As a workaround we reinterpret the report like
this:
+ * OLD: Array type, count 1, size 48 bit, log.
maximum 64
+ * NEW: Variable type, count 6, size 8 bit, log.
maximum 255
+ * The burden to reconstruct the data is moved into
user space (hiddev).
+ */
+static void
usbhid_fixup_samsung_irda_descriptor(unsigned char
*rdesc,
+ int rsize)
+{
+ if (rsize >= 182 && rdesc[175] == 0x25
+ && rdesc[176] == 0x40
+ && rdesc[177] == 0x75
+ && rdesc[178] == 0x30
+ && rdesc[179] == 0x95
+ && rdesc[180] == 0x01
+ && rdesc[182] == 0x40) {
+ printk(KERN_INFO "Fixing up Samsung IrDA report
descriptor\n");
+ rdesc[176] = 0xff; /* logical max value 255 */
+ rdesc[178] = 0x08; /* 8 bit */
+ rdesc[180] = 0x06; /* 6 usage elements */
+ rdesc[182] = 0x42; /* variable */
+ }
+}
+
/* Petalynx Maxter Remote has maximum for consumer
page set too low */
static void usbhid_fixup_petalynx_descriptor(unsigned
char *rdesc, int rsize)
{
@@ -941,6 +976,9 @@ static void
__usbhid_fixup_report_descri
if (quirks & HID_QUIRK_RDESC_PETALYNX)
usbhid_fixup_petalynx_descriptor(rdesc, rsize);
+
+ if (quirks & HID_QUIRK_RDESC_SAMSUNG_REMOTE)
+ usbhid_fixup_samsung_irda_descriptor(rdesc, rsize);
}
/**
diff -uprN linux-2.6.23-orig/include/linux/hid.h
linux-2.6.23/include/linux/hid.h
--- linux-2.6.23-orig/include/linux/hid.h 2007-10-09
22:31:38.000000000 +0200
+++ linux-2.6.23/include/linux/hid.h 2007-12-22
08:53:30.000000000 +0100
@@ -285,6 +285,7 @@ struct hid_item {
#define HID_QUIRK_RDESC_LOGITECH 0x00000002
#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX 0x00000004
#define HID_QUIRK_RDESC_PETALYNX 0x00000008
+#define HID_QUIRK_RDESC_SAMSUNG_REMOTE 0x00000010
/*
* This is the global environment of the parser. This
information is
__________________________________ Ihr erstes Baby? Holen Sie sich Tipps von anderen Eltern. www.yahoo.de/clever
Samsung USB remotes (0419:0001) are rejected by kernel
2.6.23, because the report descriptor from the remote
contains a 48 bit HID report field. HID 1.11 states:
Fields may span at most 4 bytes.
This patch, based on 2.6.23, fixes this by modifying
the internal report descriptor in hid-quirks.c.
Additional user space support (e.g. LIRC) is required
to fetch the information from the hiddev interface.
Signed-off-by: Robert Schedel <***@yahoo.de>
---
drivers/hid/usbhid/hid-quirks.c | 38
++++++++++++++++++++++++++++++++++++++
include/linux/hid.h | 1 +
2 files changed, 39 insertions(+)
On vanilla kernel 2.6.23 the USB remote bundled with
Satelco EasyWatch DVBs
(idVendor/Product 0419:0001 "Samsung IrDA", device
name "Cypress USB Mouse") does not work correctly. On
plugin the kernel rejects the device immediately, see
trace below:
drivers/hid/usbhid/hid-core.c: HID probe called for
ifnum 0
drivers/hid/usbhid/hid-core.c: report descriptor (size
184, read 184) = 05 01 09 06 a1 01 85 01 05 07 19 e0
29 e7 15 00 25 01 95 08 75 01 81 02 95 01 75 08 81 01
95 05 75 01 05 08 19 01 29 05 91 02 95 01 75 03 91 01
95 05 75 08 15 00 25 65 05 07 19 00 29 65 81 00 c0 05
01 09 02 a1 01 85 02 09 01 a1 00 05 09 19 01 29 03 15
00 25 01 95 03 75 01 81 02 95 01 75 05 81 01 05 01 09
30 09 31 09 38 15 81 25 7f 75 08 95 03 81 06 c0 c0 05
01 09 80 a1 01 85 03 05 01 19 81 29 88 15 00 25 01 95
08 75 01 81 02 c0 06 cc ff 09 88 a1 01 85 04 09 01 09
02 09 03 09 04 09 05 09 06 09 07 09 08 09 09 09 0a 15
00 25 40 75 30 95 01 81 40 c0
drivers/hid/hid-core.c: invalid report_size 48
drivers/hid/hid-core.c: item 0 1 1 7 parsing failed
drivers/hid/usbhid/hid-core.c: parsing report
descriptor failed
I have also attached the decoded "lsusb" output for
this device. As it shows, the proprietary usage page
(used for indicating most keys) indicates a single 48
bit array field. In my understanding of HID 1.11,
section "Report Constraints", fields may not span more
than 4 bytes, so it sounds like a device quirk rather
than a kernel deficiency.
The patch introduces a workaround to the quirk by
fixing up the report descriptor in hid-quirks.c.
Some side notes:
- As the device also has output applications (which
are unused by the remote though), an hiddev interface
is already created. So the flag "HID_QUIRK_HIDDEV" is
not set in the patch.
- Note, the new "hidraw" from 2.6.24 also will not
solve the issue because the device is rejected either
before hidraw has a chance to access the device.
- A LIRC patch to fetch all keys from the hiddev
interface has been posted to the LIRC developer list.
- I am aware that the merge window for 2.6.24 is
closed, so please consider whether this can be
included in later kernels or provide feedback
meanwhile.
Regards,
Robert Schedel
diff -uprN
linux-2.6.23-orig/drivers/hid/usbhid/hid-quirks.c
linux-2.6.23/drivers/hid/usbhid/hid-quirks.c
--- linux-2.6.23-orig/drivers/hid/usbhid/hid-quirks.c
2007-10-09 22:31:38.000000000 +0200
+++ linux-2.6.23/drivers/hid/usbhid/hid-quirks.c
2007-12-22 08:57:46.000000000 +0100
@@ -310,6 +310,9 @@
#define USB_VENDOR_ID_SAITEK 0x06a3
#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
+#define USB_VENDOR_ID_SAMSUNG 0x0419
+#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
+
#define USB_VENDOR_ID_SONY 0x054c
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
@@ -616,6 +619,8 @@ static const struct
hid_rdesc_blacklist
{ USB_VENDOR_ID_PETALYNX,
USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE,
HID_QUIRK_RDESC_PETALYNX },
+ { USB_VENDOR_ID_SAMSUNG,
USB_DEVICE_ID_SAMSUNG_IR_REMOTE,
HID_QUIRK_RDESC_SAMSUNG_REMOTE },
+
{ 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 },
@@ -888,6 +893,36 @@ static void
usbhid_fixup_logitech_descri
}
}
+/*
+ * Samsung IrDA remote controller (reports as Cypress
USB Mouse).
+ *
+ * Unfortunately, the vendor specific report #4 has a
size of 48 bit,
+ * and therefore is not accepted when inspecting the
descriptors on plugin.
+ * According to the USB HID 1.11, section "Report
Constraints", a field
+ * should span at most 4 bytes (=current Linux USB
HID implementation).
+ * As a workaround we reinterpret the report like
this:
+ * OLD: Array type, count 1, size 48 bit, log.
maximum 64
+ * NEW: Variable type, count 6, size 8 bit, log.
maximum 255
+ * The burden to reconstruct the data is moved into
user space (hiddev).
+ */
+static void
usbhid_fixup_samsung_irda_descriptor(unsigned char
*rdesc,
+ int rsize)
+{
+ if (rsize >= 182 && rdesc[175] == 0x25
+ && rdesc[176] == 0x40
+ && rdesc[177] == 0x75
+ && rdesc[178] == 0x30
+ && rdesc[179] == 0x95
+ && rdesc[180] == 0x01
+ && rdesc[182] == 0x40) {
+ printk(KERN_INFO "Fixing up Samsung IrDA report
descriptor\n");
+ rdesc[176] = 0xff; /* logical max value 255 */
+ rdesc[178] = 0x08; /* 8 bit */
+ rdesc[180] = 0x06; /* 6 usage elements */
+ rdesc[182] = 0x42; /* variable */
+ }
+}
+
/* Petalynx Maxter Remote has maximum for consumer
page set too low */
static void usbhid_fixup_petalynx_descriptor(unsigned
char *rdesc, int rsize)
{
@@ -941,6 +976,9 @@ static void
__usbhid_fixup_report_descri
if (quirks & HID_QUIRK_RDESC_PETALYNX)
usbhid_fixup_petalynx_descriptor(rdesc, rsize);
+
+ if (quirks & HID_QUIRK_RDESC_SAMSUNG_REMOTE)
+ usbhid_fixup_samsung_irda_descriptor(rdesc, rsize);
}
/**
diff -uprN linux-2.6.23-orig/include/linux/hid.h
linux-2.6.23/include/linux/hid.h
--- linux-2.6.23-orig/include/linux/hid.h 2007-10-09
22:31:38.000000000 +0200
+++ linux-2.6.23/include/linux/hid.h 2007-12-22
08:53:30.000000000 +0100
@@ -285,6 +285,7 @@ struct hid_item {
#define HID_QUIRK_RDESC_LOGITECH 0x00000002
#define HID_QUIRK_RDESC_SWAPPED_MIN_MAX 0x00000004
#define HID_QUIRK_RDESC_PETALYNX 0x00000008
+#define HID_QUIRK_RDESC_SAMSUNG_REMOTE 0x00000010
/*
* This is the global environment of the parser. This
information is
__________________________________ Ihr erstes Baby? Holen Sie sich Tipps von anderen Eltern. www.yahoo.de/clever