[PATCH] USB HID: Support Samsung IR remote (0419:0001)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Robert Schedel <r.schedel@xxxxxxxx>

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 <r.schedel@xxxxxxxx>

---

 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
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)
-------------------------------------------------------------------------
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/
_______________________________________________
linux-usb-devel@xxxxxxxxxxxxxxxxxxxxx
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

[Index of Archives]     [Video for Linux]     [Photo]     [Yosemite Forum]     [Yosemite Photos]    [Linux Kernel]     [Linux SCSI]     [XFree86]     [Devices]     [Big List of Linux Books]

  Powered by Linux