Re: [PATCH v4] hid/i2c-hid: override HID descriptors for certain devices

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

 



On Wed, 19 Sep 2018, Julian Sax wrote:

> A particular touchpad (SIPODEV SP1064) refuses to supply the HID
> descriptors. This patch provides the framework for overriding these
> descriptors based on DMI data. It also includes the descriptors for
> said touchpad, which were extracted by listening to the traffic of the
> windows filter driver, as well as the DMI data for the laptops known
> to use this device.
> 
> Relevant Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1526312
> 
> Cc: Hans de Goede <hdegoede@xxxxxxxxxx>
> Reported-and-tested-by: ahormann@xxxxxxx
> Reported-and-tested-by: Bruno Jesus <bruno.fl.jesus@xxxxxxxxx>
> Reported-and-tested-by: Dietrich <enaut.w@xxxxxxxxxxxxxx>
> Reported-and-tested-by: kloxdami@xxxxxxxxx
> Signed-off-by: Julian Sax <jsbc@xxxxxx>
> ---
> Changes in v4:
> * added Mediacom Flexbook Edge 11 to the override list
> 
> Changes in v3:
> * added additional check for the ACPI ID of the device
> * added Direkt-Tek DTLAPY116-2 to the override list
> 
> Changes in v2:
> * added documentation about the source of the descriptors
> * added documentation inside the descriptors

Applied to for-4.20/i2c-hid, thanks.

