[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(+)

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

-------------------------------------------------------------------------
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)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.