linux/drivers/hid/hid-apple.c
<<
>>
Prefs
   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
  38static unsigned int fnmode = 1;
  39module_param(fnmode, uint, 0644);
  40MODULE_PARM_DESC(fnmode, "Mode of fn key on Apple keyboards (0 = disabled, "
  41                "[1] = fkeyslast, 2 = fkeysfirst)");
  42
  43struct 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
  50struct apple_key_translation {
  51        u16 from;
  52        u16 to;
  53        u8 flags;
  54};
  55
  56static 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
  78static 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
  97static 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
 120static const struct apple_key_translation apple_iso_keyboard[] = {
 121        { KEY_GRAVE,    KEY_102ND },
 122        { KEY_102ND,    KEY_GRAVE },
 123        { }
 124};
 125
 126static 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
 139static 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 < 0x21d ||
 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
 213static 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 */
 241static 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
 254static 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
 274static 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
 290static 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
 308static 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;
 344err_free:
 345        kfree(asc);
 346        return ret;
 347}
 348
 349static void apple_remove(struct hid_device *hdev)
 350{
 351        hid_hw_stop(hdev);
 352        kfree(hid_get_drvdata(hdev));
 353}
 354
 355static 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        { }
 440};
 441MODULE_DEVICE_TABLE(hid, apple_devices);
 442
 443static struct hid_driver apple_driver = {
 444        .name = "apple",
 445        .id_table = apple_devices,
 446        .report_fixup = apple_report_fixup,
 447        .probe = apple_probe,
 448        .remove = apple_remove,
 449        .event = apple_event,
 450        .input_mapping = apple_input_mapping,
 451        .input_mapped = apple_input_mapped,
 452};
 453
 454static int __init apple_init(void)
 455{
 456        int ret;
 457
 458        ret = hid_register_driver(&apple_driver);
 459        if (ret)
 460                printk(KERN_ERR "can't register apple driver\n");
 461
 462        return ret;
 463}
 464
 465static void __exit apple_exit(void)
 466{
 467        hid_unregister_driver(&apple_driver);
 468}
 469
 470module_init(apple_init);
 471module_exit(apple_exit);
 472MODULE_LICENSE("GPL");
 473