12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
28c19a515SJiri Slaby /*
38c19a515SJiri Slaby * USB HID quirks support for Linux
48c19a515SJiri Slaby *
58c19a515SJiri Slaby * Copyright (c) 1999 Andreas Gal
68c19a515SJiri Slaby * Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
78c19a515SJiri Slaby * Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
88c19a515SJiri Slaby * Copyright (c) 2006-2007 Jiri Kosina
98c19a515SJiri Slaby * Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
109018eacbSPaul Pawlowski * Copyright (c) 2019 Paul Pawlowski <paul@mrarm.io>
118c19a515SJiri Slaby */
128c19a515SJiri Slaby
138c19a515SJiri Slaby /*
148c19a515SJiri Slaby */
158c19a515SJiri Slaby
164291ee30SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
174291ee30SJoe Perches
188c19a515SJiri Slaby #include <linux/device.h>
198c19a515SJiri Slaby #include <linux/hid.h>
206e143293SJosé Expósito #include <linux/jiffies.h>
218c19a515SJiri Slaby #include <linux/module.h>
225a0e3ad6STejun Heo #include <linux/slab.h>
236e143293SJosé Expósito #include <linux/timer.h>
24fa33382cSBryan Cain #include <linux/string.h>
256c89c116SThomas Weißschuh #include <linux/leds.h>
268c19a515SJiri Slaby
278c19a515SJiri Slaby #include "hid-ids.h"
288c19a515SJiri Slaby
297f52ece2SJosé Expósito #define APPLE_RDESC_JIS BIT(0)
307f52ece2SJosé Expósito #define APPLE_IGNORE_MOUSE BIT(1)
317f52ece2SJosé Expósito #define APPLE_HAS_FN BIT(2)
327f52ece2SJosé Expósito /* BIT(3) reserved, was: APPLE_HIDDEV */
337f52ece2SJosé Expósito #define APPLE_ISO_TILDE_QUIRK BIT(4)
347f52ece2SJosé Expósito #define APPLE_MIGHTYMOUSE BIT(5)
357f52ece2SJosé Expósito #define APPLE_INVERT_HWHEEL BIT(6)
367f52ece2SJosé Expósito /* BIT(7) reserved, was: APPLE_IGNORE_HIDINPUT */
377f52ece2SJosé Expósito #define APPLE_NUMLOCK_EMULATION BIT(8)
386e143293SJosé Expósito #define APPLE_RDESC_BATTERY BIT(9)
399018eacbSPaul Pawlowski #define APPLE_BACKLIGHT_CTL BIT(10)
40a0a05054SHilton Chain #define APPLE_IS_NON_APPLE BIT(11)
418c19a515SJiri Slaby
428c19a515SJiri Slaby #define APPLE_FLAG_FKEY 0x01
438c19a515SJiri Slaby
44bd77a0f0SAlex Henrie #define HID_COUNTRY_INTERNATIONAL_ISO 13
456e143293SJosé Expósito #define APPLE_BATTERY_TIMEOUT_MS 60000
46bd77a0f0SAlex Henrie
47fa33382cSBryan Cain static unsigned int fnmode = 3;
488c19a515SJiri Slaby module_param(fnmode, uint, 0644);
498c19a515SJiri Slaby MODULE_PARM_DESC(fnmode, "Mode of fn key on Apple keyboards (0 = disabled, "
50fa33382cSBryan Cain "1 = fkeyslast, 2 = fkeysfirst, [3] = auto)");
518c19a515SJiri Slaby
52d58cf34aSAlex Henrie static int iso_layout = -1;
53d58cf34aSAlex Henrie module_param(iso_layout, int, 0644);
54d58cf34aSAlex Henrie MODULE_PARM_DESC(iso_layout, "Swap the backtick/tilde and greater-than/less-than keys. "
55d58cf34aSAlex Henrie "([-1] = auto, 0 = disabled, 1 = enabled)");
5654a6593dSStefan Glasenhardt
57a94c79bdSJiri Kosina static unsigned int swap_opt_cmd;
5843c83146SNanno Langstraat module_param(swap_opt_cmd, uint, 0644);
5943c83146SNanno Langstraat MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\") keys. "
6043c83146SNanno Langstraat "(For people who want to keep Windows PC keyboard muscle memory. "
6172e49cadSLasse Brun "[0] = as-is, Mac layout. 1 = swapped, Windows layout., 2 = swapped, Swap only left side)");
6243c83146SNanno Langstraat
63fd7b68b7SAditya Garg static unsigned int swap_ctrl_cmd;
64fd7b68b7SAditya Garg module_param(swap_ctrl_cmd, uint, 0644);
65fd7b68b7SAditya Garg MODULE_PARM_DESC(swap_ctrl_cmd, "Swap the Control (\"Ctrl\") and Command (\"Flag\") keys. "
66fd7b68b7SAditya Garg "(For people who are used to Mac shortcuts involving Command instead of Control. "
67fd7b68b7SAditya Garg "[0] = No change. 1 = Swapped.)");
68fd7b68b7SAditya Garg
69346338efSfree5lot static unsigned int swap_fn_leftctrl;
70346338efSfree5lot module_param(swap_fn_leftctrl, uint, 0644);
71346338efSfree5lot MODULE_PARM_DESC(swap_fn_leftctrl, "Swap the Fn and left Control keys. "
72346338efSfree5lot "(For people who want to keep PC keyboard muscle memory. "
73346338efSfree5lot "[0] = as-is, Mac layout, 1 = swapped, PC layout)");
74346338efSfree5lot
75a0a05054SHilton Chain struct apple_non_apple_keyboard {
76a0a05054SHilton Chain char *name;
77a0a05054SHilton Chain };
78a0a05054SHilton Chain
799018eacbSPaul Pawlowski struct apple_sc_backlight {
809018eacbSPaul Pawlowski struct led_classdev cdev;
819018eacbSPaul Pawlowski struct hid_device *hdev;
829018eacbSPaul Pawlowski unsigned short backlight_off, backlight_on_min, backlight_on_max;
839018eacbSPaul Pawlowski };
849018eacbSPaul Pawlowski
858c19a515SJiri Slaby struct apple_sc {
866e143293SJosé Expósito struct hid_device *hdev;
878c19a515SJiri Slaby unsigned long quirks;
888c19a515SJiri Slaby unsigned int fn_on;
89a5d81646SHans de Goede unsigned int fn_found;
908c19a515SJiri Slaby DECLARE_BITMAP(pressed_numlock, KEY_CNT);
916e143293SJosé Expósito struct timer_list battery_timer;
929018eacbSPaul Pawlowski struct apple_sc_backlight *backlight;
938c19a515SJiri Slaby };
948c19a515SJiri Slaby
958c19a515SJiri Slaby struct apple_key_translation {
968c19a515SJiri Slaby u16 from;
978c19a515SJiri Slaby u16 to;
988c19a515SJiri Slaby u8 flags;
998c19a515SJiri Slaby };
1008c19a515SJiri Slaby
1010fea6fe7SJosé Expósito static const struct apple_key_translation magic_keyboard_alu_fn_keys[] = {
1020fea6fe7SJosé Expósito { KEY_BACKSPACE, KEY_DELETE },
1030fea6fe7SJosé Expósito { KEY_ENTER, KEY_INSERT },
1040fea6fe7SJosé Expósito { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
1050fea6fe7SJosé Expósito { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
1060fea6fe7SJosé Expósito { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY },
1070fea6fe7SJosé Expósito { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY },
1080fea6fe7SJosé Expósito { KEY_F6, KEY_NUMLOCK, APPLE_FLAG_FKEY },
1090fea6fe7SJosé Expósito { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
1100fea6fe7SJosé Expósito { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
1110fea6fe7SJosé Expósito { KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY },
1120fea6fe7SJosé Expósito { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY },
1130fea6fe7SJosé Expósito { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
1140fea6fe7SJosé Expósito { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
1150fea6fe7SJosé Expósito { KEY_UP, KEY_PAGEUP },
1160fea6fe7SJosé Expósito { KEY_DOWN, KEY_PAGEDOWN },
1170fea6fe7SJosé Expósito { KEY_LEFT, KEY_HOME },
1180fea6fe7SJosé Expósito { KEY_RIGHT, KEY_END },
1190fea6fe7SJosé Expósito { }
1200fea6fe7SJosé Expósito };
1210fea6fe7SJosé Expósito
122250b369eSJosé Expósito static const struct apple_key_translation magic_keyboard_2015_fn_keys[] = {
123250b369eSJosé Expósito { KEY_BACKSPACE, KEY_DELETE },
124250b369eSJosé Expósito { KEY_ENTER, KEY_INSERT },
125250b369eSJosé Expósito { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
126250b369eSJosé Expósito { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
127250b369eSJosé Expósito { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY },
128250b369eSJosé Expósito { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY },
129250b369eSJosé Expósito { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
130250b369eSJosé Expósito { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
131250b369eSJosé Expósito { KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY },
132250b369eSJosé Expósito { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY },
133250b369eSJosé Expósito { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
134250b369eSJosé Expósito { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
135250b369eSJosé Expósito { KEY_UP, KEY_PAGEUP },
136250b369eSJosé Expósito { KEY_DOWN, KEY_PAGEDOWN },
137250b369eSJosé Expósito { KEY_LEFT, KEY_HOME },
138250b369eSJosé Expósito { KEY_RIGHT, KEY_END },
139250b369eSJosé Expósito { }
140250b369eSJosé Expósito };
141250b369eSJosé Expósito
1429018eacbSPaul Pawlowski struct apple_backlight_config_report {
1439018eacbSPaul Pawlowski u8 report_id;
1449018eacbSPaul Pawlowski u8 version;
1459018eacbSPaul Pawlowski u16 backlight_off, backlight_on_min, backlight_on_max;
1469018eacbSPaul Pawlowski };
1479018eacbSPaul Pawlowski
1489018eacbSPaul Pawlowski struct apple_backlight_set_report {
1499018eacbSPaul Pawlowski u8 report_id;
1509018eacbSPaul Pawlowski u8 version;
1519018eacbSPaul Pawlowski u16 backlight;
1529018eacbSPaul Pawlowski u16 rate;
1539018eacbSPaul Pawlowski };
1549018eacbSPaul Pawlowski
1559018eacbSPaul Pawlowski
156531cb569SBenjamin Berg static const struct apple_key_translation apple2021_fn_keys[] = {
157531cb569SBenjamin Berg { KEY_BACKSPACE, KEY_DELETE },
158531cb569SBenjamin Berg { KEY_ENTER, KEY_INSERT },
159531cb569SBenjamin Berg { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
160531cb569SBenjamin Berg { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
161531cb569SBenjamin Berg { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY },
162531cb569SBenjamin Berg { KEY_F4, KEY_SEARCH, APPLE_FLAG_FKEY },
163531cb569SBenjamin Berg { KEY_F5, KEY_MICMUTE, APPLE_FLAG_FKEY },
164531cb569SBenjamin Berg { KEY_F6, KEY_SLEEP, APPLE_FLAG_FKEY },
165531cb569SBenjamin Berg { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
166531cb569SBenjamin Berg { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
167531cb569SBenjamin Berg { KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY },
168531cb569SBenjamin Berg { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY },
169531cb569SBenjamin Berg { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
170531cb569SBenjamin Berg { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
171531cb569SBenjamin Berg { KEY_UP, KEY_PAGEUP },
172531cb569SBenjamin Berg { KEY_DOWN, KEY_PAGEDOWN },
173531cb569SBenjamin Berg { KEY_LEFT, KEY_HOME },
174531cb569SBenjamin Berg { KEY_RIGHT, KEY_END },
175531cb569SBenjamin Berg { }
176531cb569SBenjamin Berg };
177531cb569SBenjamin Berg
17899b9f758SEdgar (gimli) Hucek static const struct apple_key_translation macbookair_fn_keys[] = {
17999b9f758SEdgar (gimli) Hucek { KEY_BACKSPACE, KEY_DELETE },
18099b9f758SEdgar (gimli) Hucek { KEY_ENTER, KEY_INSERT },
18199b9f758SEdgar (gimli) Hucek { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
18299b9f758SEdgar (gimli) Hucek { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
18399b9f758SEdgar (gimli) Hucek { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY },
18499b9f758SEdgar (gimli) Hucek { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY },
18599b9f758SEdgar (gimli) Hucek { KEY_F6, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
18699b9f758SEdgar (gimli) Hucek { KEY_F7, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
18799b9f758SEdgar (gimli) Hucek { KEY_F8, KEY_NEXTSONG, APPLE_FLAG_FKEY },
18899b9f758SEdgar (gimli) Hucek { KEY_F9, KEY_MUTE, APPLE_FLAG_FKEY },
18999b9f758SEdgar (gimli) Hucek { KEY_F10, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
19099b9f758SEdgar (gimli) Hucek { KEY_F11, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
19199b9f758SEdgar (gimli) Hucek { KEY_F12, KEY_EJECTCD, APPLE_FLAG_FKEY },
19299b9f758SEdgar (gimli) Hucek { KEY_UP, KEY_PAGEUP },
19399b9f758SEdgar (gimli) Hucek { KEY_DOWN, KEY_PAGEDOWN },
19499b9f758SEdgar (gimli) Hucek { KEY_LEFT, KEY_HOME },
19599b9f758SEdgar (gimli) Hucek { KEY_RIGHT, KEY_END },
19699b9f758SEdgar (gimli) Hucek { }
19799b9f758SEdgar (gimli) Hucek };
19899b9f758SEdgar (gimli) Hucek
199c5f09b1bSAditya Garg static const struct apple_key_translation macbookpro_no_esc_fn_keys[] = {
200c5f09b1bSAditya Garg { KEY_BACKSPACE, KEY_DELETE },
201c5f09b1bSAditya Garg { KEY_ENTER, KEY_INSERT },
202c5f09b1bSAditya Garg { KEY_GRAVE, KEY_ESC },
203c5f09b1bSAditya Garg { KEY_1, KEY_F1 },
204c5f09b1bSAditya Garg { KEY_2, KEY_F2 },
205c5f09b1bSAditya Garg { KEY_3, KEY_F3 },
206c5f09b1bSAditya Garg { KEY_4, KEY_F4 },
207c5f09b1bSAditya Garg { KEY_5, KEY_F5 },
208c5f09b1bSAditya Garg { KEY_6, KEY_F6 },
209c5f09b1bSAditya Garg { KEY_7, KEY_F7 },
210c5f09b1bSAditya Garg { KEY_8, KEY_F8 },
211c5f09b1bSAditya Garg { KEY_9, KEY_F9 },
212c5f09b1bSAditya Garg { KEY_0, KEY_F10 },
213c5f09b1bSAditya Garg { KEY_MINUS, KEY_F11 },
214c5f09b1bSAditya Garg { KEY_EQUAL, KEY_F12 },
215c5f09b1bSAditya Garg { KEY_UP, KEY_PAGEUP },
216c5f09b1bSAditya Garg { KEY_DOWN, KEY_PAGEDOWN },
217c5f09b1bSAditya Garg { KEY_LEFT, KEY_HOME },
218c5f09b1bSAditya Garg { KEY_RIGHT, KEY_END },
219c5f09b1bSAditya Garg { }
220c5f09b1bSAditya Garg };
221c5f09b1bSAditya Garg
222c5f09b1bSAditya Garg static const struct apple_key_translation macbookpro_dedicated_esc_fn_keys[] = {
223c5f09b1bSAditya Garg { KEY_BACKSPACE, KEY_DELETE },
224c5f09b1bSAditya Garg { KEY_ENTER, KEY_INSERT },
225c5f09b1bSAditya Garg { KEY_1, KEY_F1 },
226c5f09b1bSAditya Garg { KEY_2, KEY_F2 },
227c5f09b1bSAditya Garg { KEY_3, KEY_F3 },
228c5f09b1bSAditya Garg { KEY_4, KEY_F4 },
229c5f09b1bSAditya Garg { KEY_5, KEY_F5 },
230c5f09b1bSAditya Garg { KEY_6, KEY_F6 },
231c5f09b1bSAditya Garg { KEY_7, KEY_F7 },
232c5f09b1bSAditya Garg { KEY_8, KEY_F8 },
233c5f09b1bSAditya Garg { KEY_9, KEY_F9 },
234c5f09b1bSAditya Garg { KEY_0, KEY_F10 },
235c5f09b1bSAditya Garg { KEY_MINUS, KEY_F11 },
236c5f09b1bSAditya Garg { KEY_EQUAL, KEY_F12 },
237c5f09b1bSAditya Garg { KEY_UP, KEY_PAGEUP },
238c5f09b1bSAditya Garg { KEY_DOWN, KEY_PAGEDOWN },
239c5f09b1bSAditya Garg { KEY_LEFT, KEY_HOME },
240c5f09b1bSAditya Garg { KEY_RIGHT, KEY_END },
241c5f09b1bSAditya Garg { }
242c5f09b1bSAditya Garg };
243c5f09b1bSAditya Garg
244b2ddd54eSPaul Collins static const struct apple_key_translation apple_fn_keys[] = {
2458c19a515SJiri Slaby { KEY_BACKSPACE, KEY_DELETE },
246437184aeSHenrik Rydberg { KEY_ENTER, KEY_INSERT },
2478c19a515SJiri Slaby { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
2488c19a515SJiri Slaby { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
249437184aeSHenrik Rydberg { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY },
250437184aeSHenrik Rydberg { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY },
2518c19a515SJiri Slaby { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY },
2528c19a515SJiri Slaby { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY },
2538c19a515SJiri Slaby { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY },
2548c19a515SJiri Slaby { KEY_F8, KEY_PLAYPAUSE, APPLE_FLAG_FKEY },
2558c19a515SJiri Slaby { KEY_F9, KEY_NEXTSONG, APPLE_FLAG_FKEY },
2568c19a515SJiri Slaby { KEY_F10, KEY_MUTE, APPLE_FLAG_FKEY },
2578c19a515SJiri Slaby { KEY_F11, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
2588c19a515SJiri Slaby { KEY_F12, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
2598c19a515SJiri Slaby { KEY_UP, KEY_PAGEUP },
2608c19a515SJiri Slaby { KEY_DOWN, KEY_PAGEDOWN },
2618c19a515SJiri Slaby { KEY_LEFT, KEY_HOME },
2628c19a515SJiri Slaby { KEY_RIGHT, KEY_END },
2638c19a515SJiri Slaby { }
2648c19a515SJiri Slaby };
2658c19a515SJiri Slaby
266b2ddd54eSPaul Collins static const struct apple_key_translation powerbook_fn_keys[] = {
2678c19a515SJiri Slaby { KEY_BACKSPACE, KEY_DELETE },
2688c19a515SJiri Slaby { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
2698c19a515SJiri Slaby { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY },
2708c19a515SJiri Slaby { KEY_F3, KEY_MUTE, APPLE_FLAG_FKEY },
2718c19a515SJiri Slaby { KEY_F4, KEY_VOLUMEDOWN, APPLE_FLAG_FKEY },
2728c19a515SJiri Slaby { KEY_F5, KEY_VOLUMEUP, APPLE_FLAG_FKEY },
2738c19a515SJiri Slaby { KEY_F6, KEY_NUMLOCK, APPLE_FLAG_FKEY },
2748c19a515SJiri Slaby { KEY_F7, KEY_SWITCHVIDEOMODE, APPLE_FLAG_FKEY },
2758c19a515SJiri Slaby { KEY_F8, KEY_KBDILLUMTOGGLE, APPLE_FLAG_FKEY },
2768c19a515SJiri Slaby { KEY_F9, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY },
2778c19a515SJiri Slaby { KEY_F10, KEY_KBDILLUMUP, APPLE_FLAG_FKEY },
2788c19a515SJiri Slaby { KEY_UP, KEY_PAGEUP },
2798c19a515SJiri Slaby { KEY_DOWN, KEY_PAGEDOWN },
2808c19a515SJiri Slaby { KEY_LEFT, KEY_HOME },
2818c19a515SJiri Slaby { KEY_RIGHT, KEY_END },
2828c19a515SJiri Slaby { }
2838c19a515SJiri Slaby };
2848c19a515SJiri Slaby
285b2ddd54eSPaul Collins static const struct apple_key_translation powerbook_numlock_keys[] = {
2868c19a515SJiri Slaby { KEY_J, KEY_KP1 },
2878c19a515SJiri Slaby { KEY_K, KEY_KP2 },
2888c19a515SJiri Slaby { KEY_L, KEY_KP3 },
2898c19a515SJiri Slaby { KEY_U, KEY_KP4 },
2908c19a515SJiri Slaby { KEY_I, KEY_KP5 },
2918c19a515SJiri Slaby { KEY_O, KEY_KP6 },
2928c19a515SJiri Slaby { KEY_7, KEY_KP7 },
2938c19a515SJiri Slaby { KEY_8, KEY_KP8 },
2948c19a515SJiri Slaby { KEY_9, KEY_KP9 },
2958c19a515SJiri Slaby { KEY_M, KEY_KP0 },
2968c19a515SJiri Slaby { KEY_DOT, KEY_KPDOT },
2978c19a515SJiri Slaby { KEY_SLASH, KEY_KPPLUS },
2988c19a515SJiri Slaby { KEY_SEMICOLON, KEY_KPMINUS },
2998c19a515SJiri Slaby { KEY_P, KEY_KPASTERISK },
3008c19a515SJiri Slaby { KEY_MINUS, KEY_KPEQUAL },
3018c19a515SJiri Slaby { KEY_0, KEY_KPSLASH },
3028c19a515SJiri Slaby { KEY_F6, KEY_NUMLOCK },
3038c19a515SJiri Slaby { KEY_KPENTER, KEY_KPENTER },
3048c19a515SJiri Slaby { KEY_BACKSPACE, KEY_BACKSPACE },
3058c19a515SJiri Slaby { }
3068c19a515SJiri Slaby };
3078c19a515SJiri Slaby
308b2ddd54eSPaul Collins static const struct apple_key_translation apple_iso_keyboard[] = {
3098c19a515SJiri Slaby { KEY_GRAVE, KEY_102ND },
3108c19a515SJiri Slaby { KEY_102ND, KEY_GRAVE },
3118c19a515SJiri Slaby { }
3128c19a515SJiri Slaby };
3138c19a515SJiri Slaby
31443c83146SNanno Langstraat static const struct apple_key_translation swapped_option_cmd_keys[] = {
31543c83146SNanno Langstraat { KEY_LEFTALT, KEY_LEFTMETA },
31643c83146SNanno Langstraat { KEY_LEFTMETA, KEY_LEFTALT },
31743c83146SNanno Langstraat { KEY_RIGHTALT, KEY_RIGHTMETA },
31843c83146SNanno Langstraat { KEY_RIGHTMETA, KEY_RIGHTALT },
31943c83146SNanno Langstraat { }
32043c83146SNanno Langstraat };
32143c83146SNanno Langstraat
32272e49cadSLasse Brun static const struct apple_key_translation swapped_option_cmd_left_keys[] = {
32372e49cadSLasse Brun { KEY_LEFTALT, KEY_LEFTMETA },
32472e49cadSLasse Brun { KEY_LEFTMETA, KEY_LEFTALT },
32572e49cadSLasse Brun { }
32672e49cadSLasse Brun };
32772e49cadSLasse Brun
328fd7b68b7SAditya Garg static const struct apple_key_translation swapped_ctrl_cmd_keys[] = {
329fd7b68b7SAditya Garg { KEY_LEFTCTRL, KEY_LEFTMETA },
330fd7b68b7SAditya Garg { KEY_LEFTMETA, KEY_LEFTCTRL },
331fd7b68b7SAditya Garg { KEY_RIGHTCTRL, KEY_RIGHTMETA },
332fd7b68b7SAditya Garg { KEY_RIGHTMETA, KEY_RIGHTCTRL },
333fd7b68b7SAditya Garg { }
334fd7b68b7SAditya Garg };
335fd7b68b7SAditya Garg
336346338efSfree5lot static const struct apple_key_translation swapped_fn_leftctrl_keys[] = {
337346338efSfree5lot { KEY_FN, KEY_LEFTCTRL },
3385476fcf7SKerem Karabay { KEY_LEFTCTRL, KEY_FN },
339346338efSfree5lot { }
340346338efSfree5lot };
341346338efSfree5lot
342a0a05054SHilton Chain static const struct apple_non_apple_keyboard non_apple_keyboards[] = {
343a0a05054SHilton Chain { "SONiX USB DEVICE" },
344a0a05054SHilton Chain { "Keychron" },
34520afcc46SHilton Chain { "AONE" },
346c4444d87SNils Tonnaett { "GANSS" },
347c4444d87SNils Tonnaett { "Hailuck" },
3486b3507b8SYihong Cao { "Jamesdonkey" },
3496b3507b8SYihong Cao { "A3R" },
350a0a05054SHilton Chain };
351a0a05054SHilton Chain
apple_is_non_apple_keyboard(struct hid_device * hdev)352a0a05054SHilton Chain static bool apple_is_non_apple_keyboard(struct hid_device *hdev)
353a0a05054SHilton Chain {
354a0a05054SHilton Chain int i;
355a0a05054SHilton Chain
356a0a05054SHilton Chain for (i = 0; i < ARRAY_SIZE(non_apple_keyboards); i++) {
357a0a05054SHilton Chain char *non_apple = non_apple_keyboards[i].name;
358a0a05054SHilton Chain
359a0a05054SHilton Chain if (strncmp(hdev->name, non_apple, strlen(non_apple)) == 0)
360a0a05054SHilton Chain return true;
361a0a05054SHilton Chain }
362a0a05054SHilton Chain
363a0a05054SHilton Chain return false;
364a0a05054SHilton Chain }
365a0a05054SHilton Chain
apple_setup_key_translation(struct input_dev * input,const struct apple_key_translation * table)366*62485737SAlex Henrie static bool apple_is_omoton_kb066(struct hid_device *hdev)
367*62485737SAlex Henrie {
368*62485737SAlex Henrie return hdev->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI &&
369*62485737SAlex Henrie strcmp(hdev->name, "Bluetooth Keyboard") == 0;
370*62485737SAlex Henrie }
371*62485737SAlex Henrie
372f1d1b3a9SJosé Expósito static inline void apple_setup_key_translation(struct input_dev *input,
373f1d1b3a9SJosé Expósito const struct apple_key_translation *table)
374f1d1b3a9SJosé Expósito {
apple_find_translation(const struct apple_key_translation * table,u16 from)375f1d1b3a9SJosé Expósito const struct apple_key_translation *trans;
376f1d1b3a9SJosé Expósito
377f1d1b3a9SJosé Expósito for (trans = table; trans->from; trans++)
378f1d1b3a9SJosé Expósito set_bit(trans->to, input->keybit);
379f1d1b3a9SJosé Expósito }
380f1d1b3a9SJosé Expósito
381b2ddd54eSPaul Collins static const struct apple_key_translation *apple_find_translation(
382b2ddd54eSPaul Collins const struct apple_key_translation *table, u16 from)
3838c19a515SJiri Slaby {
384b2ddd54eSPaul Collins const struct apple_key_translation *trans;
3858c19a515SJiri Slaby
3868c19a515SJiri Slaby /* Look for the translation */
3878c19a515SJiri Slaby for (trans = table; trans->from; trans++)
input_event_with_scancode(struct input_dev * input,__u8 type,__u16 code,unsigned int hid,__s32 value)3888c19a515SJiri Slaby if (trans->from == from)
3898c19a515SJiri Slaby return trans;
3908c19a515SJiri Slaby
3918c19a515SJiri Slaby return NULL;
3928c19a515SJiri Slaby }
3938c19a515SJiri Slaby
3943b41fb40SVincent Lefevre static void input_event_with_scancode(struct input_dev *input,
3953b41fb40SVincent Lefevre __u8 type, __u16 code, unsigned int hid, __s32 value)
3963b41fb40SVincent Lefevre {
hidinput_apple_event(struct hid_device * hid,struct input_dev * input,struct hid_usage * usage,__s32 value)3973b41fb40SVincent Lefevre if (type == EV_KEY &&
3983b41fb40SVincent Lefevre (!test_bit(code, input->key)) == value)
3993b41fb40SVincent Lefevre input_event(input, EV_MSC, MSC_SCAN, hid);
4003b41fb40SVincent Lefevre input_event(input, type, code, value);
4013b41fb40SVincent Lefevre }
4023b41fb40SVincent Lefevre
4038c19a515SJiri Slaby static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
4048c19a515SJiri Slaby struct hid_usage *usage, __s32 value)
4058c19a515SJiri Slaby {
4068c19a515SJiri Slaby struct apple_sc *asc = hid_get_drvdata(hid);
407a4bc6926SJiri Kosina const struct apple_key_translation *trans, *table;
408aec256d0SJoao Moreno bool do_translate;
4095476fcf7SKerem Karabay u16 code = usage->code;
410fa33382cSBryan Cain unsigned int real_fnmode;
4118c19a515SJiri Slaby
412fa33382cSBryan Cain if (fnmode == 3) {
413a0a05054SHilton Chain real_fnmode = (asc->quirks & APPLE_IS_NON_APPLE) ? 2 : 1;
414fa33382cSBryan Cain } else {
415fa33382cSBryan Cain real_fnmode = fnmode;
416fa33382cSBryan Cain }
417fa33382cSBryan Cain
4185476fcf7SKerem Karabay if (swap_fn_leftctrl) {
4195476fcf7SKerem Karabay trans = apple_find_translation(swapped_fn_leftctrl_keys, code);
4205476fcf7SKerem Karabay
4215476fcf7SKerem Karabay if (trans)
4225476fcf7SKerem Karabay code = trans->to;
4235476fcf7SKerem Karabay }
4245476fcf7SKerem Karabay
4255476fcf7SKerem Karabay if (iso_layout > 0 || (iso_layout < 0 && (asc->quirks & APPLE_ISO_TILDE_QUIRK) &&
4265476fcf7SKerem Karabay hid->country == HID_COUNTRY_INTERNATIONAL_ISO)) {
4275476fcf7SKerem Karabay trans = apple_find_translation(apple_iso_keyboard, code);
4285476fcf7SKerem Karabay
4295476fcf7SKerem Karabay if (trans)
4305476fcf7SKerem Karabay code = trans->to;
4315476fcf7SKerem Karabay }
4325476fcf7SKerem Karabay
4335476fcf7SKerem Karabay if (swap_opt_cmd) {
43472e49cadSLasse Brun if (swap_opt_cmd == 2)
43572e49cadSLasse Brun trans = apple_find_translation(swapped_option_cmd_left_keys, code);
43672e49cadSLasse Brun else
4375476fcf7SKerem Karabay trans = apple_find_translation(swapped_option_cmd_keys, code);
4385476fcf7SKerem Karabay
4395476fcf7SKerem Karabay if (trans)
4405476fcf7SKerem Karabay code = trans->to;
4415476fcf7SKerem Karabay }
4425476fcf7SKerem Karabay
443fd7b68b7SAditya Garg if (swap_ctrl_cmd) {
444fd7b68b7SAditya Garg trans = apple_find_translation(swapped_ctrl_cmd_keys, code);
445fd7b68b7SAditya Garg
446fd7b68b7SAditya Garg if (trans)
447fd7b68b7SAditya Garg code = trans->to;
448fd7b68b7SAditya Garg }
449fd7b68b7SAditya Garg
4505476fcf7SKerem Karabay if (code == KEY_FN)
4515476fcf7SKerem Karabay asc->fn_on = !!value;
4525476fcf7SKerem Karabay
453fa33382cSBryan Cain if (real_fnmode) {
4540fea6fe7SJosé Expósito if (hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI ||
4550fea6fe7SJosé Expósito hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO ||
4560fea6fe7SJosé Expósito hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS ||
4570fea6fe7SJosé Expósito hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI ||
4580fea6fe7SJosé Expósito hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO ||
4590fea6fe7SJosé Expósito hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS ||
4600fea6fe7SJosé Expósito hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI ||
4610fea6fe7SJosé Expósito hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO ||
4620fea6fe7SJosé Expósito hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS)
4630fea6fe7SJosé Expósito table = magic_keyboard_alu_fn_keys;
464250b369eSJosé Expósito else if (hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015 ||
465250b369eSJosé Expósito hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015)
466250b369eSJosé Expósito table = magic_keyboard_2015_fn_keys;
4670fea6fe7SJosé Expósito else if (hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 ||
46868eddb06SIevgen Vovk hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024 ||
4697f84e243SJosé Expósito hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 ||
4707f84e243SJosé Expósito hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021)
471531cb569SBenjamin Berg table = apple2021_fn_keys;
472c5f09b1bSAditya Garg else if (hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132 ||
473c5f09b1bSAditya Garg hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680 ||
474c5f09b1bSAditya Garg hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213)
475c5f09b1bSAditya Garg table = macbookpro_no_esc_fn_keys;
476c5f09b1bSAditya Garg else if (hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K ||
477c5f09b1bSAditya Garg hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223 ||
478c5f09b1bSAditya Garg hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F)
479c5f09b1bSAditya Garg table = macbookpro_dedicated_esc_fn_keys;
480c5f09b1bSAditya Garg else if (hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K ||
481c5f09b1bSAditya Garg hid->product == USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K)
482c5f09b1bSAditya Garg table = apple_fn_keys;
483531cb569SBenjamin Berg else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
484a4bc6926SJiri Kosina hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS)
485a4bc6926SJiri Kosina table = macbookair_fn_keys;
486a4bc6926SJiri Kosina else if (hid->product < 0x21d || hid->product >= 0x300)
487a4bc6926SJiri Kosina table = powerbook_fn_keys;
488a4bc6926SJiri Kosina else
489a4bc6926SJiri Kosina table = apple_fn_keys;
490a4bc6926SJiri Kosina
4915476fcf7SKerem Karabay trans = apple_find_translation(table, code);
49299b9f758SEdgar (gimli) Hucek
4938c19a515SJiri Slaby if (trans) {
4945476fcf7SKerem Karabay bool from_is_set = test_bit(trans->from, input->key);
4955476fcf7SKerem Karabay bool to_is_set = test_bit(trans->to, input->key);
4965476fcf7SKerem Karabay
4975476fcf7SKerem Karabay if (from_is_set)
498aec256d0SJoao Moreno code = trans->from;
4995476fcf7SKerem Karabay else if (to_is_set)
500aec256d0SJoao Moreno code = trans->to;
501aec256d0SJoao Moreno
5025476fcf7SKerem Karabay if (!(from_is_set || to_is_set)) {
503aec256d0SJoao Moreno if (trans->flags & APPLE_FLAG_FKEY) {
504fa33382cSBryan Cain switch (real_fnmode) {
505aec256d0SJoao Moreno case 1:
506aec256d0SJoao Moreno do_translate = !asc->fn_on;
507aec256d0SJoao Moreno break;
508aec256d0SJoao Moreno case 2:
5098c19a515SJiri Slaby do_translate = asc->fn_on;
510aec256d0SJoao Moreno break;
511aec256d0SJoao Moreno default:
512aec256d0SJoao Moreno /* should never happen */
513aec256d0SJoao Moreno do_translate = false;
5148c19a515SJiri Slaby }
515aec256d0SJoao Moreno } else {
516aec256d0SJoao Moreno do_translate = asc->fn_on;
517aec256d0SJoao Moreno }
518aec256d0SJoao Moreno
5195476fcf7SKerem Karabay if (do_translate)
5205476fcf7SKerem Karabay code = trans->to;
521aec256d0SJoao Moreno }
5228c19a515SJiri Slaby }
5238c19a515SJiri Slaby
5248c19a515SJiri Slaby if (asc->quirks & APPLE_NUMLOCK_EMULATION &&
5255476fcf7SKerem Karabay (test_bit(code, asc->pressed_numlock) ||
5268c19a515SJiri Slaby test_bit(LED_NUML, input->led))) {
5275476fcf7SKerem Karabay trans = apple_find_translation(powerbook_numlock_keys, code);
5288c19a515SJiri Slaby
5298c19a515SJiri Slaby if (trans) {
5308c19a515SJiri Slaby if (value)
5315476fcf7SKerem Karabay set_bit(code, asc->pressed_numlock);
5328c19a515SJiri Slaby else
5335476fcf7SKerem Karabay clear_bit(code, asc->pressed_numlock);
5348c19a515SJiri Slaby
5355476fcf7SKerem Karabay code = trans->to;
5368c19a515SJiri Slaby }
5375476fcf7SKerem Karabay }
5385476fcf7SKerem Karabay }
5395476fcf7SKerem Karabay
5405476fcf7SKerem Karabay if (usage->code != code) {
5415476fcf7SKerem Karabay input_event_with_scancode(input, usage->type, code, usage->hid, value);
apple_event(struct hid_device * hdev,struct hid_field * field,struct hid_usage * usage,__s32 value)5428c19a515SJiri Slaby
5438c19a515SJiri Slaby return 1;
5448c19a515SJiri Slaby }
545346338efSfree5lot
5468c19a515SJiri Slaby return 0;
5478c19a515SJiri Slaby }
5488c19a515SJiri Slaby
5498c19a515SJiri Slaby static int apple_event(struct hid_device *hdev, struct hid_field *field,
5508c19a515SJiri Slaby struct hid_usage *usage, __s32 value)
5518c19a515SJiri Slaby {
5528c19a515SJiri Slaby struct apple_sc *asc = hid_get_drvdata(hdev);
5538c19a515SJiri Slaby
5548c19a515SJiri Slaby if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
5558c19a515SJiri Slaby !usage->type)
5568c19a515SJiri Slaby return 0;
5578c19a515SJiri Slaby
5588c19a515SJiri Slaby if ((asc->quirks & APPLE_INVERT_HWHEEL) &&
5598c19a515SJiri Slaby usage->code == REL_HWHEEL) {
5603b41fb40SVincent Lefevre input_event_with_scancode(field->hidinput->input, usage->type,
5613b41fb40SVincent Lefevre usage->code, usage->hid, -value);
5628c19a515SJiri Slaby return 1;
5638c19a515SJiri Slaby }
5648c19a515SJiri Slaby
5658c19a515SJiri Slaby if ((asc->quirks & APPLE_HAS_FN) &&
5668c19a515SJiri Slaby hidinput_apple_event(hdev, field->hidinput->input,
apple_fetch_battery(struct hid_device * hdev)5678c19a515SJiri Slaby usage, value))
5688c19a515SJiri Slaby return 1;
5698c19a515SJiri Slaby
5708c19a515SJiri Slaby
5718c19a515SJiri Slaby return 0;
5728c19a515SJiri Slaby }
5738c19a515SJiri Slaby
5746e143293SJosé Expósito static int apple_fetch_battery(struct hid_device *hdev)
5756e143293SJosé Expósito {
5766e143293SJosé Expósito #ifdef CONFIG_HID_BATTERY_STRENGTH
5776e143293SJosé Expósito struct apple_sc *asc = hid_get_drvdata(hdev);
5786e143293SJosé Expósito struct hid_report_enum *report_enum;
5796e143293SJosé Expósito struct hid_report *report;
5806e143293SJosé Expósito
5816e143293SJosé Expósito if (!(asc->quirks & APPLE_RDESC_BATTERY) || !hdev->battery)
5826e143293SJosé Expósito return -1;
5836e143293SJosé Expósito
5846e143293SJosé Expósito report_enum = &hdev->report_enum[hdev->battery_report_type];
5856e143293SJosé Expósito report = report_enum->report_id_hash[hdev->battery_report_id];
5866e143293SJosé Expósito
5876e143293SJosé Expósito if (!report || report->maxfield < 1)
5886e143293SJosé Expósito return -1;
5896e143293SJosé Expósito
5906e143293SJosé Expósito if (hdev->battery_capacity == hdev->battery_max)
5916e143293SJosé Expósito return -1;
5926e143293SJosé Expósito
apple_battery_timer_tick(struct timer_list * t)5936e143293SJosé Expósito hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
5946e143293SJosé Expósito return 0;
5956e143293SJosé Expósito #else
5966e143293SJosé Expósito return -1;
5976e143293SJosé Expósito #endif
5986e143293SJosé Expósito }
5996e143293SJosé Expósito
6006e143293SJosé Expósito static void apple_battery_timer_tick(struct timer_list *t)
6016e143293SJosé Expósito {
6026e143293SJosé Expósito struct apple_sc *asc = from_timer(asc, t, battery_timer);
6036e143293SJosé Expósito struct hid_device *hdev = asc->hdev;
6046e143293SJosé Expósito
6056e143293SJosé Expósito if (apple_fetch_battery(hdev) == 0) {
6066e143293SJosé Expósito mod_timer(&asc->battery_timer,
6076e143293SJosé Expósito jiffies + msecs_to_jiffies(APPLE_BATTERY_TIMEOUT_MS));
apple_report_fixup(struct hid_device * hdev,__u8 * rdesc,unsigned int * rsize)6086e143293SJosé Expósito }
6096e143293SJosé Expósito }
6106e143293SJosé Expósito
6118c19a515SJiri Slaby /*
6128c19a515SJiri Slaby * MacBook JIS keyboard has wrong logical maximum
61367fd71baSMizuho Mori * Magic Keyboard JIS has wrong logical maximum
6148c19a515SJiri Slaby */
61573e4008dSNikolai Kondrashov static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
61673e4008dSNikolai Kondrashov unsigned int *rsize)
6178c19a515SJiri Slaby {
6188c19a515SJiri Slaby struct apple_sc *asc = hid_get_drvdata(hdev);
6198c19a515SJiri Slaby
62067fd71baSMizuho Mori if(*rsize >=71 && rdesc[70] == 0x65 && rdesc[64] == 0x65) {
62167fd71baSMizuho Mori hid_info(hdev,
62267fd71baSMizuho Mori "fixing up Magic Keyboard JIS report descriptor\n");
62367fd71baSMizuho Mori rdesc[64] = rdesc[70] = 0xe7;
62467fd71baSMizuho Mori }
62567fd71baSMizuho Mori
62673e4008dSNikolai Kondrashov if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 &&
6278c19a515SJiri Slaby rdesc[53] == 0x65 && rdesc[59] == 0x65) {
6284291ee30SJoe Perches hid_info(hdev,
6294291ee30SJoe Perches "fixing up MacBook JIS keyboard report descriptor\n");
6308c19a515SJiri Slaby rdesc[53] = rdesc[59] = 0xe7;
6318c19a515SJiri Slaby }
6326e143293SJosé Expósito
6336e143293SJosé Expósito /*
6346e143293SJosé Expósito * Change the usage from:
6356e143293SJosé Expósito * 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 0
6366e143293SJosé Expósito * 0x09, 0x0b, // Usage (Vendor Usage 0x0b) 3
6376e143293SJosé Expósito * To:
6386e143293SJosé Expósito * 0x05, 0x01, // Usage Page (Generic Desktop) 0
6396e143293SJosé Expósito * 0x09, 0x06, // Usage (Keyboard) 2
6406e143293SJosé Expósito */
6416e143293SJosé Expósito if ((asc->quirks & APPLE_RDESC_BATTERY) && *rsize == 83 &&
6426e143293SJosé Expósito rdesc[46] == 0x84 && rdesc[58] == 0x85) {
6436e143293SJosé Expósito hid_info(hdev,
6446e143293SJosé Expósito "fixing up Magic Keyboard battery report descriptor\n");
6456e143293SJosé Expósito *rsize = *rsize - 1;
6466e143293SJosé Expósito rdesc = kmemdup(rdesc + 1, *rsize, GFP_KERNEL);
6476e143293SJosé Expósito if (!rdesc)
6486e143293SJosé Expósito return NULL;
6496e143293SJosé Expósito
6506e143293SJosé Expósito rdesc[0] = 0x05;
6516e143293SJosé Expósito rdesc[1] = 0x01;
6526e143293SJosé Expósito rdesc[2] = 0x09;
6536e143293SJosé Expósito rdesc[3] = 0x06;
6546e143293SJosé Expósito }
6556e143293SJosé Expósito
65673e4008dSNikolai Kondrashov return rdesc;
6578c19a515SJiri Slaby }
6588c19a515SJiri Slaby
6598c19a515SJiri Slaby static void apple_setup_input(struct input_dev *input)
6608c19a515SJiri Slaby {
6618c19a515SJiri Slaby set_bit(KEY_NUMLOCK, input->keybit);
6628c19a515SJiri Slaby
6638c19a515SJiri Slaby /* Enable all needed keys */
664f1d1b3a9SJosé Expósito apple_setup_key_translation(input, apple_fn_keys);
665f1d1b3a9SJosé Expósito apple_setup_key_translation(input, powerbook_fn_keys);
666f1d1b3a9SJosé Expósito apple_setup_key_translation(input, powerbook_numlock_keys);
667f1d1b3a9SJosé Expósito apple_setup_key_translation(input, apple_iso_keyboard);
apple_input_mapping(struct hid_device * hdev,struct hid_input * hi,struct hid_field * field,struct hid_usage * usage,unsigned long ** bit,int * max)6680fea6fe7SJosé Expósito apple_setup_key_translation(input, magic_keyboard_alu_fn_keys);
669250b369eSJosé Expósito apple_setup_key_translation(input, magic_keyboard_2015_fn_keys);
670f1d1b3a9SJosé Expósito apple_setup_key_translation(input, apple2021_fn_keys);
671c5f09b1bSAditya Garg apple_setup_key_translation(input, macbookpro_no_esc_fn_keys);
672c5f09b1bSAditya Garg apple_setup_key_translation(input, macbookpro_dedicated_esc_fn_keys);
6738c19a515SJiri Slaby }
6748c19a515SJiri Slaby
6758c19a515SJiri Slaby static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
6768c19a515SJiri Slaby struct hid_field *field, struct hid_usage *usage,
6778c19a515SJiri Slaby unsigned long **bit, int *max)
6788c19a515SJiri Slaby {
679a5d81646SHans de Goede struct apple_sc *asc = hid_get_drvdata(hdev);
680a5d81646SHans de Goede
681ee345492SSean O'Brien if (usage->hid == (HID_UP_CUSTOM | 0x0003) ||
682e433be92SMansour Behabadi usage->hid == (HID_UP_MSVENDOR | 0x0003) ||
683e433be92SMansour Behabadi usage->hid == (HID_UP_HPVENDOR2 | 0x0003)) {
6848c19a515SJiri Slaby /* The fn key on Apple USB keyboards */
6858c19a515SJiri Slaby set_bit(EV_REP, hi->input->evbit);
6868c19a515SJiri Slaby hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
687a5d81646SHans de Goede asc->fn_found = true;
6888c19a515SJiri Slaby apple_setup_input(hi->input);
apple_input_mapped(struct hid_device * hdev,struct hid_input * hi,struct hid_field * field,struct hid_usage * usage,unsigned long ** bit,int * max)6898c19a515SJiri Slaby return 1;
6908c19a515SJiri Slaby }
6918c19a515SJiri Slaby
6928c19a515SJiri Slaby /* we want the hid layer to go through standard path (set and ignore) */
6938c19a515SJiri Slaby return 0;
6948c19a515SJiri Slaby }
6958c19a515SJiri Slaby
6968c19a515SJiri Slaby static int apple_input_mapped(struct hid_device *hdev, struct hid_input *hi,
6978c19a515SJiri Slaby struct hid_field *field, struct hid_usage *usage,
6988c19a515SJiri Slaby unsigned long **bit, int *max)
6998c19a515SJiri Slaby {
7008c19a515SJiri Slaby struct apple_sc *asc = hid_get_drvdata(hdev);
7018c19a515SJiri Slaby
7028c19a515SJiri Slaby if (asc->quirks & APPLE_MIGHTYMOUSE) {
7038c19a515SJiri Slaby if (usage->hid == HID_GD_Z)
7048c19a515SJiri Slaby hid_map_usage(hi, usage, bit, max, EV_REL, REL_HWHEEL);
7058c19a515SJiri Slaby else if (usage->code == BTN_1)
7068c19a515SJiri Slaby hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_2);
apple_input_configured(struct hid_device * hdev,struct hid_input * hidinput)7078c19a515SJiri Slaby else if (usage->code == BTN_2)
7088c19a515SJiri Slaby hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_1);
7098c19a515SJiri Slaby }
7108c19a515SJiri Slaby
7118c19a515SJiri Slaby return 0;
7128c19a515SJiri Slaby }
7138c19a515SJiri Slaby
714a5d81646SHans de Goede static int apple_input_configured(struct hid_device *hdev,
715a5d81646SHans de Goede struct hid_input *hidinput)
716a5d81646SHans de Goede {
717a5d81646SHans de Goede struct apple_sc *asc = hid_get_drvdata(hdev);
718a5d81646SHans de Goede
719*62485737SAlex Henrie if (((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) || apple_is_omoton_kb066(hdev)) {
720a5d81646SHans de Goede hid_info(hdev, "Fn key not found (Apple Wireless Keyboard clone?), disabling Fn key handling\n");
721a5fe7864SJosé Expósito asc->quirks &= ~APPLE_HAS_FN;
722a5d81646SHans de Goede }
723a5d81646SHans de Goede
724a0a05054SHilton Chain if (apple_is_non_apple_keyboard(hdev)) {
apple_backlight_check_support(struct hid_device * hdev)725a0a05054SHilton Chain hid_info(hdev, "Non-apple keyboard detected; function keys will default to fnmode=2 behavior\n");
726a0a05054SHilton Chain asc->quirks |= APPLE_IS_NON_APPLE;
727fa33382cSBryan Cain }
728fa33382cSBryan Cain
729a5d81646SHans de Goede return 0;
730a5d81646SHans de Goede }
731a5d81646SHans de Goede
7329018eacbSPaul Pawlowski static bool apple_backlight_check_support(struct hid_device *hdev)
7339018eacbSPaul Pawlowski {
7349018eacbSPaul Pawlowski int i;
7359018eacbSPaul Pawlowski unsigned int hid;
7369018eacbSPaul Pawlowski struct hid_report *report;
7379018eacbSPaul Pawlowski
7389018eacbSPaul Pawlowski list_for_each_entry(report, &hdev->report_enum[HID_INPUT_REPORT].report_list, list) {
7399018eacbSPaul Pawlowski for (i = 0; i < report->maxfield; i++) {
7409018eacbSPaul Pawlowski hid = report->field[i]->usage->hid;
7419018eacbSPaul Pawlowski if ((hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR && (hid & HID_USAGE) == 0xf)
apple_backlight_set(struct hid_device * hdev,u16 value,u16 rate)7429018eacbSPaul Pawlowski return true;
7439018eacbSPaul Pawlowski }
7449018eacbSPaul Pawlowski }
7459018eacbSPaul Pawlowski
7469018eacbSPaul Pawlowski return false;
7479018eacbSPaul Pawlowski }
7489018eacbSPaul Pawlowski
7499018eacbSPaul Pawlowski static int apple_backlight_set(struct hid_device *hdev, u16 value, u16 rate)
7509018eacbSPaul Pawlowski {
7519018eacbSPaul Pawlowski int ret = 0;
7529018eacbSPaul Pawlowski struct apple_backlight_set_report *rep;
7539018eacbSPaul Pawlowski
7549018eacbSPaul Pawlowski rep = kmalloc(sizeof(*rep), GFP_KERNEL);
7559018eacbSPaul Pawlowski if (rep == NULL)
7569018eacbSPaul Pawlowski return -ENOMEM;
7579018eacbSPaul Pawlowski
7589018eacbSPaul Pawlowski rep->report_id = 0xB0;
7599018eacbSPaul Pawlowski rep->version = 1;
7609018eacbSPaul Pawlowski rep->backlight = value;
7619018eacbSPaul Pawlowski rep->rate = rate;
7629018eacbSPaul Pawlowski
apple_backlight_led_set(struct led_classdev * led_cdev,enum led_brightness brightness)7639018eacbSPaul Pawlowski ret = hid_hw_raw_request(hdev, 0xB0u, (u8 *) rep, sizeof(*rep),
7649018eacbSPaul Pawlowski HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
7659018eacbSPaul Pawlowski
7669018eacbSPaul Pawlowski kfree(rep);
7679018eacbSPaul Pawlowski return ret;
7689018eacbSPaul Pawlowski }
7699018eacbSPaul Pawlowski
7709018eacbSPaul Pawlowski static int apple_backlight_led_set(struct led_classdev *led_cdev,
7719018eacbSPaul Pawlowski enum led_brightness brightness)
apple_backlight_init(struct hid_device * hdev)7729018eacbSPaul Pawlowski {
7739018eacbSPaul Pawlowski struct apple_sc_backlight *backlight = container_of(led_cdev,
7749018eacbSPaul Pawlowski struct apple_sc_backlight, cdev);
7759018eacbSPaul Pawlowski
7769018eacbSPaul Pawlowski return apple_backlight_set(backlight->hdev, brightness, 0);
7779018eacbSPaul Pawlowski }
7789018eacbSPaul Pawlowski
7799018eacbSPaul Pawlowski static int apple_backlight_init(struct hid_device *hdev)
7809018eacbSPaul Pawlowski {
7819018eacbSPaul Pawlowski int ret;
7829018eacbSPaul Pawlowski struct apple_sc *asc = hid_get_drvdata(hdev);
7839018eacbSPaul Pawlowski struct apple_backlight_config_report *rep;
7849018eacbSPaul Pawlowski
7859018eacbSPaul Pawlowski if (!apple_backlight_check_support(hdev))
7869018eacbSPaul Pawlowski return -EINVAL;
7879018eacbSPaul Pawlowski
7889018eacbSPaul Pawlowski rep = kmalloc(0x200, GFP_KERNEL);
7899018eacbSPaul Pawlowski if (rep == NULL)
7909018eacbSPaul Pawlowski return -ENOMEM;
7919018eacbSPaul Pawlowski
7929018eacbSPaul Pawlowski ret = hid_hw_raw_request(hdev, 0xBFu, (u8 *) rep, sizeof(*rep),
7939018eacbSPaul Pawlowski HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
7949018eacbSPaul Pawlowski if (ret < 0) {
7959018eacbSPaul Pawlowski hid_err(hdev, "backlight request failed: %d\n", ret);
7969018eacbSPaul Pawlowski goto cleanup_and_exit;
7979018eacbSPaul Pawlowski }
7989018eacbSPaul Pawlowski if (ret < 8 || rep->version != 1) {
7999018eacbSPaul Pawlowski hid_err(hdev, "backlight config struct: bad version %i\n", rep->version);
8009018eacbSPaul Pawlowski ret = -EINVAL;
8019018eacbSPaul Pawlowski goto cleanup_and_exit;
8029018eacbSPaul Pawlowski }
8039018eacbSPaul Pawlowski
8049018eacbSPaul Pawlowski hid_dbg(hdev, "backlight config: off=%u, on_min=%u, on_max=%u\n",
8059018eacbSPaul Pawlowski rep->backlight_off, rep->backlight_on_min, rep->backlight_on_max);
8069018eacbSPaul Pawlowski
8079018eacbSPaul Pawlowski asc->backlight = devm_kzalloc(&hdev->dev, sizeof(*asc->backlight), GFP_KERNEL);
8089018eacbSPaul Pawlowski if (!asc->backlight) {
8099018eacbSPaul Pawlowski ret = -ENOMEM;
8109018eacbSPaul Pawlowski goto cleanup_and_exit;
8119018eacbSPaul Pawlowski }
8129018eacbSPaul Pawlowski
8139018eacbSPaul Pawlowski asc->backlight->hdev = hdev;
8149018eacbSPaul Pawlowski asc->backlight->cdev.name = "apple::kbd_backlight";
8159018eacbSPaul Pawlowski asc->backlight->cdev.max_brightness = rep->backlight_on_max;
8169018eacbSPaul Pawlowski asc->backlight->cdev.brightness_set_blocking = apple_backlight_led_set;
8179018eacbSPaul Pawlowski
8189018eacbSPaul Pawlowski ret = apple_backlight_set(hdev, 0, 0);
8199018eacbSPaul Pawlowski if (ret < 0) {
8209018eacbSPaul Pawlowski hid_err(hdev, "backlight set request failed: %d\n", ret);
8219018eacbSPaul Pawlowski goto cleanup_and_exit;
8229018eacbSPaul Pawlowski }
8239018eacbSPaul Pawlowski
apple_probe(struct hid_device * hdev,const struct hid_device_id * id)8249018eacbSPaul Pawlowski ret = devm_led_classdev_register(&hdev->dev, &asc->backlight->cdev);
8259018eacbSPaul Pawlowski
8269018eacbSPaul Pawlowski cleanup_and_exit:
8279018eacbSPaul Pawlowski kfree(rep);
8289018eacbSPaul Pawlowski return ret;
8299018eacbSPaul Pawlowski }
8309018eacbSPaul Pawlowski
8318c19a515SJiri Slaby static int apple_probe(struct hid_device *hdev,
8328c19a515SJiri Slaby const struct hid_device_id *id)
8338c19a515SJiri Slaby {
8348c19a515SJiri Slaby unsigned long quirks = id->driver_data;
8358c19a515SJiri Slaby struct apple_sc *asc;
8368c19a515SJiri Slaby int ret;
8378c19a515SJiri Slaby
838abf832bfSBenjamin Tissoires asc = devm_kzalloc(&hdev->dev, sizeof(*asc), GFP_KERNEL);
8398c19a515SJiri Slaby if (asc == NULL) {
8404291ee30SJoe Perches hid_err(hdev, "can't alloc apple descriptor\n");
8418c19a515SJiri Slaby return -ENOMEM;
8428c19a515SJiri Slaby }
8438c19a515SJiri Slaby
8446e143293SJosé Expósito asc->hdev = hdev;
8458c19a515SJiri Slaby asc->quirks = quirks;
8468c19a515SJiri Slaby
8478c19a515SJiri Slaby hid_set_drvdata(hdev, asc);
8488c19a515SJiri Slaby
8498c19a515SJiri Slaby ret = hid_parse(hdev);
8508c19a515SJiri Slaby if (ret) {
8514291ee30SJoe Perches hid_err(hdev, "parse failed\n");
852abf832bfSBenjamin Tissoires return ret;
8538c19a515SJiri Slaby }
8548c19a515SJiri Slaby
855cc840942SAlexander F. Lent ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
8568c19a515SJiri Slaby if (ret) {
8574291ee30SJoe Perches hid_err(hdev, "hw start failed\n");
8588c19a515SJiri Slaby return ret;
8598c19a515SJiri Slaby }
8608c19a515SJiri Slaby
8616e143293SJosé Expósito timer_setup(&asc->battery_timer, apple_battery_timer_tick, 0);
8626e143293SJosé Expósito mod_timer(&asc->battery_timer,
8636e143293SJosé Expósito jiffies + msecs_to_jiffies(APPLE_BATTERY_TIMEOUT_MS));
8646e143293SJosé Expósito apple_fetch_battery(hdev);
apple_remove(struct hid_device * hdev)8656e143293SJosé Expósito
8669018eacbSPaul Pawlowski if (quirks & APPLE_BACKLIGHT_CTL)
8679018eacbSPaul Pawlowski apple_backlight_init(hdev);
8689018eacbSPaul Pawlowski
869abf832bfSBenjamin Tissoires return 0;
8708c19a515SJiri Slaby }
8718c19a515SJiri Slaby
8726e143293SJosé Expósito static void apple_remove(struct hid_device *hdev)
8736e143293SJosé Expósito {
8746e143293SJosé Expósito struct apple_sc *asc = hid_get_drvdata(hdev);
8756e143293SJosé Expósito
8766e143293SJosé Expósito del_timer_sync(&asc->battery_timer);
8776e143293SJosé Expósito
8786e143293SJosé Expósito hid_hw_stop(hdev);
8796e143293SJosé Expósito }
8806e143293SJosé Expósito
8818c19a515SJiri Slaby static const struct hid_device_id apple_devices[] = {
8828c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE),
8838c19a515SJiri Slaby .driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
8848c19a515SJiri Slaby
8858c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI),
886b4d8e473SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
8878c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO),
888b4d8e473SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
8898c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI),
890b4d8e473SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
8918c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO),
892bd77a0f0SAlex Henrie .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
8938c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS),
894b4d8e473SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
8958c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI),
896b4d8e473SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
8978c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO),
89829e1ecc1SAlex Henrie .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
89929e1ecc1SAlex Henrie APPLE_ISO_TILDE_QUIRK },
9008c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS),
9018c19a515SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
902b4d8e473SJiri Slaby APPLE_RDESC_JIS },
9038c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI),
904b4d8e473SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
9058c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO),
906c3388ddcSAlex Henrie .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
907c3388ddcSAlex Henrie APPLE_ISO_TILDE_QUIRK },
9088c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS),
9098c19a515SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
910b4d8e473SJiri Slaby APPLE_RDESC_JIS },
911fef3f571SRyan Finnie { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ANSI),
912fef3f571SRyan Finnie .driver_data = APPLE_HAS_FN },
913fef3f571SRyan Finnie { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ISO),
914bd77a0f0SAlex Henrie .driver_data = APPLE_HAS_FN },
915fef3f571SRyan Finnie { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_JIS),
916fef3f571SRyan Finnie .driver_data = APPLE_HAS_FN },
9178c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI),
9188c19a515SJiri Slaby .driver_data = APPLE_HAS_FN },
9198c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO),
920bd77a0f0SAlex Henrie .driver_data = APPLE_HAS_FN },
9218c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS),
9228c19a515SJiri Slaby .driver_data = APPLE_HAS_FN },
9238c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI),
924b4d8e473SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
9258c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO),
926c3388ddcSAlex Henrie .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
927c3388ddcSAlex Henrie APPLE_ISO_TILDE_QUIRK },
9288c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
9298c19a515SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
930b4d8e473SJiri Slaby APPLE_RDESC_JIS },
9314a4c8799SDan Bastone { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI),
9324a4c8799SDan Bastone .driver_data = APPLE_HAS_FN },
933ebe0b42aSHaochen Tong { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI),
934ebe0b42aSHaochen Tong .driver_data = APPLE_HAS_FN },
9354a4c8799SDan Bastone { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO),
936bd77a0f0SAlex Henrie .driver_data = APPLE_HAS_FN },
9374c945426SBALATON Zoltan { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ISO),
9384c945426SBALATON Zoltan .driver_data = APPLE_HAS_FN },
9394a4c8799SDan Bastone { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_JIS),
9404a4c8799SDan Bastone .driver_data = APPLE_HAS_FN },
941ee8a1a0aSJan Scholz { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
9428c19a515SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
943ee8a1a0aSJan Scholz { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
944d58cf34aSAlex Henrie .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
945d58cf34aSAlex Henrie APPLE_ISO_TILDE_QUIRK },
946ad734bc1SAndreas Krist { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO),
947d58cf34aSAlex Henrie .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
948d58cf34aSAlex Henrie APPLE_ISO_TILDE_QUIRK },
9490a97e1e9SAlexey Kaminsky { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
9500a97e1e9SAlexey Kaminsky USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
9510a97e1e9SAlexey Kaminsky .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
952bd4a7ce1SHuei-Horng Yo { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
953bd4a7ce1SHuei-Horng Yo USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_JIS),
954bd4a7ce1SHuei-Horng Yo .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
955ee8a1a0aSJan Scholz { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
9568c19a515SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
957371a9dceSAlex Henrie { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015),
9586e143293SJosé Expósito .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY },
959371a9dceSAlex Henrie { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2015),
960d58cf34aSAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
961371a9dceSAlex Henrie { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015),
9626e143293SJosé Expósito .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY },
963371a9dceSAlex Henrie { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2015),
964d58cf34aSAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
9658c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
966b4d8e473SJiri Slaby .driver_data = APPLE_HAS_FN },
9678c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
968c3388ddcSAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
9698c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS),
970b4d8e473SJiri Slaby .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
9718c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
972b4d8e473SJiri Slaby .driver_data = APPLE_HAS_FN },
9738c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
974c3388ddcSAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
9758c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
976b4d8e473SJiri Slaby .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
977a96d6ef3SHenrik Rydberg { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
978a96d6ef3SHenrik Rydberg .driver_data = APPLE_HAS_FN },
979a96d6ef3SHenrik Rydberg { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
980c3388ddcSAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
981a96d6ef3SHenrik Rydberg { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
982a96d6ef3SHenrik Rydberg .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
98399b9f758SEdgar (gimli) Hucek { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI),
98499b9f758SEdgar (gimli) Hucek .driver_data = APPLE_HAS_FN },
98599b9f758SEdgar (gimli) Hucek { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_ISO),
986c3388ddcSAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
98799b9f758SEdgar (gimli) Hucek { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4_JIS),
98899b9f758SEdgar (gimli) Hucek .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
98999b9f758SEdgar (gimli) Hucek { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI),
99099b9f758SEdgar (gimli) Hucek .driver_data = APPLE_HAS_FN },
99199b9f758SEdgar (gimli) Hucek { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO),
992c3388ddcSAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
99399b9f758SEdgar (gimli) Hucek { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
99499b9f758SEdgar (gimli) Hucek .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
99547340bd9SAndy Botting { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
99647340bd9SAndy Botting .driver_data = APPLE_HAS_FN },
99747340bd9SAndy Botting { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
998e26a7805SAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
99947340bd9SAndy Botting { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
100047340bd9SAndy Botting .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
10015d922baaSJoshua V. Dillon { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI),
10025d922baaSJoshua V. Dillon .driver_data = APPLE_HAS_FN },
10035d922baaSJoshua V. Dillon { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_ISO),
1004e26a7805SAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
10055d922baaSJoshua V. Dillon { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6_JIS),
10065d922baaSJoshua V. Dillon .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
1007d762cc29SNobuhiro Iwamatsu { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI),
1008d762cc29SNobuhiro Iwamatsu .driver_data = APPLE_HAS_FN },
1009d762cc29SNobuhiro Iwamatsu { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO),
1010e26a7805SAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
1011d762cc29SNobuhiro Iwamatsu { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS),
1012d762cc29SNobuhiro Iwamatsu .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
1013213f9da8SGökçen Eraslan { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI),
1014213f9da8SGökçen Eraslan .driver_data = APPLE_HAS_FN },
1015213f9da8SGökçen Eraslan { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO),
1016e26a7805SAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
1017213f9da8SGökçen Eraslan { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS),
1018213f9da8SGökçen Eraslan .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
1019b2e6ad7dSRyan Bourgeois { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
1020b2e6ad7dSRyan Bourgeois .driver_data = APPLE_HAS_FN },
1021b2e6ad7dSRyan Bourgeois { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
1022e26a7805SAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
1023b2e6ad7dSRyan Bourgeois { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
1024b2e6ad7dSRyan Bourgeois .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
10258d80da90SDirk Hohndel { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
10268d80da90SDirk Hohndel .driver_data = APPLE_HAS_FN },
10278d80da90SDirk Hohndel { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
1028e26a7805SAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
10298d80da90SDirk Hohndel { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
10308d80da90SDirk Hohndel .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
10319d9a04eeSDmitry Torokhov { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI),
10329d9a04eeSDmitry Torokhov .driver_data = APPLE_HAS_FN },
10339d9a04eeSDmitry Torokhov { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO),
1034e26a7805SAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
10359d9a04eeSDmitry Torokhov { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS),
10369d9a04eeSDmitry Torokhov .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
1037a4a2c545SHenrik Rydberg { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI),
1038a4a2c545SHenrik Rydberg .driver_data = APPLE_HAS_FN },
1039a4a2c545SHenrik Rydberg { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO),
1040e26a7805SAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
1041a4a2c545SHenrik Rydberg { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
1042a4a2c545SHenrik Rydberg .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
104342f6a2d3SAun-Ali Zaidi { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K),
1044084bc074SKerem Karabay .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
104542f6a2d3SAun-Ali Zaidi { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132),
1046084bc074SKerem Karabay .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
104742f6a2d3SAun-Ali Zaidi { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680),
1048084bc074SKerem Karabay .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
104942f6a2d3SAun-Ali Zaidi { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213),
1050084bc074SKerem Karabay .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
105142f6a2d3SAun-Ali Zaidi { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K),
1052084bc074SKerem Karabay .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
105342f6a2d3SAun-Ali Zaidi { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223),
1054084bc074SKerem Karabay .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
105542f6a2d3SAun-Ali Zaidi { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K),
1056084bc074SKerem Karabay .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
105742f6a2d3SAun-Ali Zaidi { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F),
1058084bc074SKerem Karabay .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
105923aeb61eSChristian Schuerer-Waldheim { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
106023aeb61eSChristian Schuerer-Waldheim .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
106123aeb61eSChristian Schuerer-Waldheim { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
1062d58cf34aSAlex Henrie .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
1063d58cf34aSAlex Henrie APPLE_ISO_TILDE_QUIRK },
106423aeb61eSChristian Schuerer-Waldheim { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS),
106523aeb61eSChristian Schuerer-Waldheim .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
10668c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY),
1067b4d8e473SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
10688c19a515SJiri Slaby { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
1069b4d8e473SJiri Slaby .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
10700cd3be51SAlex Henrie { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021),
10718ae5c16cSJosé Expósito .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY },
10720cd3be51SAlex Henrie { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021),
1073d58cf34aSAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
107468eddb06SIevgen Vovk { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024),
107568eddb06SIevgen Vovk .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY },
107668eddb06SIevgen Vovk { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2024),
107768eddb06SIevgen Vovk .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
10789f92d61fSAlex Henrie { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021),
1079cbfcfbfcSJosé Expósito .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY },
10809f92d61fSAlex Henrie { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021),
10819f92d61fSAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
1082b2dcadefSAlex Henrie { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021),
1083cbfcfbfcSJosé Expósito .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK | APPLE_RDESC_BATTERY },
1084b2dcadefSAlex Henrie { HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021),
1085b2dcadefSAlex Henrie .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
10868c19a515SJiri Slaby
10878c19a515SJiri Slaby { }
10888c19a515SJiri Slaby };
10898c19a515SJiri Slaby MODULE_DEVICE_TABLE(hid, apple_devices);
10908c19a515SJiri Slaby
10918c19a515SJiri Slaby static struct hid_driver apple_driver = {
10928c19a515SJiri Slaby .name = "apple",
10938c19a515SJiri Slaby .id_table = apple_devices,
10948c19a515SJiri Slaby .report_fixup = apple_report_fixup,
10958c19a515SJiri Slaby .probe = apple_probe,
10966e143293SJosé Expósito .remove = apple_remove,
10978c19a515SJiri Slaby .event = apple_event,
10988c19a515SJiri Slaby .input_mapping = apple_input_mapping,
10998c19a515SJiri Slaby .input_mapped = apple_input_mapped,
1100a5d81646SHans de Goede .input_configured = apple_input_configured,
11018c19a515SJiri Slaby };
1102f425458eSH Hartley Sweeten module_hid_driver(apple_driver);
11038c19a515SJiri Slaby
11048c19a515SJiri Slaby MODULE_LICENSE("GPL");
1105