Commit fce0d275 authored by Jiri Kosina's avatar Jiri Kosina
Browse files

Merge branch 'for-5.17/apple' into for-linus

- Apple Magic Keyboard support improvements (José Expósito, Alex Henrie,
  Benjamin Berg)
parents 8a2094d6 7f84e243
Loading
Loading
Loading
Loading
+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,
+2 −0
Original line number Diff line number Diff line
@@ -175,6 +175,8 @@
#define USB_DEVICE_ID_APPLE_IRCONTROL4	0x8242
#define USB_DEVICE_ID_APPLE_IRCONTROL5	0x8243
#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021   0x029c
#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021   0x029a
#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021   0x029f

#define USB_VENDOR_ID_ASUS		0x0486
#define USB_DEVICE_ID_ASUS_T91MT	0x0185
+17 −3
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ static bool report_undeciphered;
module_param(report_undeciphered, bool, 0644);
MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event");

#define TRACKPAD2_2021_BT_VERSION 0x110

#define TRACKPAD_REPORT_ID 0x28
#define TRACKPAD2_USB_REPORT_ID 0x02
#define TRACKPAD2_BT_REPORT_ID 0x31
@@ -538,10 +540,22 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
			__set_bit(REL_HWHEEL_HI_RES, input->relbit);
		}
	} else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2) {
		/* setting the device name to ensure the same driver settings
		 * get loaded, whether connected through bluetooth or USB
		/* If the trackpad has been connected to a Mac, the name is
		 * automatically personalized, e.g., "José Expósito's Trackpad".
		 * When connected through Bluetooth, the personalized name is
		 * reported, however, when connected through USB the generic
		 * name is reported.
		 * Set the device name to ensure the same driver settings get
		 * loaded, whether connected through bluetooth or USB.
		 */
		if (hdev->vendor == BT_VENDOR_ID_APPLE) {
			if (input->id.version == TRACKPAD2_2021_BT_VERSION)
				input->name = "Apple Inc. Magic Trackpad";
			else
				input->name = "Apple Inc. Magic Trackpad 2";
		} else { /* USB_VENDOR_ID_APPLE */
			input->name = hdev->name;
		}

		__clear_bit(EV_MSC, input->evbit);
		__clear_bit(BTN_0, input->keybit);
+1 −0
Original line number Diff line number Diff line
@@ -304,6 +304,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021) },
#endif
#if IS_ENABLED(CONFIG_HID_APPLEIR)
	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },