Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cee5aa1f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull HID fixes from Jiri Kosina:

 - fixes for a couple potential memory corruption problems (the HW would
   have to be manufactured to be deliberately evil to trigger those)
   found by Ben Hawkes
 - fix for potential infinite loop when using sysfs interface of
   logitech driver, from Simon Wood
 - a couple more simple driver fixes

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
  HID: fix a couple of off-by-ones
  HID: logitech: perform bounds checking on device_id early enough
  HID: logitech: fix bounds checking on LED report size
  HID: logitech: Prevent possibility of infinite loop when using /sys interface
  HID: rmi: print an error if F11 is not found instead of stopping the device
  HID: hid-sensor-hub: use devm_ functions consistently
  HID: huion: Use allocated buffer for DMA
  HID: huion: Fail on parameter retrieval errors
parents e9d99a1d 4ab25786
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -28,7 +28,7 @@
static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc,
static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc,
		unsigned int *rsize)
		unsigned int *rsize)
{
{
	if (*rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
	if (*rsize >= 18 && rdesc[11] == 0x3c && rdesc[12] == 0x02) {
		hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n");
		hid_info(hdev, "fixing up Cherry Cymotion report descriptor\n");
		rdesc[11] = rdesc[16] = 0xff;
		rdesc[11] = rdesc[16] = 0xff;
		rdesc[12] = rdesc[17] = 0x03;
		rdesc[12] = rdesc[17] = 0x03;
+78 −50
Original line number Original line Diff line number Diff line
@@ -84,6 +84,15 @@ static const __u8 huion_tablet_rdesc_template[] = {
	0xC0                    /*  End Collection                          */
	0xC0                    /*  End Collection                          */
};
};


/* Parameter indices */
enum huion_prm {
	HUION_PRM_X_LM		= 1,
	HUION_PRM_Y_LM		= 2,
	HUION_PRM_PRESSURE_LM	= 4,
	HUION_PRM_RESOLUTION	= 5,
	HUION_PRM_NUM
};

/* Driver data */
/* Driver data */
struct huion_drvdata {
struct huion_drvdata {
	__u8 *rdesc;
	__u8 *rdesc;
@@ -115,7 +124,12 @@ static int huion_tablet_enable(struct hid_device *hdev)
	int rc;
	int rc;
	struct usb_device *usb_dev = hid_to_usb_dev(hdev);
	struct usb_device *usb_dev = hid_to_usb_dev(hdev);
	struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
	struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
	__le16 buf[6];
	__le16 *buf = NULL;
	size_t len;
	s32 params[HUION_PH_ID_NUM];
	s32 resolution;
	__u8 *p;
	s32 v;


	/*
	/*
	 * Read string descriptor containing tablet parameters. The specific
	 * Read string descriptor containing tablet parameters. The specific
@@ -123,28 +137,38 @@ static int huion_tablet_enable(struct hid_device *hdev)
	 * driver traffic.
	 * driver traffic.
	 * NOTE: This enables fully-functional tablet mode.
	 * NOTE: This enables fully-functional tablet mode.
	 */
	 */
	len = HUION_PRM_NUM * sizeof(*buf);
	buf = kmalloc(len, GFP_KERNEL);
	if (buf == NULL) {
		hid_err(hdev, "failed to allocate parameter buffer\n");
		rc = -ENOMEM;
		goto cleanup;
	}
	rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
	rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
				(USB_DT_STRING << 8) + 0x64,
				(USB_DT_STRING << 8) + 0x64,
				0x0409, buf, sizeof(buf),
				0x0409, buf, len,
				USB_CTRL_GET_TIMEOUT);
				USB_CTRL_GET_TIMEOUT);
	if (rc == -EPIPE)
	if (rc == -EPIPE) {
		hid_warn(hdev, "device parameters not found\n");
		hid_err(hdev, "device parameters not found\n");
	else if (rc < 0)
		rc = -ENODEV;
		hid_warn(hdev, "failed to get device parameters: %d\n", rc);
		goto cleanup;
	else if (rc != sizeof(buf))
	} else if (rc < 0) {
		hid_warn(hdev, "invalid device parameters\n");
		hid_err(hdev, "failed to get device parameters: %d\n", rc);
	else {
		rc = -ENODEV;
		s32 params[HUION_PH_ID_NUM];
		goto cleanup;
		s32 resolution;
	} else if (rc != len) {
		__u8 *p;
		hid_err(hdev, "invalid device parameters\n");
		s32 v;
		rc = -ENODEV;
		goto cleanup;
	}


	/* Extract device parameters */
	/* Extract device parameters */
		params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[1]);
	params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[HUION_PRM_X_LM]);
		params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[2]);
	params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[HUION_PRM_Y_LM]);
		params[HUION_PH_ID_PRESSURE_LM] = le16_to_cpu(buf[4]);
	params[HUION_PH_ID_PRESSURE_LM] =
		resolution = le16_to_cpu(buf[5]);
		le16_to_cpu(buf[HUION_PRM_PRESSURE_LM]);
	resolution = le16_to_cpu(buf[HUION_PRM_RESOLUTION]);
	if (resolution == 0) {
	if (resolution == 0) {
		params[HUION_PH_ID_X_PM] = 0;
		params[HUION_PH_ID_X_PM] = 0;
		params[HUION_PH_ID_Y_PM] = 0;
		params[HUION_PH_ID_Y_PM] = 0;
@@ -161,7 +185,8 @@ static int huion_tablet_enable(struct hid_device *hdev)
				GFP_KERNEL);
				GFP_KERNEL);
	if (drvdata->rdesc == NULL) {
	if (drvdata->rdesc == NULL) {
		hid_err(hdev, "failed to allocate fixed rdesc\n");
		hid_err(hdev, "failed to allocate fixed rdesc\n");
			return -ENOMEM;
		rc = -ENOMEM;
		goto cleanup;
	}
	}
	drvdata->rsize = sizeof(huion_tablet_rdesc_template);
	drvdata->rsize = sizeof(huion_tablet_rdesc_template);


