OpenSolaris

Printable Version Enter a New Search
Bug ID 6366097
Synopsis hidparser shouldn't use signed chars when computing max packet size
State 10-Fix Delivered (Fix available in build)
Category:Subcategory driver:usb-hid
Keywords opensolaris | oss-request | oss-sponsor
Sponsor Strony Zhang
Submitter jk
Responsible Engineer Strony Zhang
Reported Against
Duplicate Of
Introduced In
Commit to Fix snv_31
Fixed In snv_31
Release Fixed solaris_nevada(snv_31) , solaris_10u4(s10u4_06) (Bug ID:2137498)
Related Bugs
Submit Date 21-December-2005
Last Update Date 6-November-2008
Description
Category
   driver
Sub-Category
   usb-hid
Description
   I tried to hotplug a "Yealink Network Technology Ltd. VOIP USB Phone" device
(= USB audio device).
This usb audio device isn't usable on solaris, it fails like this:
Dec 13 19:27:51 elise usba: [ID 912658 kern.info] USB 2.0 device (usb6993,b001) operating at full speed (USB 1.x) on USB 2.0 external hub: device@1, usb_mid0 at bus address 3
Dec 13 19:27:51 elise usba: [ID 349649 kern.info]       Yealink Network Technology Ltd. VOIP USB Phone
Dec 13 19:27:51 elise genunix: [ID 936769 kern.info] usb_mid0 is /pci@0,0/pci10b9,5239@a,3/hub@6/device@1
Dec 13 19:27:51 elise genunix: [ID 408114 kern.info] /pci@0,0/pci10b9,5239@a,3/hub@6/device@1 (usb_mid0) online
Dec 13 19:27:51 elise usba: [ID 912658 kern.info] USB 2.0 interface (usbif6993,b001.config1.0) operating at full speed (USB 1.x) on USB 2.0 external hub: sound-control@0, usb_ac0 at bus address 3
Dec 13 19:27:51 elise usba: [ID 349649 kern.info]       Yealink Network Technology Ltd. VOIP USB Phone
Dec 13 19:27:51 elise genunix: [ID 936769 kern.info] usb_ac0 is /pci@0,0/pci10b9,5239@a,3/hub@6/device@1/sound-control@0
Dec 13 19:27:51 elise usba: [ID 912658 kern.info] USB 2.0 interface (usbif6993,b001.config1.1) operating at full speed (USB 1.x) on USB 2.0 external hub: sound@1, usb_as0 at bus address 3
Dec 13 19:27:51 elise usba: [ID 349649 kern.info]       Yealink Network Technology Ltd. VOIP USB Phone
Dec 13 19:27:51 elise genunix: [ID 936769 kern.info] usb_as0 is /pci@0,0/pci10b9,5239@a,3/hub@6/device@1/sound@1
Dec 13 19:27:51 elise genunix: [ID 408114 kern.info] /pci@0,0/pci10b9,5239@a,3/hub@6/device@1/sound@1 (usb_as0) online
Dec 13 19:27:51 elise usba: [ID 912658 kern.info] USB 2.0 interface (usbif6993,b001.config1.2) operating at full speed (USB 1.x) on USB 2.0 external hub: sound@2, usb_as1 at bus address 3
Dec 13 19:27:51 elise usba: [ID 349649 kern.info]       Yealink Network Technology Ltd. VOIP USB Phone
Dec 13 19:27:51 elise genunix: [ID 936769 kern.info] usb_as1 is /pci@0,0/pci10b9,5239@a,3/hub@6/device@1/sound@2
Dec 13 19:27:51 elise genunix: [ID 408114 kern.info] /pci@0,0/pci10b9,5239@a,3/hub@6/device@1/sound@2 (usb_as1) online
Dec 13 19:27:51 elise usba: [ID 912658 kern.info] USB 2.0 interface (usbif6993,b001.config1.3) operating at full speed (USB 1.x) on USB 2.0 external hub: input@3, hid0 at bus address 3
Dec 13 19:27:51 elise usba: [ID 349649 kern.info]       Yealink Network Technology Ltd. VOIP USB Phone
Dec 13 19:27:51 elise genunix: [ID 936769 kern.info] hid0 is /pci@0,0/pci10b9,5239@a,3/hub@6/device@1/input@3
Dec 13 19:27:51 elise genunix: [ID 408114 kern.info] /pci@0,0/pci10b9,5239@a,3/hub@6/device@1/input@3 (hid0) online
Dec 13 19:27:51 elise usba: [ID 723738 kern.info] /pci@0,0/pci10b9,5239@a,3/hub@6/device@1/sound-control@0 (usb_ac0): ldi_open_by_dev failed on major = 58 minor = 0,
name = hid error=5
Dec 13 19:27:51 elise usba: [ID 723738 kern.info] /pci@0,0/pci10b9,5239@a,3/hub@6/device@1/sound-control@0 (usb_ac0): no audio streams driver plumbed
Dec 13 19:27:51 elise genunix: [ID 667643 kern.warning] WARNING: Postattach failed for usb_ac0
In mdb ::usba_debug_bug, the following error can be found
(note the huge interrupt request size of 0x1ffffff0):
mid0:   usb_mid_bus_config: op=2
usba:   hub0 port 1: sound-control, dip = 0xd4e0f900
usba:   hub0 port 1: sound, dip = 0xd4e0f7e0
usba:   hub0 port 1: sound, dip = 0xd4e0f6c0
usba:   hub0 port 1: input, dip = 0xd4e0f5a0
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0fa20, op = 0x1, arg = 0xd4e0f900
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0fa20, op = 0x1, arg = 0xd4e0f7e0
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0fa20, op = 0x1, arg = 0xd4e0f6c0
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0fa20, op = 0x1, arg = 0xd4e0f5a0
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0f900, op = 0x16, arg = 0xd6d03ba0
mid0:   DDI_PRE DDI_CTLOPS_ATTACH
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0f900, op = 0x3, arg = 0x0
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0f900, op = 0x16, arg = 0xd6d03ba0
mid0:   usb_mid_post_attach: ifno = 0 result = 0
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0f7e0, op = 0x16, arg = 0xd6d039f0
mid0:   DDI_PRE DDI_CTLOPS_ATTACH
as0:    enable remote wakeup failed
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0f7e0, op = 0x3, arg = 0x0
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0f7e0, op = 0x16, arg = 0xd6d039f0
mid0:   usb_mid_post_attach: ifno = 1 result = 0
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0f6c0, op = 0x16, arg = 0xd6d039f0
mid0:   DDI_PRE DDI_CTLOPS_ATTACH
as1:    enable remote wakeup failed
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0f6c0, op = 0x3, arg = 0x0
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0f6c0, op = 0x16, arg = 0xd6d039f0
mid0:   usb_mid_post_attach: ifno = 2 result = 0
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0f5a0, op = 0x16, arg = 0xd6d039f0
mid0:   DDI_PRE DDI_CTLOPS_ATTACH
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0f5a0, op = 0x3, arg = 0x0
mid0:   usb_mid_bus_ctl:
        dip = 0xd4e0fa20, rdip = 0xd4e0f5a0, op = 0x16, arg = 0xd6d039f0
