Re: [PATCH] USB HID: Support Samsung IR remote (0419:0001)
Robert Schedel <[email protected]>
| Newsgroups | gmane.linux.usb.devel |
|---|---|
| Message-ID | <[email protected]> |
From: Robert Schedel <[email protected]> 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 <[email protected]> --- drivers/hid/usbhid/hid-quirks.c | 38 ++++++++++++++++++++++++++++++++++++++ include/linux/hid.h | 1 + 2 files changed, 39 insertions(+) ***** FOLLOWUP, now with MIME attachment. Unfortunately due to web mail interface line wraps in the inline patch were broken in original email. ***** 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 Heute schon einen Blick in die Zukunft von E-Mails wagen? Versuchen Sie´s mit dem neuen Yahoo! Mail. www.yahoo.de/mail ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ [email protected] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
satelco-remote-lsusb.txt
(text/plain, 10.3 KB)
Bus 005 Device 002: ID 0419:0001 Samsung Info. Systems America, Inc. IrDA Remote Controller
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x0419 Samsung Info. Systems America, Inc.
idProduct 0x0001 IrDA Remote Controller
bcdDevice 0.00
iManufacturer 1 Cypress Sem
iProduct 2 Cypress USB Mouse
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 34
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 4 HID Mouse
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Devices
bInterfaceSubClass 1 Boot Interface Subclass
bInterfaceProtocol 1 Keyboard
iInterface 5 EndPoint1 Interrupt Pipe
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.00
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 184
Report Descriptor: (length is 184)
Item(Global): Usage Page, data= [ 0x01 ] 1
Generic Desktop Controls
Item(Local ): Usage, data= [ 0x06 ] 6
Keyboard
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Global): Report ID, data= [ 0x01 ] 1
Item(Global): Usage Page, data= [ 0x07 ] 7
Keyboard
Item(Local ): Usage Minimum, data= [ 0xe0 ] 224
Control Left
Item(Local ): Usage Maximum, data= [ 0xe7 ] 231
GUI Right
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x08 ] 8
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Main ): Input, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report Count, data= [ 0x01 ] 1
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Main ): Input, data= [ 0x01 ] 1
Constant Array Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report Count, data= [ 0x05 ] 5
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Global): Usage Page, data= [ 0x08 ] 8
LEDs
Item(Local ): Usage Minimum, data= [ 0x01 ] 1
NumLock
Item(Local ): Usage Maximum, data= [ 0x05 ] 5
Kana
Item(Main ): Output, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report Count, data= [ 0x01 ] 1
Item(Global): Report Size, data= [ 0x03 ] 3
Item(Main ): Output, data= [ 0x01 ] 1
Constant Array Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report Count, data= [ 0x05 ] 5
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0x65 ] 101
Item(Global): Usage Page, data= [ 0x07 ] 7
Keyboard
Item(Local ): Usage Minimum, data= [ 0x00 ] 0
No Event
Item(Local ): Usage Maximum, data= [ 0x65 ] 101
Keyboard Application (Windows Key for Win95 or Compose)
Item(Main ): Input, data= [ 0x00 ] 0
Data Array Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Main ): End Collection, data=none
Item(Global): Usage Page, data= [ 0x01 ] 1
Generic Desktop Controls
Item(Local ): Usage, data= [ 0x02 ] 2
Mouse
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Global): Report ID, data= [ 0x02 ] 2
Item(Local ): Usage, data= [ 0x01 ] 1
Pointer
Item(Main ): Collection, data= [ 0x00 ] 0
Physical
Item(Global): Usage Page, data= [ 0x09 ] 9
Buttons
Item(Local ): Usage Minimum, data= [ 0x01 ] 1
Button 1 (Primary)
Item(Local ): Usage Maximum, data= [ 0x03 ] 3
Button 3 (Tertiary)
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x03 ] 3
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Main ): Input, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Report Count, data= [ 0x01 ] 1
Item(Global): Report Size, data= [ 0x05 ] 5
Item(Main ): Input, data= [ 0x01 ] 1
Constant Array Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Global): Usage Page, data= [ 0x01 ] 1
Generic Desktop Controls
Item(Local ): Usage, data= [ 0x30 ] 48
Direction-X
Item(Local ): Usage, data= [ 0x31 ] 49
Direction-Y
Item(Local ): Usage, data= [ 0x38 ] 56
Wheel
Item(Global): Logical Minimum, data= [ 0x81 ] 129
Item(Global): Logical Maximum, data= [ 0x7f ] 127
Item(Global): Report Size, data= [ 0x08 ] 8
Item(Global): Report Count, data= [ 0x03 ] 3
Item(Main ): Input, data= [ 0x06 ] 6
Data Variable Relative No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Main ): End Collection, data=none
Item(Main ): End Collection, data=none
Item(Global): Usage Page, data= [ 0x01 ] 1
Generic Desktop Controls
Item(Local ): Usage, data= [ 0x80 ] 128
System Control
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Global): Report ID, data= [ 0x03 ] 3
Item(Global): Usage Page, data= [ 0x01 ] 1
Generic Desktop Controls
Item(Local ): Usage Minimum, data= [ 0x81 ] 129
System Power Down
Item(Local ): Usage Maximum, data= [ 0x88 ] 136
System Menu Exit
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0x01 ] 1
Item(Global): Report Count, data= [ 0x08 ] 8
Item(Global): Report Size, data= [ 0x01 ] 1
Item(Main ): Input, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Main ): End Collection, data=none
Item(Global): Usage Page, data= [ 0xcc 0xff ] 65484
(null)
Item(Local ): Usage, data= [ 0x88 ] 136
(null)
Item(Main ): Collection, data= [ 0x01 ] 1
Application
Item(Global): Report ID, data= [ 0x04 ] 4
Item(Local ): Usage, data= [ 0x01 ] 1
(null)
Item(Local ): Usage, data= [ 0x02 ] 2
(null)
Item(Local ): Usage, data= [ 0x03 ] 3
(null)
Item(Local ): Usage, data= [ 0x04 ] 4
(null)
Item(Local ): Usage, data= [ 0x05 ] 5
(null)
Item(Local ): Usage, data= [ 0x06 ] 6
(null)
Item(Local ): Usage, data= [ 0x07 ] 7
(null)
Item(Local ): Usage, data= [ 0x08 ] 8
(null)
Item(Local ): Usage, data= [ 0x09 ] 9
(null)
Item(Local ): Usage, data= [ 0x0a ] 10
(null)
Item(Global): Logical Minimum, data= [ 0x00 ] 0
Item(Global): Logical Maximum, data= [ 0x40 ] 64
Item(Global): Report Size, data= [ 0x30 ] 48
Item(Global): Report Count, data= [ 0x01 ] 1
Item(Main ): Input, data= [ 0x40 ] 64
Data Array Absolute No_Wrap Linear
Preferred_State Null_State Non_Volatile Bitfield
Item(Main ): End Collection, data=none
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 10
Device Status: 0x0000
(Bus Powered)
kernel-2.6.23-samsung.patch
(application/octet-stream, 3.6 KB)
From: Robert Schedel <[email protected]> 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 <[email protected]> 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