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

 - syzkaller-reported error handling fixes in various drivers, from
   various people

 - increase of HID report buffer size to 8K, which is apparently needed
   by certain modern devices

 - a few new device-ID-specific fixes / quirks

 - battery charging status reporting fix in logitech-hidpp, from Filipe
   Laíns

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
  HID: hid-bigbenff: fix race condition for scheduled work during removal
  HID: hid-bigbenff: call hid_hw_stop() in case of error
  HID: hid-bigbenff: fix general protection fault caused by double kfree
  HID: i2c-hid: add Trekstor Surfbook E11B to descriptor override
  HID: alps: Fix an error handling path in 'alps_input_configured()'
  HID: hiddev: Fix race in in hiddev_disconnect()
  HID: core: increase HID report buffer size to 8KiB
  HID: core: fix off-by-one memset in hid_report_raw_event()
  HID: apple: Add support for recent firmware on Magic Keyboards
  HID: ite: Only bind to keyboard USB interface on Acer SW5-012 keyboard dock
  HID: logitech-hidpp: BatteryVoltage: only read chargeStatus if extPower is active
parents e46bfaba 4eb1b01d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -730,7 +730,7 @@ static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)
	if (data->has_sp) {
		input2 = input_allocate_device();
		if (!input2) {
			input_free_device(input2);
			ret = -ENOMEM;
			goto exit;
		}

+2 −1
Original line number Diff line number Diff line
@@ -340,7 +340,8 @@ static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
		unsigned long **bit, int *max)
{
	if (usage->hid == (HID_UP_CUSTOM | 0x0003) ||
			usage->hid == (HID_UP_MSVENDOR | 0x0003)) {
			usage->hid == (HID_UP_MSVENDOR | 0x0003) ||
			usage->hid == (HID_UP_HPVENDOR2 | 0x0003)) {
		/* The fn key on Apple USB keyboards */
		set_bit(EV_REP, hi->input->evbit);
		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
+24 −7
Original line number Diff line number Diff line
@@ -174,6 +174,7 @@ static __u8 pid0902_rdesc_fixed[] = {
struct bigben_device {
	struct hid_device *hid;
	struct hid_report *report;
	bool removed;
	u8 led_state;         /* LED1 = 1 .. LED4 = 8 */
	u8 right_motor_on;    /* right motor off/on 0/1 */
	u8 left_motor_force;  /* left motor force 0-255 */
@@ -190,6 +191,9 @@ static void bigben_worker(struct work_struct *work)
		struct bigben_device, worker);
	struct hid_field *report_field = bigben->report->field[0];

	if (bigben->removed)
		return;

	if (bigben->work_led) {
		bigben->work_led = false;
		report_field->value[0] = 0x01; /* 1 = led message */
@@ -220,10 +224,16 @@ static void bigben_worker(struct work_struct *work)
static int hid_bigben_play_effect(struct input_dev *dev, void *data,
			 struct ff_effect *effect)
{
	struct bigben_device *bigben = data;
	struct hid_device *hid = input_get_drvdata(dev);
	struct bigben_device *bigben = hid_get_drvdata(hid);
	u8 right_motor_on;
	u8 left_motor_force;

	if (!bigben) {
		hid_err(hid, "no device data\n");
		return 0;
	}

	if (effect->type != FF_RUMBLE)
		return 0;

@@ -298,8 +308,8 @@ static void bigben_remove(struct hid_device *hid)
{
	struct bigben_device *bigben = hid_get_drvdata(hid);

	bigben->removed = true;
	cancel_work_sync(&bigben->worker);
	hid_hw_close(hid);
	hid_hw_stop(hid);
}

@@ -319,6 +329,7 @@ static int bigben_probe(struct hid_device *hid,
		return -ENOMEM;
	hid_set_drvdata(hid, bigben);
	bigben->hid = hid;
	bigben->removed = false;

	error = hid_parse(hid);
	if (error) {
@@ -341,10 +352,10 @@ static int bigben_probe(struct hid_device *hid,

	INIT_WORK(&bigben->worker, bigben_worker);

	error = input_ff_create_memless(hidinput->input, bigben,
	error = input_ff_create_memless(hidinput->input, NULL,
		hid_bigben_play_effect);
	if (error)
		return error;
		goto error_hw_stop;

	name_sz = strlen(dev_name(&hid->dev)) + strlen(":red:bigben#") + 1;

@@ -354,8 +365,10 @@ static int bigben_probe(struct hid_device *hid,
			sizeof(struct led_classdev) + name_sz,
			GFP_KERNEL
		);
		if (!led)
			return -ENOMEM;
		if (!led) {
			error = -ENOMEM;
			goto error_hw_stop;
		}
		name = (void *)(&led[1]);
		snprintf(name, name_sz,
			"%s:red:bigben%d",
@@ -369,7 +382,7 @@ static int bigben_probe(struct hid_device *hid,
		bigben->leds[n] = led;
		error = devm_led_classdev_register(&hid->dev, led);
		if (error)
			return error;
			goto error_hw_stop;
	}

	/* initial state: LED1 is on, no rumble effect */
@@ -383,6 +396,10 @@ static int bigben_probe(struct hid_device *hid,
	hid_info(hid, "LED and force feedback support for BigBen gamepad\n");

	return 0;

error_hw_stop:
	hid_hw_stop(hid);
	return error;
}

static __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc,
+3 −1
Original line number Diff line number Diff line
@@ -1741,7 +1741,9 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,

	rsize = ((report->size - 1) >> 3) + 1;

	if (rsize > HID_MAX_BUFFER_SIZE)
	if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
		rsize = HID_MAX_BUFFER_SIZE - 1;
	else if (rsize > HID_MAX_BUFFER_SIZE)
		rsize = HID_MAX_BUFFER_SIZE;

	if (csize < rsize) {
+3 −2
Original line number Diff line number Diff line
@@ -41,7 +41,8 @@ static const struct hid_device_id ite_devices[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
	/* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS,
	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
		     USB_VENDOR_ID_SYNAPTICS,
		     USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
	{ }
};
Loading