mid0:   usb_mid_post_attach: ifno = 3 result = 0
ehci0:  ehci_allocate_intr_resources: Intr request size 0x1ffffff0 is more than
0x5000
ehci0:  ehci_start_periodic_pipe_polling: Start polling failed
hid0:   hid_start_intr_polling failed: rval = -2
hid0:   unable to start intr pipe polling. rval = -2
ac0:    ldi_open_by_dev failed on major = 58 minor = 0, name = hid error=5
ac0:    no audio streams driver plumbed
HID report descriptor data for the usb VOIP phone device:
unsigned char hid_report_desc[] = {
        0x5, 0xb,              /* Usage Page (Telphony)                    */
        0x9, 0x1,              /* Usage (0x1)                              */
        0xa1, 0x1,             /* Collection (Application)                 */
        0x5, 0x9,              /*     Usage Page (Button)                  */
        0x19, 0x1,             /*     Usage Minimum (0x1)                  */
        0x29, 0x3f,            /*     Usage Maximum (0x3f)                 */
        0x15, 0,               /*     Logical Minimum (0)                  */
        0x25, 0x1,             /*     Logical Maximum (0x1)                */
        0x75, 0x1,             /*     Report Size (0x1)                    */
        0x95, 0x80,            /*     Report Count (0x80)                  */
        0x81, 0,               /*     Input (Data, Array, Absolute)        */
        0x5, 0x8,              /*     Usage Page (LED)                     */
        0x19, 0x1,             /*     Usage Minimum (0x1)                  */
        0x29, 0x10,            /*     Usage Maximum (0x10)                 */
        0x15, 0x6,             /*     Logical Minimum (0x6)                */
        0x25, 0x1,             /*     Logical Maximum (0x1)                */
        0x75, 0x1,             /*     Report Size (0x1)                    */
        0x95, 0x80,            /*     Report Count (0x80)                  */
        0x91, 0,               /*     Output (Data, Array, Absolute)       */
        0xc0,                  /* End Collection                           */
};
usr/src/uts/common/io/usb/clients/hid/hid.c:
  1779                  /* Get Report Descriptor was successful */
  1780                  if (hidparser_parse_report_descriptor(
  1781                      data->b_rptr,
  1782                      hidp->hid_hid_descr.wReportDescriptorLength,
  1783                      &hidp->hid_hid_descr,
  1784                      &hidp->hid_report_descr) == HIDPARSER_SUCCESS) {
  1785
  1786                          /* find max intr-in xfer length */
  1787                          hidparser_find_max_packet_size_from_report_descriptor(
  1788                              hidp->hid_report_descr, &hpack);
  1789                          /* round up to the nearest byte */
  1790                          hidp->hid_packet_size = (hpack.max_packet_size + 7) / 8;
Line 1787 computes "hpack.max_packet_size" as 0xffffff80
and (hpack.max_packet_size + 7) / 8 == 0x1ffffff0
Obviously, Report Count (0x80) is interpreted as a signed byte; -128.
Obviously, the device expects the report count to be interpreted as
an unsigned byte; +128.
With a kmdb breakpoint on line 1790, patching hpack.max_packet_size
from -128 to +128, the USB VOIP phone device attaches as an (USB)
audio device just fine.
Frequency
   Always
Regression
   No
Steps to Reproduce
   Hotplug a "Yealink Network Technology Ltd. VOIP USB Phone"
Expected Result
   A usable usb audio device
Actual Result
   no usable usb audio device (because of the failure to plumb the hid device,
using a bad interupt request size).
Error Message(s)
   usba: [ID 723738 kern.info] /pci@0,0/pci10b9,5239@a,3/hub@6/device@1/sound-control@0 (usb_ac0): ldi_open_by_dev failed on major = 58 minor = 0,
name = hid error=5
usba: [ID 723738 kern.info] /pci@0,0/pci10b9,5239@a,3/hub@6/device@1/sound-control@0 (usb_ac0): no audio streams driver plumbed
genunix: [ID 667643 kern.warning] WARNING: Postattach failed for usb_ac0
Test Case
   
Workaround
   Suggested fix:
==============
In usr/src/uts/common/io/usb/clients/hidparser/hidparser.c ...
   353                                  } else if (attribute->entity_attribute_tag ==
   354                                      R_ITEM_REPORT_SIZE) {
   355                                          foundsize = 1;
   356                                          temp = temp * attribute->
   357                                                  entity_attribute_value[0];
   358                                          if (foundcount == 1) {
   359                                                  if (report_id &&
   360                                                      right_report_id) {
   361                                                          break;
   362                                                  }
   363                                          }
   364                                  } else if (attribute->entity_attribute_tag ==
   365                                      R_ITEM_REPORT_COUNT) {
   366                                          foundcount = 1;
   367                                          temp = temp * attribute->
   368                                                  entity_attribute_value[0];
   369                                          if (foundsize == 1) {
   370                                                  if (report_id &&
   371                                                      right_report_id) {
   372                                                          break;
   373                                                  }
   374                                          }
   375                                  }
