Commit 26b88fba authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull HID updates from Jiri Kosina:
 "Highlights:

   - support for USI style pens (Tero Kristo, Mika Westerberg)

   - quirk for devices that need inverted X/Y axes (Alistair Francis)

   - small core code cleanups and deduplication (Benjamin Tissoires)

   - Apple Magic Keyboard support improvements (José Expósito, Alex
     Henrie, Benjamin Berg)

   - locking performance improvement for hidraw code (André Almeida)

   - PM wakeup support for i2c-hid driver (Matthias Kaehlcke

   - new driver to support for LetSketch device (Hans de Goede)

   - proper batter reporting for hid-magicmouse USB-connected devices
     (José Expósito)"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (32 commits)
  HID: magicmouse: Fix an error handling path in magicmouse_probe()
  HID: address kernel-doc warnings
  HID: intel-ish-hid: ishtp-fw-loader: Fix a kernel-doc formatting issue
  HID: intel-ish-hid: ipc: Specify no cache snooping on TGL and ADL
  HID: hid-uclogic-params: Invalid parameter check in uclogic_params_frame_init_v1_buttonpad
  HID: hid-uclogic-params: Invalid parameter check in uclogic_params_huion_init
  HID: hid-uclogic-params: Invalid parameter check in uclogic_params_get_str_desc
  HID: hid-uclogic-params: Invalid parameter check in uclogic_params_init
  HID: Add new Letsketch tablet driver
  HID: apple: Add Magic Keyboard 2021 with fingerprint reader FN key mapping
  HID: apple: Add 2021 magic keyboard FN key mapping
  HID: magicmouse: set Magic Trackpad 2021 name
  HID: magicmouse: set device name when it has been personalized
  HID: apple: Add 2021 Magic Keyboard with number pad
  HID: apple: Add 2021 Magic Keyboard with fingerprint reader
  HID: i2c-hid-of: Expose the touchscreen-inverted properties
  HID: quirks: Allow inverting the absolute X/Y values
  HID: hidraw: Replace hidraw device table mutex with a rwsem
  HID: thrustmaster use swap() to make code cleaner
  HID: debug: Add USI usages
  ...
parents 4a110907 cd598d21
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@ device-specific compatible properties, which should be used in addition to the
- vdd-supply: phandle of the regulator that provides the supply voltage.
- post-power-on-delay-ms: time required by the device after enabling its regulators
  or powering it on, before it is ready for communication.
- touchscreen-inverted-x: See touchscreen.txt
- touchscreen-inverted-y: See touchscreen.txt

Example:

+13 −0
Original line number Diff line number Diff line
@@ -8542,6 +8542,12 @@ F: drivers/hid/
F:	include/linux/hid*
F:	include/uapi/linux/hid*
HID LOGITECH DRIVERS
R:	Filipe Laíns <lains@riseup.net>
L:	linux-input@vger.kernel.org
S:	Maintained
F:	drivers/hid/hid-logitech-*
HID PLAYSTATION DRIVER
M:	Roderick Colenbrander <roderick.colenbrander@sony.com>
L:	linux-input@vger.kernel.org
@@ -10804,6 +10810,13 @@ S: Maintained
W:	http://legousb.sourceforge.net/
F:	drivers/usb/misc/legousbtower.c
LETSKETCH HID TABLET DRIVER
M:	Hans de Goede <hdegoede@redhat.com>
L:	linux-input@vger.kernel.org
S:	Maintained
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git
F:	drivers/hid/hid-letsketch.c
LG LAPTOP EXTRAS
M:	Matan Ziv-Av <matan@svgalib.org>
L:	platform-driver-x86@vger.kernel.org
+14 −0
Original line number Diff line number Diff line
@@ -558,6 +558,20 @@ config HID_LENOVO
	- ThinkPad Compact Bluetooth Keyboard with TrackPoint (supports Fn keys)
	- ThinkPad Compact USB Keyboard with TrackPoint (supports Fn keys)

config HID_LETSKETCH
	tristate "Letsketch WP9620N tablets"
	depends on USB_HID
	help
	  Driver for the LetSketch / VSON WP9620N drawing tablet. This
	  drawing tablet is also sold under other brand names such as Case U,
	  presumably this driver will work for all of them. But it has only been
	  tested with a LetSketch WP9620N model.

	  These tablets also work without a special HID driver, but then only
	  part of the active area works and both the pad and stylus buttons are
	  hardwired to special key-combos. E.g. the 2 stylus buttons send right
	  mouse clicks / resp. "e" key presses.

config HID_LOGITECH
	tristate "Logitech devices"
	depends on USB_HID
+1 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o
obj-$(CONFIG_HID_KYE)		+= hid-kye.o
obj-$(CONFIG_HID_LCPOWER)	+= hid-lcpower.o
obj-$(CONFIG_HID_LENOVO)	+= hid-lenovo.o
obj-$(CONFIG_HID_LETSKETCH)	+= hid-letsketch.o
obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
obj-$(CONFIG_HID_LOGITECH)	+= hid-lg-g15.o
obj-$(CONFIG_HID_LOGITECH_DJ)	+= hid-logitech-dj.o
+133 −13
Original line number Diff line number Diff line
@@ -16,24 +16,28 @@

#include <linux/device.h>
#include <linux/hid.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/timer.h>

#include "hid-ids.h"

#define APPLE_RDESC_JIS		0x0001
#define APPLE_IGNORE_MOUSE	0x0002
#define APPLE_HAS_FN		0x0004
/* 0x0008 reserved, was: APPLE_HIDDEV */
#define APPLE_ISO_TILDE_QUIRK	0x0010
#define APPLE_MIGHTYMOUSE	0x0020
#define APPLE_INVERT_HWHEEL	0x0040
/* 0x0080 reserved, was: APPLE_IGNORE_HIDINPUT */
#define APPLE_NUMLOCK_EMULATION	0x0100
#define APPLE_RDESC_JIS		BIT(0)
#define APPLE_IGNORE_MOUSE	BIT(1)
#define APPLE_HAS_FN		BIT(2)
/* BIT(3) reserved, was: APPLE_HIDDEV */
#define APPLE_ISO_TILDE_QUIRK	BIT(4)
#define APPLE_MIGHTYMOUSE	BIT(5)
#define APPLE_INVERT_HWHEEL	BIT(6)
/* BIT(7) reserved, was: APPLE_IGNORE_HIDINPUT */
#define APPLE_NUMLOCK_EMULATION	BIT(8)
#define APPLE_RDESC_BATTERY	BIT(9)

#define APPLE_FLAG_FKEY		0x01

#define HID_COUNTRY_INTERNATIONAL_ISO	13
#define APPLE_BATTERY_TIMEOUT_MS	60000

static unsigned int fnmode = 1;
module_param(fnmode, uint, 0644);
@@ -58,10 +62,12 @@ MODULE_PARM_DESC(swap_fn_leftctrl, "Swap the Fn and left Control keys. "
		"[0] = as-is, Mac layout, 1 = swapped, PC layout)");

struct apple_sc {
	struct hid_device *hdev;
	unsigned long quirks;
	unsigned int fn_on;
	unsigned int fn_found;
	DECLARE_BITMAP(pressed_numlock, KEY_CNT);
	struct timer_list battery_timer;
};

struct apple_key_translation {
@@ -70,6 +76,28 @@ struct apple_key_translation {
	u8 flags;
};

static const struct apple_key_translation apple2021_fn_keys[] = {
	{ KEY_BACKSPACE, KEY_DELETE },
	{ KEY_ENTER,	KEY_INSERT },
	{ KEY_F1,	KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
	{ KEY_F2,	KEY_BRIGHTNESSUP,   APPLE_FLAG_FKEY },
	{ KEY_F3,	KEY_SCALE,          APPLE_FLAG_FKEY },
	{ KEY_F4,	KEY_SEARCH,         APPLE_FLAG_FKEY },
	{ KEY_F5,	KEY_MICMUTE,        APPLE_FLAG_FKEY },
	{ KEY_F6,	KEY_SLEEP,          APPLE_FLAG_FKEY },
	{ KEY_F7,	KEY_PREVIOUSSONG,   APPLE_FLAG_FKEY },
	{ KEY_F8,	KEY_PLAYPAUSE,      APPLE_FLAG_FKEY },
	{ KEY_F9,	KEY_NEXTSONG,       APPLE_FLAG_FKEY },
	{ KEY_F10,	KEY_MUTE,           APPLE_FLAG_FKEY },
	{ KEY_F11,	KEY_VOLUMEDOWN,     APPLE_FLAG_FKEY },
	{ KEY_F12,	KEY_VOLUMEUP,       APPLE_FLAG_FKEY },
	{ KEY_UP,	KEY_PAGEUP },
	{ KEY_DOWN,	KEY_PAGEDOWN },
	{ KEY_LEFT,	KEY_HOME },
	{ KEY_RIGHT,	KEY_END },
	{ }
};

static const struct apple_key_translation macbookair_fn_keys[] = {
	{ KEY_BACKSPACE, KEY_DELETE },
	{ KEY_ENTER,	KEY_INSERT },
@@ -214,7 +242,11 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
	}

	if (fnmode) {
		if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
		if (hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 ||
		    hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 ||
		    hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021)
			table = apple2021_fn_keys;
		else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
				hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS)
			table = macbookair_fn_keys;
		else if (hid->product < 0x21d || hid->product >= 0x300)
@@ -333,6 +365,43 @@ static int apple_event(struct hid_device *hdev, struct hid_field *field,
	return 0;
}

static int apple_fetch_battery(struct hid_device *hdev)
{
#ifdef CONFIG_HID_BATTERY_STRENGTH
	struct apple_sc *asc = hid_get_drvdata(hdev);
	struct hid_report_enum *report_enum;
	struct hid_report *report;

	if (!(asc->quirks & APPLE_RDESC_BATTERY) || !hdev->battery)
		return -1;

	report_enum = &hdev->report_enum[hdev->battery_report_type];
	report = report_enum->report_id_hash[hdev->battery_report_id];

	if (!report || report->maxfield < 1)
		return -1;

	if (hdev->battery_capacity == hdev->battery_max)
		return -1;

	hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
	return 0;
#else
	return -1;
#endif
}

static void apple_battery_timer_tick(struct timer_list *t)
{
	struct apple_sc *asc = from_timer(asc, t, battery_timer);
	struct hid_device *hdev = asc->hdev;

	if (apple_fetch_battery(hdev) == 0) {
		mod_timer(&asc->battery_timer,
			  jiffies + msecs_to_jiffies(APPLE_BATTERY_TIMEOUT_MS));
	}
}

/*
 * MacBook JIS keyboard has wrong logical maximum
 * Magic Keyboard JIS has wrong logical maximum
@@ -354,6 +423,30 @@ static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
			 "fixing up MacBook JIS keyboard report descriptor\n");
		rdesc[53] = rdesc[59] = 0xe7;
	}

	/*
	 * Change the usage from:
	 *   0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1)  0
	 *   0x09, 0x0b,       // Usage (Vendor Usage 0x0b)           3
	 * To:
	 *   0x05, 0x01,       // Usage Page (Generic Desktop)        0
	 *   0x09, 0x06,       // Usage (Keyboard)                    2
	 */
	if ((asc->quirks & APPLE_RDESC_BATTERY) && *rsize == 83 &&
	    rdesc[46] == 0x84 && rdesc[58] == 0x85) {
		hid_info(hdev,
			 "fixing up Magic Keyboard battery report descriptor\n");
		*rsize = *rsize - 1;
		rdesc = kmemdup(rdesc + 1, *rsize, GFP_KERNEL);
		if (!rdesc)
			return NULL;

		rdesc[0] = 0x05;
		rdesc[1] = 0x01;
		rdesc[2] = 0x09;
		rdesc[3] = 0x06;
	}

	return rdesc;
}

@@ -376,6 +469,9 @@ static void apple_setup_input(struct input_dev *input)
	for (trans = apple_iso_keyboard; trans->from; trans++)
		set_bit(trans->to, input->keybit);

	for (trans = apple2021_fn_keys; trans->from; trans++)
		set_bit(trans->to, input->keybit);

	if (swap_fn_leftctrl) {
		for (trans = swapped_fn_leftctrl_keys; trans->from; trans++)
			set_bit(trans->to, input->keybit);
@@ -428,7 +524,7 @@ static int apple_input_configured(struct hid_device *hdev,

	if ((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) {
		hid_info(hdev, "Fn key not found (Apple Wireless Keyboard clone?), disabling Fn key handling\n");
		asc->quirks = 0;
		asc->quirks &= ~APPLE_HAS_FN;
	}

	return 0;
@@ -447,6 +543,7 @@ static int apple_probe(struct hid_device *hdev,
		return -ENOMEM;
	}

	asc->hdev = hdev;
	asc->quirks = quirks;

	hid_set_drvdata(hdev, asc);
@@ -463,9 +560,23 @@ static int apple_probe(struct hid_device *hdev,
		return ret;
	}

	timer_setup(&asc->battery_timer, apple_battery_timer_tick, 0);
	mod_timer(&asc->battery_timer,
		  jiffies + msecs_to_jiffies(APPLE_BATTERY_TIMEOUT_MS));
	apple_fetch_battery(hdev);

	return 0;
}

static void apple_remove(struct hid_device *hdev)
{
	struct apple_sc *asc = hid_get_drvdata(hdev);

	del_timer_sync(&asc->battery_timer);

	hid_hw_stop(hdev);
}

static const struct hid_device_id apple_devices[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE),
		.driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
@@ -540,11 +651,11 @@ static const struct hid_device_id apple_devices[] = {
	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015),
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY },
	{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015),
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015),
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY },
	{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015),
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
@@ -640,6 +751,14 @@ static const struct hid_device_id apple_devices[] = {
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
	{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021),
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021),
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
	{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021),
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021),
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
	{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021),
		.driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },

	{ }
};
@@ -650,6 +769,7 @@ static struct hid_driver apple_driver = {
	.id_table = apple_devices,
	.report_fixup = apple_report_fixup,
	.probe = apple_probe,
	.remove = apple_remove,
	.event = apple_event,
	.input_mapping = apple_input_mapping,
	.input_mapped = apple_input_mapped,
Loading