xref: /openbmc/linux/drivers/hid/hid-apple.c (revision 8db70d3d)
1 /*
2  *  USB HID quirks support for Linux
3  *
4  *  Copyright (c) 1999 Andreas Gal
5  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
6  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
7  *  Copyright (c) 2006-2007 Jiri Kosina
8  *  Copyright (c) 2007 Paul Walmsley
9  *  Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
10  */
11 
12 /*
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the Free
15  * Software Foundation; either version 2 of the License, or (at your option)
16  * any later version.
17  */
18 
19 #include <linux/device.h>
20 #include <linux/hid.h>
21 #include <linux/module.h>
22 #include <linux/usb.h>
23 
24 #include "hid-ids.h"
25 
26 #define APPLE_RDESC_JIS		0x0001
27 #define APPLE_IGNORE_MOUSE	0x0002
28 #define APPLE_HAS_FN		0x0004
29 #define APPLE_HIDDEV		0x0008
30 #define APPLE_ISO_KEYBOARD	0x0010
31 #define APPLE_MIGHTYMOUSE	0x0020
32 #define APPLE_INVERT_HWHEEL	0x0040
33 #define APPLE_IGNORE_HIDINPUT	0x0080
34 #define APPLE_NUMLOCK_EMULATION	0x0100
35 
36 #define APPLE_FLAG_FKEY		0x01
37 
38 static unsigned int fnmode = 1;
39 module_param(fnmode, uint, 0644);
40 MODULE_PARM_DESC(fnmode, "Mode of fn key on Apple keyboards (0 = disabled, "
41 		"[1] = fkeyslast, 2 = fkeysfirst)");
42 
43 struct apple_sc {
44 	unsigned long quirks;
45 	unsigned int fn_on;
46 	DECLARE_BITMAP(pressed_fn, KEY_CNT);
47 	DECLARE_BITMAP(pressed_numlock, KEY_CNT);
48 };
49 
50 struct apple_key_translation {
51 	u16 from;
52 	u16 to;
53 	u8 flags;
54 };
55 
56 static const struct apple_key_translation apple_fn_keys[] = {
57 	{ KEY_BACKSPACE, KEY_DELETE },
58 	{ KEY_ENTER,	KEY_INSERT },
59 	{ KEY_F1,	KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
60 	{ KEY_F2,	KEY_BRIGHTNESSUP,   APPLE_FLAG_FKEY },
61 	{ KEY_F3,	KEY_SCALE,          APPLE_FLAG_FKEY },
62 	{ KEY_F4,	KEY_DASHBOARD,      APPLE_FLAG_FKEY },
63 	{ KEY_F5,	KEY_KBDILLUMDOWN,   APPLE_FLAG_FKEY },
64 	{ KEY_F6,	KEY_KBDILLUMUP,     APPLE_FLAG_FKEY },
65 	{ KEY_F7,	KEY_PREVIOUSSONG,   APPLE_FLAG_FKEY },
66 	{ KEY_F8,	KEY_PLAYPAUSE,      APPLE_FLAG_FKEY },
67 	{ KEY_F9,	KEY_NEXTSONG,       APPLE_FLAG_FKEY },
68 	{ KEY_F10,	KEY_MUTE,           APPLE_FLAG_FKEY },
69 	{ KEY_F11,	KEY_VOLUMEDOWN,     APPLE_FLAG_FKEY },
70 	{ KEY_F12,	KEY_VOLUMEUP,       APPLE_FLAG_FKEY },
71 	{ KEY_UP,	KEY_PAGEUP },
72 	{ KEY_DOWN,	KEY_PAGEDOWN },
73 	{ KEY_LEFT,	KEY_HOME },
74 	{ KEY_RIGHT,	KEY_END },
75 	{ }
76 };
77 
78 static const struct apple_key_translation powerbook_fn_keys[] = {
79 	{ KEY_BACKSPACE, KEY_DELETE },
80 	{ KEY_F1,	KEY_BRIGHTNESSDOWN,     APPLE_FLAG_FKEY },
81 	{ KEY_F2,	KEY_BRIGHTNESSUP,       APPLE_FLAG_FKEY },
82 	{ KEY_F3,	KEY_MUTE,               APPLE_FLAG_FKEY },
83 	{ KEY_F4,	KEY_VOLUMEDOWN,         APPLE_FLAG_FKEY },
84 	{ KEY_F5,	KEY_VOLUMEUP,           APPLE_FLAG_FKEY },
85 	{ KEY_F6,	KEY_NUMLOCK,            APPLE_FLAG_FKEY },
86 	{ KEY_F7,	KEY_SWITCHVIDEOMODE,    APPLE_FLAG_FKEY },
87 	{ KEY_F8,	KEY_KBDILLUMTOGGLE,     APPLE_FLAG_FKEY },
88 	{ KEY_F9,	KEY_KBDILLUMDOWN,       APPLE_FLAG_FKEY },
89 	{ KEY_F10,	KEY_KBDILLUMUP,         APPLE_FLAG_FKEY },
90 	{ KEY_UP,	KEY_PAGEUP },
91 	{ KEY_DOWN,	KEY_PAGEDOWN },
92 	{ KEY_LEFT,	KEY_HOME },
93 	{ KEY_RIGHT,	KEY_END },
94 	{ }
95 };
96 
97 static const struct apple_key_translation powerbook_numlock_keys[] = {
98 	{ KEY_J,	KEY_KP1 },
99 	{ KEY_K,	KEY_KP2 },
100 	{ KEY_L,	KEY_KP3 },
101 	{ KEY_U,	KEY_KP4 },
102 	{ KEY_I,	KEY_KP5 },
103 	{ KEY_O,	KEY_KP6 },
104 	{ KEY_7,	KEY_KP7 },
105 	{ KEY_8,	KEY_KP8 },
106 	{ KEY_9,	KEY_KP9 },
107 	{ KEY_M,	KEY_KP0 },
108 	{ KEY_DOT,	KEY_KPDOT },
109 	{ KEY_SLASH,	KEY_KPPLUS },
110 	{ KEY_SEMICOLON, KEY_KPMINUS },
111 	{ KEY_P,	KEY_KPASTERISK },
112 	{ KEY_MINUS,	KEY_KPEQUAL },
113 	{ KEY_0,	KEY_KPSLASH },
114 	{ KEY_F6,	KEY_NUMLOCK },
115 	{ KEY_KPENTER,	KEY_KPENTER },
116 	{ KEY_BACKSPACE, KEY_BACKSPACE },
117 	{ }
118 };
119 
120 static const struct apple_key_translation apple_iso_keyboard[] = {
121 	{ KEY_GRAVE,	KEY_102ND },
122 	{ KEY_102ND,	KEY_GRAVE },
123 	{ }
124 };
125 
126 static const struct apple_key_translation *apple_find_translation(
127 		const struct apple_key_translation *table, u16 from)
128 {
129 	const struct apple_key_translation *trans;
130 
131 	/* Look for the translation */
132 	for (trans = table; trans->from; trans++)
133 		if (trans->from == from)
134 			return trans;
135 
136 	return NULL;
137 }
138 
139 static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
140 		struct hid_usage *usage, __s32 value)
141 {
142 	struct apple_sc *asc = hid_get_drvdata(hid);
143 	const struct apple_key_translation *trans;
144 
145 	if (usage->code == KEY_FN) {
146 		asc->fn_on = !!value;
147 		input_event(input, usage->type, usage->code, value);
148 		return 1;
149 	}
150 
151 	if (fnmode) {
152 		int do_translate;
153 
154 		trans = apple_find_translation((hid->product < 0x220 ||
155 					hid->product >= 0x300) ?
156 					powerbook_fn_keys : apple_fn_keys,
157 					usage->code);
158 		if (trans) {
159 			if (test_bit(usage->code, asc->pressed_fn))
160 				do_translate = 1;
161 			else if (trans->flags & APPLE_FLAG_FKEY)
162 				do_translate = (fnmode == 2 && asc->fn_on) ||
163 					(fnmode == 1 && !asc->fn_on);
164 			else
165 				do_translate = asc->fn_on;
166 
167 			if (do_translate) {
168 				if (value)
169 					set_bit(usage->code, asc->pressed_fn);
170 				else
171 					clear_bit(usage->code, asc->pressed_fn);
172 
173 				input_event(input, usage->type, trans->to,
174 						value);
175 
176 				return 1;
177 			}
178 		}
179 
180 		if (asc->quirks & APPLE_NUMLOCK_EMULATION &&
181 				(test_bit(usage->code, asc->pressed_numlock) ||
182 				test_bit(LED_NUML, input->led))) {
183 			trans = apple_find_translation(powerbook_numlock_keys,
184 					usage->code);
185 
186 			if (trans) {
187 				if (value)
188 					set_bit(usage->code,
189 							asc->pressed_numlock);
190 				else
191 					clear_bit(usage->code,
192 							asc->pressed_numlock);
193 
194 				input_event(input, usage->type, trans->to,
195 						value);
196 			}
197 
198 			return 1;
199 		}
200 	}
201 
202 	if (asc->quirks & APPLE_ISO_KEYBOARD) {
203 		trans = apple_find_translation(apple_iso_keyboard, usage->code);
204 		if (trans) {
205 			input_event(input, usage->type, trans->to, value);
206 			return 1;
207 		}
208 	}
209 
210 	return 0;
211 }
212 
213 static int apple_event(struct hid_device *hdev, struct hid_field *field,
214 		struct hid_usage *usage, __s32 value)
215 {
216 	struct apple_sc *asc = hid_get_drvdata(hdev);
217 
218 	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
219 			!usage->type)
220 		return 0;
221 
222 	if ((asc->quirks & APPLE_INVERT_HWHEEL) &&
223 			usage->code == REL_HWHEEL) {
224 		input_event(field->hidinput->input, usage->type, usage->code,
225 				-value);
226 		return 1;
227 	}
228 
229 	if ((asc->quirks & APPLE_HAS_FN) &&
230 			hidinput_apple_event(hdev, field->hidinput->input,
231 				usage, value))
232 		return 1;
233 
234 
235 	return 0;
236 }
237 
238 /*
239  * MacBook JIS keyboard has wrong logical maximum
240  */
241 static void apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
242 		unsigned int rsize)
243 {
244 	struct apple_sc *asc = hid_get_drvdata(hdev);
245 
246 	if ((asc->quirks & APPLE_RDESC_JIS) && rsize >= 60 &&
247 			rdesc[53] == 0x65 && rdesc[59] == 0x65) {
248 		dev_info(&hdev->dev, "fixing up MacBook JIS keyboard report "
249 				"descriptor\n");
250 		rdesc[53] = rdesc[59] = 0xe7;
251 	}
252 }
253 
254 static void apple_setup_input(struct input_dev *input)
255 {
256 	const struct apple_key_translation *trans;
257 
258 	set_bit(KEY_NUMLOCK, input->keybit);
259 
260 	/* Enable all needed keys */
261 	for (trans = apple_fn_keys; trans->from; trans++)
262 		set_bit(trans->to, input->keybit);
263 
264 	for (trans = powerbook_fn_keys; trans->from; trans++)
265 		set_bit(trans->to, input->keybit);
266 
267 	for (trans = powerbook_numlock_keys; trans->from; trans++)
268 		set_bit(trans->to, input->keybit);
269 
270 	for (trans = apple_iso_keyboard; trans->from; trans++)
271 		set_bit(trans->to, input->keybit);
272 }
273 
274 static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
275 		struct hid_field *field, struct hid_usage *usage,
276 		unsigned long **bit, int *max)
277 {
278 	if (usage->hid == (HID_UP_CUSTOM | 0x0003)) {
279 		/* The fn key on Apple USB keyboards */
280 		set_bit(EV_REP, hi->input->evbit);
281 		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
282 		apple_setup_input(hi->input);
283 		return 1;
284 	}
285 
286 	/* we want the hid layer to go through standard path (set and ignore) */
287 	return 0;
288 }
289 
290 static int apple_input_mapped(struct hid_device *hdev, struct hid_input *hi,
291 		struct hid_field *field, struct hid_usage *usage,
292 		unsigned long **bit, int *max)
293 {
294 	struct apple_sc *asc = hid_get_drvdata(hdev);
295 
296 	if (asc->quirks & APPLE_MIGHTYMOUSE) {
297 		if (usage->hid == HID_GD_Z)
298 			hid_map_usage(hi, usage, bit, max, EV_REL, REL_HWHEEL);
299 		else if (usage->code == BTN_1)
300 			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_2);
301 		else if (usage->code == BTN_2)
302 			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_1);
303 	}
304 
305 	return 0;
306 }
307 
308 static int apple_probe(struct hid_device *hdev,
309 		const struct hid_device_id *id)
310 {
311 	unsigned long quirks = id->driver_data;
312 	struct apple_sc *asc;
313 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
314 	int ret;
315 
316 	asc = kzalloc(sizeof(*asc), GFP_KERNEL);
317 	if (asc == NULL) {
318 		dev_err(&hdev->dev, "can't alloc apple descriptor\n");
319 		return -ENOMEM;
320 	}
321 
322 	asc->quirks = quirks;
323 
324 	hid_set_drvdata(hdev, asc);
325 
326 	ret = hid_parse(hdev);
327 	if (ret) {
328 		dev_err(&hdev->dev, "parse failed\n");
329 		goto err_free;
330 	}
331 
332 	if (quirks & APPLE_HIDDEV)
333 		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
334 	if (quirks & APPLE_IGNORE_HIDINPUT)
335 		connect_mask &= ~HID_CONNECT_HIDINPUT;
336 
337 	ret = hid_hw_start(hdev, connect_mask);
338 	if (ret) {
339 		dev_err(&hdev->dev, "hw start failed\n");
340 		goto err_free;
341 	}
342 
343 	return 0;
344 err_free:
345 	kfree(asc);
346 	return ret;
347 }
348 
349 static void apple_remove(struct hid_device *hdev)
350 {
351 	hid_hw_stop(hdev);
352 	kfree(hid_get_drvdata(hdev));
353 }
354 
355 static const struct hid_device_id apple_devices[] = {
356 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL),
357 		.driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
358 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4),
359 		.driver_data = APPLE_HIDDEV | APPLE_IGNORE_HIDINPUT },
360 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE),
361 		.driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
362 
363 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI),
364 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
365 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO),
366 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
367 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI),
368 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
369 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO),
370 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
371 			APPLE_ISO_KEYBOARD },
372 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS),
373 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
374 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI),
375 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
376 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO),
377 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
378 			APPLE_ISO_KEYBOARD },
379 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS),
380 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
381 			APPLE_RDESC_JIS },
382 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI),
383 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
384 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO),
385 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
386 			APPLE_ISO_KEYBOARD },
387 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS),
388 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
389 			APPLE_RDESC_JIS },
390 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ANSI),
391 		.driver_data = APPLE_HAS_FN },
392 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ISO),
393 		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
394 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_JIS),
395 		.driver_data = APPLE_HAS_FN },
396 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI),
397 		.driver_data = APPLE_HAS_FN },
398 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO),
399 		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
400 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS),
401 		.driver_data = APPLE_HAS_FN },
402 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI),
403 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
404 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO),
405 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
406 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS),
407 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
408 			APPLE_RDESC_JIS },
409 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
410 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
411 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO),
412 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN |
413 			APPLE_ISO_KEYBOARD },
414 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS),
415 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
416 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ANSI),
417 		.driver_data = APPLE_HAS_FN },
418 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_ISO),
419 		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
420 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING_JIS),
421 		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
422 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
423 		.driver_data = APPLE_HAS_FN },
424 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
425 		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
426 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
427 		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
428 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
429 		.driver_data = APPLE_HAS_FN },
430 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
431 		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
432 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
433 		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
434 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY),
435 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
436 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
437 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
438 
439 	/* Apple wireless Mighty Mouse */
440 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c),
441 		.driver_data = APPLE_MIGHTYMOUSE | APPLE_INVERT_HWHEEL },
442 
443 	{ }
444 };
445 MODULE_DEVICE_TABLE(hid, apple_devices);
446 
447 static struct hid_driver apple_driver = {
448 	.name = "apple",
449 	.id_table = apple_devices,
450 	.report_fixup = apple_report_fixup,
451 	.probe = apple_probe,
452 	.remove = apple_remove,
453 	.event = apple_event,
454 	.input_mapping = apple_input_mapping,
455 	.input_mapped = apple_input_mapped,
456 };
457 
458 static int apple_init(void)
459 {
460 	int ret;
461 
462 	ret = hid_register_driver(&apple_driver);
463 	if (ret)
464 		printk(KERN_ERR "can't register apple driver\n");
465 
466 	return ret;
467 }
468 
469 static void apple_exit(void)
470 {
471 	hid_unregister_driver(&apple_driver);
472 }
473 
474 module_init(apple_init);
475 module_exit(apple_exit);
476 MODULE_LICENSE("GPL");
477