... use "hidparser_find_unsigned_val(attribute)" instead of directly accessing
"attribute->entity_attribute_value[0]"
--- usr/src/uts/common/io/usb/clients/hidparser/hidparser.c~    2005-12-07 18:39:27.000000000 +0100
+++ usr/src/uts/common/io/usb/clients/hidparser/hidparser.c     2005-12-16 01:42:23.124526000 +0100
@@ -353,8 +353,8 @@
                                } else if (attribute->entity_attribute_tag ==
                                    R_ITEM_REPORT_SIZE) {
                                        foundsize = 1;
-                                       temp = temp * attribute->
-                                               entity_attribute_value[0];
+                                       temp *= hidparser_find_unsigned_val(
+                                           attribute);
                                        if (foundcount == 1) {
                                                if (report_id &&
                                                    right_report_id) {
@@ -364,8 +364,8 @@
                                } else if (attribute->entity_attribute_tag ==
                                    R_ITEM_REPORT_COUNT) {
                                        foundcount = 1;
-                                       temp = temp * attribute->
-                                               entity_attribute_value[0];
+                                       temp *= hidparser_find_unsigned_val(
+                                           attribute);
                                        if (foundsize == 1) {
                                                if (report_id &&
                                                    right_report_id) {
Submitter wants to work on bug
   Yes
Additional configuration information
   Yealink Network Technology Ltd. VOIP USB Phone
Work Around
N/A
Comments
N/A