@@ -179,9 +204,12 @@ static int huion_tablet_enable(struct hid_device *hdev)
			p++;
			p++;
		}
		}
	}
	}
	}


	return 0;
	rc = 0;

cleanup:
	kfree(buf);
	return rc;
}
}


static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id)
static int huion_probe(struct hid_device *hdev, const struct hid_device_id *id)
+1 −1
Original line number Original line Diff line number Diff line
@@ -300,7 +300,7 @@ static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc,
		 *   - change the button usage range to 4-7 for the extra
		 *   - change the button usage range to 4-7 for the extra
		 *     buttons
		 *     buttons
		 */
		 */
		if (*rsize >= 74 &&
		if (*rsize >= 75 &&
			rdesc[61] == 0x05 && rdesc[62] == 0x08 &&
			rdesc[61] == 0x05 && rdesc[62] == 0x08 &&
			rdesc[63] == 0x19 && rdesc[64] == 0x08 &&
			rdesc[63] == 0x19 && rdesc[64] == 0x08 &&
			rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
			rdesc[65] == 0x29 && rdesc[66] == 0x0f &&
+2 −2
Original line number Original line Diff line number Diff line
@@ -345,14 +345,14 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
	struct usb_device_descriptor *udesc;
	struct usb_device_descriptor *udesc;
	__u16 bcdDevice, rev_maj, rev_min;
	__u16 bcdDevice, rev_maj, rev_min;


	if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
	if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 &&
			rdesc[84] == 0x8c && rdesc[85] == 0x02) {
			rdesc[84] == 0x8c && rdesc[85] == 0x02) {
		hid_info(hdev,
		hid_info(hdev,
			 "fixing up Logitech keyboard report descriptor\n");
			 "fixing up Logitech keyboard report descriptor\n");
		rdesc[84] = rdesc[89] = 0x4d;
		rdesc[84] = rdesc[89] = 0x4d;
		rdesc[85] = rdesc[90] = 0x10;
		rdesc[85] = rdesc[90] = 0x10;
	}
	}
	if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 50 &&
	if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 51 &&
			rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
			rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
			rdesc[49] == 0x81 && rdesc[50] == 0x06) {
			rdesc[49] == 0x81 && rdesc[50] == 0x06) {
		hid_info(hdev,
		hid_info(hdev,
+2 −2
Original line number Original line Diff line number Diff line
@@ -451,13 +451,13 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
	drv_data = hid_get_drvdata(hid);
	drv_data = hid_get_drvdata(hid);
	if (!drv_data) {
	if (!drv_data) {
		hid_err(hid, "Private driver data not found!\n");
		hid_err(hid, "Private driver data not found!\n");
		return 0;
		return -EINVAL;
	}
	}


	entry = drv_data->device_props;
	entry = drv_data->device_props;
	if (!entry) {
	if (!entry) {
		hid_err(hid, "Device properties not found!\n");
		hid_err(hid, "Device properties not found!\n");
		return 0;
		return -EINVAL;
	}
	}


	if (range == 0)
	if (range == 0)
Loading