History

HID: i2c-hid: hid report descriptor retrieval changes

Reading the partial HID Descriptor is causing a firmware lockup in some sensor hubs. Instead of a partial read, this patch implements the i2c hid fetch using a fixed descriptor size (30 bytes) followed by a verification of the BCDVersion (V01.00), and value stored in wHIDDescLength (30 Bytes) for V1.00 descriptors. As per i2c hid spec, this is the preferred model. From hid-over-i2c-protocol-spec-v1-0: There are a variety of ways a HOST may choose to retrieve the HID Descriptor from the DEVICE. The following is a preferred implementation but should not be considered the only implementation. A HOST may read the entire HID Descriptor in a single read by issuing a read for 30 Bytes to get the entire HID Descriptor from the DEVICE.However, the HOST is responsible for validating that 1. The BCDVersion is V01.00 (later revisions may have different descriptor lengths), and 2. The value stored in wHIDDescLength is 30 (Bytes) for V1.00 descriptors.

Archana Patni committed 12 years ago

Commit f58b8481 parent 7ceeff41 file · +13 −32Browse files

Unified · Split

drivers/hid/i2c-hid/i2c-hid.c+13−32
@@ -807,34 +807,18 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid) · 806 unmodified lines
807807 unsigned int dsize;
808808 int ret;
809809
810− /* Fetch the length of HID description, retrieve the 4 first bytes:
811− * bytes 0-1 -> length
812− * bytes 2-3 -> bcdVersion (has to be 1.00) */
813− ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, 4);
814−
815− i2c_hid_dbg(ihid, "%s, ihid->hdesc_buffer: %4ph\n", __func__,
816− ihid->hdesc_buffer);
817−
810+ /* i2c hid fetch using a fixed descriptor size (30 bytes) */
811+ i2c_hid_dbg(ihid, "Fetching the HID descriptor\n");
812+ ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer,
813+ sizeof(struct i2c_hid_desc));
818814 if (ret) {
819− dev_err(&client->dev,
820− "unable to fetch the size of HID descriptor (ret=%d)\n",
821− ret);
822− return -ENODEV;
823− }
824−
825− dsize = le16_to_cpu(hdesc->wHIDDescLength);
826− /*
827− * the size of the HID descriptor should at least contain
828− * its size and the bcdVersion (4 bytes), and should not be greater
829− * than sizeof(struct i2c_hid_desc) as we directly fill this struct
830− * through i2c_hid_command.
831− */
832− if (dsize < 4 || dsize > sizeof(struct i2c_hid_desc)) {
833− dev_err(&client->dev, "weird size of HID descriptor (%u)\n",
834− dsize);
815+ dev_err(&client->dev, "hid_descr_cmd failed\n");
835816 return -ENODEV;
836817 }
837818
819+ /* Validate the length of HID descriptor, the 4 first bytes:
820+ * bytes 0-1 -> length
821+ * bytes 2-3 -> bcdVersion (has to be 1.00) */
838822 /* check bcdVersion == 1.0 */
839823 if (le16_to_cpu(hdesc->bcdVersion) != 0x0100) {
840824 dev_err(&client->dev,
@@ -843,17 +827,14 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid) · 2 unmodified lines
843827 return -ENODEV;
844828 }
845829
846− i2c_hid_dbg(ihid, "Fetching the HID descriptor\n");
847−
848− ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer,
849− dsize);
850− if (ret) {
851− dev_err(&client->dev, "hid_descr_cmd Fail\n");
830+ /* Descriptor length should be 30 bytes as per the specification */
831+ dsize = le16_to_cpu(hdesc->wHIDDescLength);
832+ if (dsize != sizeof(struct i2c_hid_desc)) {
833+ dev_err(&client->dev, "weird size of HID descriptor (%u)\n",
834+ dsize);
852835 return -ENODEV;
853836 }
854−
855837 i2c_hid_dbg(ihid, "HID Descriptor: %*ph\n", dsize, ihid->hdesc_buffer);
856−
857838 return 0;
858839 }
859840