From patchwork Tue Dec 31 17:36:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aditya Garg X-Patchwork-Id: 854456 Received: from PNZPR01CU001.outbound.protection.outlook.com (mail-centralindiaazolkn19011029.outbound.protection.outlook.com [52.103.68.29]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9BB6E42A8C; Tue, 31 Dec 2024 17:36:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.103.68.29 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735666569; cv=fail; b=b3GCaEhkDmg1kLfhT3MZ7lCbLGX7EQJLhTx0BpkU0UiFQSLqT/VQY0MwZCOlUjwZBAY0mN+Xp++fDVIBpqxt7u8fbsV8rJq0qns8qJvo3yIN2i6tueUCs+PuDSUaIH7QjjdyVzKIc0Y/18J+cjBeYRJN8VG2lF1+30JV88aJv2Q= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1735666569; c=relaxed/simple; bh=3mz6Axn8y/+plncvXp/+66j7MYDyHlf4AYZpWN7weFg=; h=From:To:CC:Subject:Date:Message-ID:References:In-Reply-To: Content-Type:MIME-Version; b=PtEX21sGBZ/Y4XEQHR8XhoRKC2GHAtw95/P6JNL2iMllZsmyFZNkeNJLSyLjyw14UJD5QWl6bqBvSdWBfSR5jlhJSpLuf+lyHJvj5OqULhkXqKpG7DkJz1kqEOg8mb1dOQJ1UkuoFNayFXNNNNZrRZvr5J5B4Wwpa/u09FQL9Fs= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=live.com; spf=pass smtp.mailfrom=live.com; dkim=pass (2048-bit key) header.d=live.com header.i=@live.com header.b=MxSiPPDL; arc=fail smtp.client-ip=52.103.68.29 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=live.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=live.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=live.com header.i=@live.com header.b="MxSiPPDL" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=uNON09VtJgLlpTa+0hkeSvIogle8q6P/5/N88CvFAdx27m2KeY2Nor7CfCuK3LVhd3PrN2ULo/D/TAPofbVSCJiH+mChP5NHebVdq/ril4xKUtC3bCimnCwwzHedXpqX4VTe5InzQMbrk2/4dgHvm947S7kzsdZuT2YjO68OEwCxiHACO5AWw3fblUT2wkVZG/JSJt083tFB/vjUCH4705NdfG96XicEfsx6DUyrd1B0pEUvG8CQzKZy+fxvco9rcRuC/ZIs64eZR3Cgq1sCL/0uC15/WQV1JyiFJMmxTGBWFwh6SCzoh8PZzNfMHJvDI18draRoKzfC2CTUKuWlTg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=1VBoik1et6ZCxTD6sE8zAbSU02w5p31wr/Vj6VJ2+EQ=; b=LaDAsIek2QdT58ORygBVL64cfGG9m3cihcbtHjoKp6fcw1BEXJJ7uXlZ016idiiEe4VmEJoE5/Hs0Z47meIYSHXxeqJS7ZHJ+Qy1CQj5jMQVhp2UV/mNqSybuepEP6jV2SLmv/f8vCkwMqodMdbmlM0rOgcjoZ+u+sBkxXZOh5aMnDCvRxwN6oc9j6TEluAmXIQj6rGZV/6abQsNq+hLyTQW0hCR8L/T01fqYh1iwUHLVQO9uV9ow5fuj4Xc0t0ZH8CFQdCx9BjXtEKikEqVSUzloBsk+S96pUMdtWvQXB7Nj3pGRm7+YGCWTt1GuaJaNHBHlcL1bbTSBiN86TnYdA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=live.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=1VBoik1et6ZCxTD6sE8zAbSU02w5p31wr/Vj6VJ2+EQ=; b=MxSiPPDL7lnnIZb5Dp06tywGGlIJ0+mxSgg/MgLIfRKTQfqndGbyKGCRGJiFA0Ik1OAbu3RqwLuMHID3HNId+6KbEjXCeCA9lonnlrMAGF3V6kKkq/+75I5vgst/131YE6cZuo99ZzvCjKGjAIm8/IlkzjS3BdrYOJ7asmDSWWZDVo9kGsfRUQq08cwUAy58m9135hYV1szhqum5qfOci1z62MhxZOLQh4V9YSe3477sVB0ocnsiQs3awOU4Az00ggPfH922DPN59hSiRAYrXWtHjg+BHCpsFvWUmIhiCXtATzsjg/PD+8chqwaCoSpdVFfUx//k7F1I1OxMwPwvAQ== Received: from PN3PR01MB7728.INDPRD01.PROD.OUTLOOK.COM (2603:1096:c01:cd::12) by MAXPR01MB4261.INDPRD01.PROD.OUTLOOK.COM (2603:1096:a01:8::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8293.20; Tue, 31 Dec 2024 17:36:03 +0000 Received: from PN3PR01MB7728.INDPRD01.PROD.OUTLOOK.COM ([fe80::d3b7:2498:cd95:5d06]) by PN3PR01MB7728.INDPRD01.PROD.OUTLOOK.COM ([fe80::d3b7:2498:cd95:5d06%4]) with mapi id 15.20.8314.012; Tue, 31 Dec 2024 17:36:03 +0000 From: Aditya Garg To: "jkosina@suse.cz" , Jiri Kosina , Benjamin Tissoires , "bentiss@kernel.org" CC: Kerem Karabay , Orlando Chamberlain , "linux-input@vger.kernel.org" , Linux Kernel Mailing List Subject: [PATCH v2 3/4] HID: hid-appletb-kbd: add support for fn toggle between media and function mode Thread-Topic: [PATCH v2 3/4] HID: hid-appletb-kbd: add support for fn toggle between media and function mode Thread-Index: AQHbW6p2kmozRkQSh06ZIEJXS4FGsA== Date: Tue, 31 Dec 2024 17:36:02 +0000 Message-ID: References: In-Reply-To: Accept-Language: en-IN, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-ms-publictraffictype: Email x-ms-traffictypediagnostic: PN3PR01MB7728:EE_|MAXPR01MB4261:EE_ x-ms-office365-filtering-correlation-id: cecccd3b-9602-480d-f5a1-08dd29c1990a x-microsoft-antispam: BCL:0; ARA:14566002|19110799003|15080799006|8062599003|7092599003|8060799006|461199028|440099028|3412199025|102099032; x-microsoft-antispam-message-info: Pw8VNQHgadkV3+A3STWhuVPqZU6gGDBIK8kNFbJLIOEKRZ1vfUtUrcr+LHEiKRugLMcoR04m9JYW8QXWe8QJW5cNxTNw9mFk5DYNcY3dr4MT7cT9vj2/uMMB1sDysw8YNk07XcnXnpok/9yipjREFsNODIiTVCiITYzcI/tUsE+ACi43kq23qJLwpFkLqesJhddHQlghTXwLbsJQIiGyFiswvPw4mfBptRRfoUBGVEcSrV7rsrpa5WfClBi141xNK4vwDJDFNol/NF4nEemZTGJMVkv4nkLnQ61Qz1YqhKfwjem61F4z95Og5D00HeIy10Mn5TVOo1SMAHGjuUbOiWqeg0UtALsd7GxkVvw05EZ817XCT/6MpEBADXAHkBfnnJAepJHP6BTdykgkP3HRYwan5BnMbxez/jPVxwmWkF9Y+KYNHoZswG0aI1OrtZ8hxlD1hHsbHEEOVYdsH0gdzHTammkFHDFVk0CkHebBcTqrEyAILfLPGnRI0PnP9yJgh/PSzN93rIjsPyp/GhwzxWFhwsPECQLwLqfT3TlmsIy0sfP5W8Y92dT1qzUqrmNSD01aMVyMu3+077CYtkWd0dIQp+u4ZYRILBgQlL8UEFy8kELIPbG9vwH5APXofd3COj6OpPfTd/MFvUvJ2sfEFQTVE2NEUYJyPYgio9hlmMWjefdpNUc3S7FtgLYgfVrQelIo1yc7xAnpxPzp3BxE5XxpolSsN76wem4/u0o8Bxw6LEjNYM6Wum4tNqK9RLN9enH6VnOWGZO6D+hbIh6GbuBESyXxk/a01MU4y8t+XM7CEegF6Hk7RGNREiI1oeNTicv/CEjEBd8OPQ9A63SMRpbPvryxfVi7FNQhd+Ksx5CpXkB3oNyx5zfvtN6q+ubii0sApmw06tiVFBP4C8rkAw5npUzyMXoxUPTHfioHdL3k3QxqVdwDVPeKzP+SGySeNy7MJGacOiIImrye8qezAcszY+Mr8UmHgjYhDx5iRJVp3af541fOmDbin0JD5c3ucXfeNfkGXJ1od2aFWFyzVQf5aYGIJEaSc6uqwLrECkpfxZ9xmhcI3K6XrZmhdWJ65Wf0OAw0idQWL8kXPI3aXQ== x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: h835CnYIY3S5LkLiBDiTritrDlB8s1UIVGjmqvzOjLMW8Sd95EuKbEk4SSS0WBEPmErzi50A1r6l5rfkaEZ346MVzFwbXQUB8LrBcWBqyfE68j+nDvugVlED9Tv4IHgNdEpg3UXSxzd5wPcByOTtRQlhln6G63UzDtOKXzrE9SZfsa2lzNBrPEv5Pi7j8s8SvbCp4deg+FU1u0KW23j4HTHNADWiPuWSUdkAANz1ue/2bFONvQApQZWKEi8qCszAxIV5AbM6MfWaNeTs73AjWauB71RZYHMi5DGqLhywUN90bZzs9hPdnzCEyZiryJ67+NisX7k+fRsRxkyWjt5CmZkrC7AK9Pu0ziGLxW/YfNVE/rFDnZ0iZJUyXaUxknitVPXZQga7q9Y2Hrwk3HExvf9hP484AGHL5eTdQTmBRJdTNmUVYYk7vp2hz1J5d2sS0uJb0RP/NtvzmWl+tDgcn44LOTfgNeNZf0cmsFdPgmkduJAlXwWfZ6gnHRhSVDvwxg0Gyzbe40Tp3P3KuDOziVWwhHpWKzIgqtprDnKkFZWXt8QUGmkDvfHA8RZgxyWDq7SMLqrwc9TvKYLJklX/xW40JLJJGN4Y/3wgOKFOcEYEFJrxSWyKSb9P9ZzZDrZ814bUl3KecV0KgIgeGGedhziwQq99yzhbqXiwyIsEOYAj9/IWU0xSzJPFjR0kTlnXxy5UvGc9sREZdscH3NZiIeVuGyJWzV+d/qWuTJker8348o39LQU33mGjrQrtTrpPbiARTQyPLC526+tsAxESEvdMzZtY/IX+5lair+WLLmSTHlz2RUHM4eAfyHIjlAjnirjlNDsmB6rLF68bvLdBvsJyJG3quwN1utVaWAziWgww3X4hDU9x46ISssmg3a0spbko4wV2dIdjnfH+2tchCzwSNL+j8XKafwdFvNxY+cor5hUKMzPcTJOPMRf0D9xxx/fN1Px9MF1lJqYx3F6nL5Rz27qcjtOXbUY6zGy+hsLByMaxdc/+wOw3MMZrgDMlY6YMFvAVz0Gs+YMsJPRUUSdsBFvr3EKG4hLhPhyJFieRMNdWoyy8wTSQsM3QLyTdDRiLv6sRgjCKa3tOjaCTfHUittC+628hqC6QP6Q7V2io6KKwBkpd45yshuJvCE0O9WmaEOoNLVWovw9zqbc3k3+rHTAntc2Q8Mu26Vfvhu/vBCNmuXrEXQuD6/7jW7oY31x6Afp9ybtjSSHgPjKHoLp/BICai3ibW4oNesItOuZRR2nGU2TvEsnnFwB6225Nupyvq7ozXPSvRCvGmB3YqVJRjQ614eLqjHq0xNd9yvOS1UXsKO3L5ox0e0+4qNVm Content-ID: <3E7F56D00E5CA64AA2D4D0A5858729C1@INDPRD01.PROD.OUTLOOK.COM> Precedence: bulk X-Mailing-List: linux-input@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-OriginatorOrg: sct-15-20-7719-20-msonline-outlook-ae5c4.templateTenant X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: PN3PR01MB7728.INDPRD01.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-Network-Message-Id: cecccd3b-9602-480d-f5a1-08dd29c1990a X-MS-Exchange-CrossTenant-rms-persistedconsumerorg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-originalarrivaltime: 31 Dec 2024 17:36:02.9487 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-Transport-CrossTenantHeadersStamped: MAXPR01MB4261 From: Aditya Garg This patch adds support for the switching between the Media and Function keys on the touchbar by pressing the Fn key on Apple Internal Keyboard. Signed-off-by: Aditya Garg --- drivers/hid/hid-appletb-kbd.c | 128 ++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/drivers/hid/hid-appletb-kbd.c b/drivers/hid/hid-appletb-kbd.c index 80c87396f..de5770500 100644 --- a/drivers/hid/hid-appletb-kbd.c +++ b/drivers/hid/hid-appletb-kbd.c @@ -26,6 +26,8 @@ #define APPLETB_KBD_MODE_OFF 3 #define APPLETB_KBD_MODE_MAX APPLETB_KBD_MODE_OFF +#define APPLETB_DEVID_KEYBOARD 1 + #define HID_USAGE_MODE 0x00ff0004 static int appletb_tb_def_mode = APPLETB_KBD_MODE_SPCL; @@ -35,11 +37,18 @@ MODULE_PARM_DESC(mode, "Default touchbar mode:\n" " 1 - function-keys\n" " [2] - special keys"); +static bool appletb_tb_fn_toggle = true; +module_param_named(fntoggle, appletb_tb_fn_toggle, bool, 0644); +MODULE_PARM_DESC(fntoggle, "Switch between Fn and media controls on pressing Fn key"); + struct appletb_kbd { struct hid_field *mode_field; u8 saved_mode; u8 current_mode; + struct input_handler inp_handler; + struct input_handle kbd_handle; + }; static const struct key_entry appletb_kbd_keymap[] = { @@ -172,6 +181,75 @@ static int appletb_kbd_hid_event(struct hid_device *hdev, struct hid_field *fiel return kbd->current_mode == APPLETB_KBD_MODE_OFF; } +static void appletb_kbd_inp_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ + struct appletb_kbd *kbd = handle->private; + + if (type == EV_KEY && code == KEY_FN && appletb_tb_fn_toggle) { + if (value == 1) { + kbd->saved_mode = kbd->current_mode; + if (kbd->current_mode == APPLETB_KBD_MODE_SPCL) + appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_FN); + else if (kbd->current_mode == APPLETB_KBD_MODE_FN) + appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_SPCL); + } else if (value == 0) { + if (kbd->saved_mode != kbd->current_mode) + appletb_kbd_set_mode(kbd, kbd->saved_mode); + } + } +} + +static int appletb_kbd_inp_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +{ + struct appletb_kbd *kbd = handler->private; + struct input_handle *handle; + int rc; + + if (id->driver_info == APPLETB_DEVID_KEYBOARD) { + handle = &kbd->kbd_handle; + handle->name = "tbkbd"; + } else { + return -ENOENT; + } + + if (handle->dev) + return -EEXIST; + + handle->open = 0; + handle->dev = input_get_device(dev); + handle->handler = handler; + handle->private = kbd; + + rc = input_register_handle(handle); + if (rc) + goto err_free_dev; + + rc = input_open_device(handle); + if (rc) + goto err_unregister_handle; + + return 0; + + err_unregister_handle: + input_unregister_handle(handle); + err_free_dev: + input_put_device(handle->dev); + handle->dev = NULL; + return rc; +} + +static void appletb_kbd_inp_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + + input_put_device(handle->dev); + handle->dev = NULL; +} + static int appletb_kbd_input_configured(struct hid_device *hdev, struct hid_input *hidinput) { int idx; @@ -195,6 +273,40 @@ static int appletb_kbd_input_configured(struct hid_device *hdev, struct hid_inpu return 0; } +static const struct input_device_id appletb_kbd_input_devices[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_BUS | + INPUT_DEVICE_ID_MATCH_VENDOR | + INPUT_DEVICE_ID_MATCH_KEYBIT, + .bustype = BUS_USB, + .vendor = USB_VENDOR_ID_APPLE, + .keybit = { [BIT_WORD(KEY_FN)] = BIT_MASK(KEY_FN) }, + .driver_info = APPLETB_DEVID_KEYBOARD, + }, + { } +}; + +static bool appletb_kbd_match_internal_device(struct input_handler *handler, + struct input_dev *inp_dev) +{ + struct device *dev = &inp_dev->dev; + + /* in kernel: dev && !is_usb_device(dev) */ + while (dev && !(dev->type && dev->type->name && + !strcmp(dev->type->name, "usb_device"))) + dev = dev->parent; + + /* + * Apple labels all their internal keyboards and trackpads as such, + * instead of maintaining an ever expanding list of product-id's we + * just look at the device's product name. + */ + if (dev) + return !!strstr(to_usb_device(dev)->product, "Internal Keyboard"); + + return false; +} + static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id *id) { struct appletb_kbd *kbd; @@ -227,6 +339,20 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id goto stop_hw; } + kbd->inp_handler.event = appletb_kbd_inp_event; + kbd->inp_handler.connect = appletb_kbd_inp_connect; + kbd->inp_handler.disconnect = appletb_kbd_inp_disconnect; + kbd->inp_handler.name = "appletb"; + kbd->inp_handler.id_table = appletb_kbd_input_devices; + kbd->inp_handler.match = appletb_kbd_match_internal_device; + kbd->inp_handler.private = kbd; + + ret = input_register_handler(&kbd->inp_handler); + if (ret) { + dev_err_probe(dev, ret, "Unable to register keyboard handler\n"); + goto close_hw; + } + ret = appletb_kbd_set_mode(kbd, appletb_tb_def_mode); if (ret) { dev_err_probe(dev, ret, "Failed to set touchbar mode\n"); @@ -250,6 +376,8 @@ static void appletb_kbd_remove(struct hid_device *hdev) appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF); + input_unregister_handler(&kbd->inp_handler); + hid_hw_close(hdev); hid_hw_stop(hdev); }