> 
>  drivers/hid/i2c-hid/Makefile                  |   3 +
>  .../hid/i2c-hid/{i2c-hid.c => i2c-hid-core.c} |  60 ++-
>  drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c      | 376 ++++++++++++++++++
>  drivers/hid/i2c-hid/i2c-hid.h                 |  20 +
>  4 files changed, 439 insertions(+), 20 deletions(-)
>  rename drivers/hid/i2c-hid/{i2c-hid.c => i2c-hid-core.c} (96%)
>  create mode 100644 drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
>  create mode 100644 drivers/hid/i2c-hid/i2c-hid.h
> 
> diff --git a/drivers/hid/i2c-hid/Makefile b/drivers/hid/i2c-hid/Makefile
> index 832d8f9aaba..099e1ce2f23 100644
> --- a/drivers/hid/i2c-hid/Makefile
> +++ b/drivers/hid/i2c-hid/Makefile
> @@ -3,3 +3,6 @@
>  #
>  
>  obj-$(CONFIG_I2C_HID)				+= i2c-hid.o
> +
> +i2c-hid-objs					=  i2c-hid-core.o
> +i2c-hid-$(CONFIG_DMI)				+= i2c-hid-dmi-quirks.o
> diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid-core.c
> similarity index 96%
> rename from drivers/hid/i2c-hid/i2c-hid.c
> rename to drivers/hid/i2c-hid/i2c-hid-core.c
> index f3076659361..823c63ad08b 100644
> --- a/drivers/hid/i2c-hid/i2c-hid.c
> +++ b/drivers/hid/i2c-hid/i2c-hid-core.c
> @@ -43,6 +43,7 @@
>  #include <linux/platform_data/i2c-hid.h>
>  
>  #include "../hid-ids.h"
> +#include "i2c-hid.h"
>  
>  /* quirks to control the device */
>  #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV	BIT(0)
> @@ -669,6 +670,7 @@ static int i2c_hid_parse(struct hid_device *hid)
>  	char *rdesc;
>  	int ret;
>  	int tries = 3;
> +	char *use_override;
>  
>  	i2c_hid_dbg(ihid, "entering %s\n", __func__);
>  
> @@ -687,26 +689,37 @@ static int i2c_hid_parse(struct hid_device *hid)
>  	if (ret)
>  		return ret;
>  
> -	rdesc = kzalloc(rsize, GFP_KERNEL);
> +	use_override = i2c_hid_get_dmi_hid_report_desc_override(client->name,
> +								&rsize);
>  
> -	if (!rdesc) {
> -		dbg_hid("couldn't allocate rdesc memory\n");
> -		return -ENOMEM;
> -	}
> -
> -	i2c_hid_dbg(ihid, "asking HID report descriptor\n");
> -
> -	ret = i2c_hid_command(client, &hid_report_descr_cmd, rdesc, rsize);
> -	if (ret) {
> -		hid_err(hid, "reading report descriptor failed\n");
> -		kfree(rdesc);
> -		return -EIO;
> +	if (use_override) {
> +		rdesc = use_override;
> +		i2c_hid_dbg(ihid, "Using a HID report descriptor override\n");
> +	} else {
> +		rdesc = kzalloc(rsize, GFP_KERNEL);
> +
> +		if (!rdesc) {
> +			dbg_hid("couldn't allocate rdesc memory\n");
> +			return -ENOMEM;
> +		}
> +
> +		i2c_hid_dbg(ihid, "asking HID report descriptor\n");
> +
> +		ret = i2c_hid_command(client, &hid_report_descr_cmd,
> +				      rdesc, rsize);
> +		if (ret) {
> +			hid_err(hid, "reading report descriptor failed\n");
> +			kfree(rdesc);
> +			return -EIO;
> +		}
>  	}
>  
>  	i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
>  
>  	ret = hid_parse_report(hid, rdesc, rsize);
> -	kfree(rdesc);
> +	if (!use_override)
> +		kfree(rdesc);
> +
>  	if (ret) {
>  		dbg_hid("parsing report descriptor failed\n");
>  		return ret;
> @@ -833,12 +846,19 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
>  	int ret;
>  
>  	/* i2c hid fetch using a fixed descriptor size (30 bytes) */
> -	i2c_hid_dbg(ihid, "Fetching the HID descriptor\n");
> -	ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer,
> -				sizeof(struct i2c_hid_desc));
> -	if (ret) {
> -		dev_err(&client->dev, "hid_descr_cmd failed\n");
> -		return -ENODEV;
> +	if (i2c_hid_get_dmi_i2c_hid_desc_override(client->name)) {
> +		i2c_hid_dbg(ihid, "Using a HID descriptor override\n");
> +		ihid->hdesc =
> +			*i2c_hid_get_dmi_i2c_hid_desc_override(client->name);
> +	} else {
> +		i2c_hid_dbg(ihid, "Fetching the HID descriptor\n");
> +		ret = i2c_hid_command(client, &hid_descr_cmd,
> +				      ihid->hdesc_buffer,
> +				      sizeof(struct i2c_hid_desc));
> +		if (ret) {
> +			dev_err(&client->dev, "hid_descr_cmd failed\n");
> +			return -ENODEV;
> +		}
>  	}
>  
>  	/* Validate the length of HID descriptor, the 4 first bytes:
> diff --git a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
> new file mode 100644
> index 00000000000..1d645c9ab41
> --- /dev/null
> +++ b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
> @@ -0,0 +1,376 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +
> +/*
> + * Quirks for I2C-HID devices that do not supply proper descriptors
> + *
> + * Copyright (c) 2018 Julian Sax <jsbc@xxxxxx>
> + *
> + */
> +
> +#include <linux/types.h>
> +#include <linux/dmi.h>
> +#include <linux/mod_devicetable.h>
> +
> +#include "i2c-hid.h"
> +
> +
> +struct i2c_hid_desc_override {
> +	union {
> +		struct i2c_hid_desc *i2c_hid_desc;
> +		uint8_t             *i2c_hid_desc_buffer;
> +	};
> +	uint8_t              *hid_report_desc;
> +	unsigned int          hid_report_desc_size;
> +	uint8_t              *i2c_name;
> +};
> +
> +
> +/*
> + * descriptors for the SIPODEV SP1064 touchpad
> + *
> + * This device does not supply any descriptors and on windows a filter
> + * driver operates between the i2c-hid layer and the device and injects
> + * these descriptors when the device is prompted. The descriptors were
> + * extracted by listening to the i2c-hid traffic that occurs between the
> + * windows filter driver and the windows i2c-hid driver.
> + */
> +
> +static const struct i2c_hid_desc_override sipodev_desc = {
> +	.i2c_hid_desc_buffer = (uint8_t [])
> +	{0x1e, 0x00,                  /* Length of descriptor                 */
> +	 0x00, 0x01,                  /* Version of descriptor                */
> +	 0xdb, 0x01,                  /* Length of report descriptor          */
> +	 0x21, 0x00,                  /* Location of report descriptor        */
> +	 0x24, 0x00,                  /* Location of input report             */
> +	 0x1b, 0x00,                  /* Max input report length              */
> +	 0x25, 0x00,                  /* Location of output report            */
> +	 0x11, 0x00,                  /* Max output report length             */
> +	 0x22, 0x00,                  /* Location of command register         */
> +	 0x23, 0x00,                  /* Location of data register            */
> +	 0x11, 0x09,                  /* Vendor ID                            */
> +	 0x88, 0x52,                  /* Product ID                           */
> +	 0x06, 0x00,                  /* Version ID                           */
> +	 0x00, 0x00, 0x00, 0x00       /* Reserved                             */
> +	},
> +
> +	.hid_report_desc = (uint8_t [])
> +	{0x05, 0x01,                  /* Usage Page (Desktop),                */
> +	 0x09, 0x02,                  /* Usage (Mouse),                       */
> +	 0xA1, 0x01,                  /* Collection (Application),            */
> +	 0x85, 0x01,                  /*     Report ID (1),                   */
> +	 0x09, 0x01,                  /*     Usage (Pointer),                 */
> +	 0xA1, 0x00,                  /*     Collection (Physical),           */
> +	 0x05, 0x09,                  /*         Usage Page (Button),         */
> +	 0x19, 0x01,                  /*         Usage Minimum (01h),         */
> +	 0x29, 0x02,                  /*         Usage Maximum (02h),         */
> +	 0x25, 0x01,                  /*         Logical Maximum (1),         */
> +	 0x75, 0x01,                  /*         Report Size (1),             */
> +	 0x95, 0x02,                  /*         Report Count (2),            */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x95, 0x06,                  /*         Report Count (6),            */
> +	 0x81, 0x01,                  /*         Input (Constant),            */
> +	 0x05, 0x01,                  /*         Usage Page (Desktop),        */
> +	 0x09, 0x30,                  /*         Usage (X),                   */
> +	 0x09, 0x31,                  /*         Usage (Y),                   */
> +	 0x15, 0x81,                  /*         Logical Minimum (-127),      */
> +	 0x25, 0x7F,                  /*         Logical Maximum (127),       */
> +	 0x75, 0x08,                  /*         Report Size (8),             */
> +	 0x95, 0x02,                  /*         Report Count (2),            */
> +	 0x81, 0x06,                  /*         Input (Variable, Relative),  */
> +	 0xC0,                        /*     End Collection,                  */
> +	 0xC0,                        /* End Collection,                      */
> +	 0x05, 0x0D,                  /* Usage Page (Digitizer),              */
> +	 0x09, 0x05,                  /* Usage (Touchpad),                    */
> +	 0xA1, 0x01,                  /* Collection (Application),            */
> +	 0x85, 0x04,                  /*     Report ID (4),                   */
> +	 0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
> +	 0x09, 0x22,                  /*     Usage (Finger),                  */
> +	 0xA1, 0x02,                  /*     Collection (Logical),            */
> +	 0x15, 0x00,                  /*         Logical Minimum (0),         */
> +	 0x25, 0x01,                  /*         Logical Maximum (1),         */
> +	 0x09, 0x47,                  /*         Usage (Touch Valid),         */
> +	 0x09, 0x42,                  /*         Usage (Tip Switch),          */
> +	 0x95, 0x02,                  /*         Report Count (2),            */
> +	 0x75, 0x01,                  /*         Report Size (1),             */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x95, 0x01,                  /*         Report Count (1),            */
> +	 0x75, 0x03,                  /*         Report Size (3),             */
> +	 0x25, 0x05,                  /*         Logical Maximum (5),         */
> +	 0x09, 0x51,                  /*         Usage (Contact Identifier),  */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x75, 0x01,                  /*         Report Size (1),             */
> +	 0x95, 0x03,                  /*         Report Count (3),            */
> +	 0x81, 0x03,                  /*         Input (Constant, Variable),  */
> +	 0x05, 0x01,                  /*         Usage Page (Desktop),        */
> +	 0x26, 0x44, 0x0A,            /*         Logical Maximum (2628),      */
> +	 0x75, 0x10,                  /*         Report Size (16),            */
> +	 0x55, 0x0E,                  /*         Unit Exponent (14),          */
> +	 0x65, 0x11,                  /*         Unit (Centimeter),           */
> +	 0x09, 0x30,                  /*         Usage (X),                   */
> +	 0x46, 0x1A, 0x04,            /*         Physical Maximum (1050),     */
> +	 0x95, 0x01,                  /*         Report Count (1),            */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x46, 0xBC, 0x02,            /*         Physical Maximum (700),      */
> +	 0x26, 0x34, 0x05,            /*         Logical Maximum (1332),      */
> +	 0x09, 0x31,                  /*         Usage (Y),                   */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0xC0,                        /*     End Collection,                  */
> +	 0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
> +	 0x09, 0x22,                  /*     Usage (Finger),                  */
> +	 0xA1, 0x02,                  /*     Collection (Logical),            */
> +	 0x25, 0x01,                  /*         Logical Maximum (1),         */
> +	 0x09, 0x47,                  /*         Usage (Touch Valid),         */
> +	 0x09, 0x42,                  /*         Usage (Tip Switch),          */
> +	 0x95, 0x02,                  /*         Report Count (2),            */
> +	 0x75, 0x01,                  /*         Report Size (1),             */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x95, 0x01,                  /*         Report Count (1),            */
> +	 0x75, 0x03,                  /*         Report Size (3),             */
> +	 0x25, 0x05,                  /*         Logical Maximum (5),         */
> +	 0x09, 0x51,                  /*         Usage (Contact Identifier),  */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x75, 0x01,                  /*         Report Size (1),             */
> +	 0x95, 0x03,                  /*         Report Count (3),            */
> +	 0x81, 0x03,                  /*         Input (Constant, Variable),  */
> +	 0x05, 0x01,                  /*         Usage Page (Desktop),        */
> +	 0x26, 0x44, 0x0A,            /*         Logical Maximum (2628),      */
> +	 0x75, 0x10,                  /*         Report Size (16),            */
> +	 0x09, 0x30,                  /*         Usage (X),                   */
> +	 0x46, 0x1A, 0x04,            /*         Physical Maximum (1050),     */
> +	 0x95, 0x01,                  /*         Report Count (1),            */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x46, 0xBC, 0x02,            /*         Physical Maximum (700),      */
> +	 0x26, 0x34, 0x05,            /*         Logical Maximum (1332),      */
> +	 0x09, 0x31,                  /*         Usage (Y),                   */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0xC0,                        /*     End Collection,                  */
> +	 0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
> +	 0x09, 0x22,                  /*     Usage (Finger),                  */
> +	 0xA1, 0x02,                  /*     Collection (Logical),            */
> +	 0x25, 0x01,                  /*         Logical Maximum (1),         */
> +	 0x09, 0x47,                  /*         Usage (Touch Valid),         */
> +	 0x09, 0x42,                  /*         Usage (Tip Switch),          */
> +	 0x95, 0x02,                  /*         Report Count (2),            */
> +	 0x75, 0x01,                  /*         Report Size (1),             */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x95, 0x01,                  /*         Report Count (1),            */
> +	 0x75, 0x03,                  /*         Report Size (3),             */
> +	 0x25, 0x05,                  /*         Logical Maximum (5),         */
> +	 0x09, 0x51,                  /*         Usage (Contact Identifier),  */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x75, 0x01,                  /*         Report Size (1),             */
> +	 0x95, 0x03,                  /*         Report Count (3),            */
> +	 0x81, 0x03,                  /*         Input (Constant, Variable),  */
> +	 0x05, 0x01,                  /*         Usage Page (Desktop),        */
> +	 0x26, 0x44, 0x0A,            /*         Logical Maximum (2628),      */
> +	 0x75, 0x10,                  /*         Report Size (16),            */
> +	 0x09, 0x30,                  /*         Usage (X),                   */
> +	 0x46, 0x1A, 0x04,            /*         Physical Maximum (1050),     */
> +	 0x95, 0x01,                  /*         Report Count (1),            */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x46, 0xBC, 0x02,            /*         Physical Maximum (700),      */
> +	 0x26, 0x34, 0x05,            /*         Logical Maximum (1332),      */
> +	 0x09, 0x31,                  /*         Usage (Y),                   */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0xC0,                        /*     End Collection,                  */
> +	 0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
> +	 0x09, 0x22,                  /*     Usage (Finger),                  */
> +	 0xA1, 0x02,                  /*     Collection (Logical),            */
> +	 0x25, 0x01,                  /*         Logical Maximum (1),         */
> +	 0x09, 0x47,                  /*         Usage (Touch Valid),         */
> +	 0x09, 0x42,                  /*         Usage (Tip Switch),          */
> +	 0x95, 0x02,                  /*         Report Count (2),            */
> +	 0x75, 0x01,                  /*         Report Size (1),             */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x95, 0x01,                  /*         Report Count (1),            */
> +	 0x75, 0x03,                  /*         Report Size (3),             */
> +	 0x25, 0x05,                  /*         Logical Maximum (5),         */
> +	 0x09, 0x51,                  /*         Usage (Contact Identifier),  */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x75, 0x01,                  /*         Report Size (1),             */
> +	 0x95, 0x03,                  /*         Report Count (3),            */
> +	 0x81, 0x03,                  /*         Input (Constant, Variable),  */
> +	 0x05, 0x01,                  /*         Usage Page (Desktop),        */
> +	 0x26, 0x44, 0x0A,            /*         Logical Maximum (2628),      */
> +	 0x75, 0x10,                  /*         Report Size (16),            */
> +	 0x09, 0x30,                  /*         Usage (X),                   */
> +	 0x46, 0x1A, 0x04,            /*         Physical Maximum (1050),     */
> +	 0x95, 0x01,                  /*         Report Count (1),            */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0x46, 0xBC, 0x02,            /*         Physical Maximum (700),      */
> +	 0x26, 0x34, 0x05,            /*         Logical Maximum (1332),      */
> +	 0x09, 0x31,                  /*         Usage (Y),                   */
> +	 0x81, 0x02,                  /*         Input (Variable),            */
> +	 0xC0,                        /*     End Collection,                  */
> +	 0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
> +	 0x55, 0x0C,                  /*     Unit Exponent (12),              */
> +	 0x66, 0x01, 0x10,            /*     Unit (Seconds),                  */
> +	 0x47, 0xFF, 0xFF, 0x00, 0x00,/*     Physical Maximum (65535),        */
> +	 0x27, 0xFF, 0xFF, 0x00, 0x00,/*     Logical Maximum (65535),         */
> +	 0x75, 0x10,                  /*     Report Size (16),                */
> +	 0x95, 0x01,                  /*     Report Count (1),                */
> +	 0x09, 0x56,                  /*     Usage (Scan Time),               */
> +	 0x81, 0x02,                  /*     Input (Variable),                */
> +	 0x09, 0x54,                  /*     Usage (Contact Count),           */
> +	 0x25, 0x7F,                  /*     Logical Maximum (127),           */
> +	 0x75, 0x08,                  /*     Report Size (8),                 */
> +	 0x81, 0x02,                  /*     Input (Variable),                */
> +	 0x05, 0x09,                  /*     Usage Page (Button),             */
> +	 0x09, 0x01,                  /*     Usage (01h),                     */
> +	 0x25, 0x01,                  /*     Logical Maximum (1),             */
> +	 0x75, 0x01,                  /*     Report Size (1),                 */
> +	 0x95, 0x01,                  /*     Report Count (1),                */
> +	 0x81, 0x02,                  /*     Input (Variable),                */
> +	 0x95, 0x07,                  /*     Report Count (7),                */
> +	 0x81, 0x03,                  /*     Input (Constant, Variable),      */
> +	 0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
> +	 0x85, 0x02,                  /*     Report ID (2),                   */
> +	 0x09, 0x55,                  /*     Usage (Contact Count Maximum),   */
> +	 0x09, 0x59,                  /*     Usage (59h),                     */
> +	 0x75, 0x04,                  /*     Report Size (4),                 */
> +	 0x95, 0x02,                  /*     Report Count (2),                */
> +	 0x25, 0x0F,                  /*     Logical Maximum (15),            */
> +	 0xB1, 0x02,                  /*     Feature (Variable),              */
> +	 0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
> +	 0x85, 0x07,                  /*     Report ID (7),                   */
> +	 0x09, 0x60,                  /*     Usage (60h),                     */
> +	 0x75, 0x01,                  /*     Report Size (1),                 */
> +	 0x95, 0x01,                  /*     Report Count (1),                */
> +	 0x25, 0x01,                  /*     Logical Maximum (1),             */
> +	 0xB1, 0x02,                  /*     Feature (Variable),              */
> +	 0x95, 0x07,                  /*     Report Count (7),                */
> +	 0xB1, 0x03,                  /*     Feature (Constant, Variable),    */
> +	 0x85, 0x06,                  /*     Report ID (6),                   */
> +	 0x06, 0x00, 0xFF,            /*     Usage Page (FF00h),              */
> +	 0x09, 0xC5,                  /*     Usage (C5h),                     */
> +	 0x26, 0xFF, 0x00,            /*     Logical Maximum (255),           */
> +	 0x75, 0x08,                  /*     Report Size (8),                 */
> +	 0x96, 0x00, 0x01,            /*     Report Count (256),              */
> +	 0xB1, 0x02,                  /*     Feature (Variable),              */
> +	 0xC0,                        /* End Collection,                      */
> +	 0x06, 0x00, 0xFF,            /* Usage Page (FF00h),                  */
> +	 0x09, 0x01,                  /* Usage (01h),                         */
> +	 0xA1, 0x01,                  /* Collection (Application),            */
> +	 0x85, 0x0D,                  /*     Report ID (13),                  */
> +	 0x26, 0xFF, 0x00,            /*     Logical Maximum (255),           */
> +	 0x19, 0x01,                  /*     Usage Minimum (01h),             */
> +	 0x29, 0x02,                  /*     Usage Maximum (02h),             */
> +	 0x75, 0x08,                  /*     Report Size (8),                 */
> +	 0x95, 0x02,                  /*     Report Count (2),                */
> +	 0xB1, 0x02,                  /*     Feature (Variable),              */
> +	 0xC0,                        /* End Collection,                      */
> +	 0x05, 0x0D,                  /* Usage Page (Digitizer),              */
> +	 0x09, 0x0E,                  /* Usage (Configuration),               */
> +	 0xA1, 0x01,                  /* Collection (Application),            */
> +	 0x85, 0x03,                  /*     Report ID (3),                   */
> +	 0x09, 0x22,                  /*     Usage (Finger),                  */
> +	 0xA1, 0x02,                  /*     Collection (Logical),            */
> +	 0x09, 0x52,                  /*         Usage (Device Mode),         */
> +	 0x25, 0x0A,                  /*         Logical Maximum (10),        */
> +	 0x95, 0x01,                  /*         Report Count (1),            */
> +	 0xB1, 0x02,                  /*         Feature (Variable),          */
> +	 0xC0,                        /*     End Collection,                  */
> +	 0x09, 0x22,                  /*     Usage (Finger),                  */
> +	 0xA1, 0x00,                  /*     Collection (Physical),           */
> +	 0x85, 0x05,                  /*         Report ID (5),               */
> +	 0x09, 0x57,                  /*         Usage (57h),                 */
> +	 0x09, 0x58,                  /*         Usage (58h),                 */
> +	 0x75, 0x01,                  /*         Report Size (1),             */
> +	 0x95, 0x02,                  /*         Report Count (2),            */
> +	 0x25, 0x01,                  /*         Logical Maximum (1),         */
> +	 0xB1, 0x02,                  /*         Feature (Variable),          */
> +	 0x95, 0x06,                  /*         Report Count (6),            */
> +	 0xB1, 0x03,                  /*         Feature (Constant, Variable),*/
> +	 0xC0,                        /*     End Collection,                  */
> +	 0xC0                         /* End Collection                       */
> +	},
> +	.hid_report_desc_size = 475,
> +	.i2c_name = "SYNA3602:00"
> +};
> +
> +
> +static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
> +	{
> +		.ident = "Teclast F6 Pro",
> +		.matches = {
> +			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TECLAST"),
> +			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "F6 Pro"),
> +		},
> +		.driver_data = (void *)&sipodev_desc
> +	},
> +	{
> +		.ident = "Teclast F7",
> +		.matches = {
> +			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TECLAST"),
> +			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "F7"),
> +		},
> +		.driver_data = (void *)&sipodev_desc
> +	},
> +	{
> +		.ident = "Trekstor Primebook C13",
> +		.matches = {
> +			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
> +			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
> +		},
> +		.driver_data = (void *)&sipodev_desc
> +	},
> +	{
> +		.ident = "Trekstor Primebook C11",
> +		.matches = {
> +			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
> +			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C11"),
> +		},
> +		.driver_data = (void *)&sipodev_desc
> +	},
> +	{
> +		.ident = "Direkt-Tek DTLAPY116-2",
> +		.matches = {
> +			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Direkt-Tek"),
> +			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "DTLAPY116-2"),
> +		},
> +		.driver_data = (void *)&sipodev_desc
> +	},
> +	{
> +		.ident = "Mediacom Flexbook Edge 11",
> +		.matches = {
> +			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MEDIACOM"),
> +			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FlexBook edge11 - M-FBE11"),
> +		},
> +		.driver_data = (void *)&sipodev_desc
> +	}
> +};
> +
> +
> +struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
> +{
> +	struct i2c_hid_desc_override *override;
> +	const struct dmi_system_id *system_id;
> +
> +	system_id = dmi_first_match(i2c_hid_dmi_desc_override_table);
> +	if (!system_id)
> +		return NULL;
> +
> +	override = system_id->driver_data;
> +	if (strcmp(override->i2c_name, i2c_name))
> +		return NULL;
> +
> +	return override->i2c_hid_desc;
> +}
> +
> +char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
> +					       unsigned int *size)
> +{
> +	struct i2c_hid_desc_override *override;
> +	const struct dmi_system_id *system_id;
> +
> +	system_id = dmi_first_match(i2c_hid_dmi_desc_override_table);
> +	if (!system_id)
> +		return NULL;
> +
> +	override = system_id->driver_data;
> +	if (strcmp(override->i2c_name, i2c_name))
> +		return NULL;
> +
> +	*size = override->hid_report_desc_size;
> +	return override->hid_report_desc;
> +}
> diff --git a/drivers/hid/i2c-hid/i2c-hid.h b/drivers/hid/i2c-hid/i2c-hid.h
> new file mode 100644
> index 00000000000..a8c19aef582
> --- /dev/null
> +++ b/drivers/hid/i2c-hid/i2c-hid.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +
> +#ifndef I2C_HID_H
> +#define I2C_HID_H
> +
> +
> +#ifdef CONFIG_DMI
> +struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name);
> +char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
> +					       unsigned int *size);
> +#else
> +static inline struct i2c_hid_desc
> +		   *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
> +{ return NULL; }
> +static inline char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
> +							     unsigned int *size)
> +{ return NULL; }
> +#endif
> +
> +#endif
> -- 
> 2.18.0
> 

-- 
Jiri Kosina
SUSE Labs




[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux