1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * drivers/input/adbhid.c 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * ADB HID driver for Power Macintosh computers. 5*1da177e4SLinus Torvalds * 6*1da177e4SLinus Torvalds * Adapted from drivers/macintosh/mac_keyb.c by Franz Sirl. 7*1da177e4SLinus Torvalds * drivers/macintosh/mac_keyb.c was Copyright (C) 1996 Paul Mackerras 8*1da177e4SLinus Torvalds * with considerable contributions from Ben Herrenschmidt and others. 9*1da177e4SLinus Torvalds * 10*1da177e4SLinus Torvalds * Copyright (C) 2000 Franz Sirl. 11*1da177e4SLinus Torvalds * 12*1da177e4SLinus Torvalds * Adapted to ADB changes and support for more devices by 13*1da177e4SLinus Torvalds * Benjamin Herrenschmidt. Adapted from code in MkLinux 14*1da177e4SLinus Torvalds * and reworked. 15*1da177e4SLinus Torvalds * 16*1da177e4SLinus Torvalds * Supported devices: 17*1da177e4SLinus Torvalds * 18*1da177e4SLinus Torvalds * - Standard 1 button mouse 19*1da177e4SLinus Torvalds * - All standard Apple Extended protocol (handler ID 4) 20*1da177e4SLinus Torvalds * - mouseman and trackman mice & trackballs 21*1da177e4SLinus Torvalds * - PowerBook Trackpad (default setup: enable tapping) 22*1da177e4SLinus Torvalds * - MicroSpeed mouse & trackball (needs testing) 23*1da177e4SLinus Torvalds * - CH Products Trackball Pro (needs testing) 24*1da177e4SLinus Torvalds * - Contour Design (Contour Mouse) 25*1da177e4SLinus Torvalds * - Hunter digital (NoHandsMouse) 26*1da177e4SLinus Torvalds * - Kensignton TurboMouse 5 (needs testing) 27*1da177e4SLinus Torvalds * - Mouse Systems A3 mice and trackballs <aidan@kublai.com> 28*1da177e4SLinus Torvalds * - MacAlly 2-buttons mouse (needs testing) <pochini@denise.shiny.it> 29*1da177e4SLinus Torvalds * 30*1da177e4SLinus Torvalds * To do: 31*1da177e4SLinus Torvalds * 32*1da177e4SLinus Torvalds * Improve Kensington support. 33*1da177e4SLinus Torvalds * Split mouse/kbd 34*1da177e4SLinus Torvalds * Move to syfs 35*1da177e4SLinus Torvalds */ 36*1da177e4SLinus Torvalds 37*1da177e4SLinus Torvalds #include <linux/config.h> 38*1da177e4SLinus Torvalds #include <linux/module.h> 39*1da177e4SLinus Torvalds #include <linux/slab.h> 40*1da177e4SLinus Torvalds #include <linux/init.h> 41*1da177e4SLinus Torvalds #include <linux/notifier.h> 42*1da177e4SLinus Torvalds #include <linux/input.h> 43*1da177e4SLinus Torvalds 44*1da177e4SLinus Torvalds #include <linux/adb.h> 45*1da177e4SLinus Torvalds #include <linux/cuda.h> 46*1da177e4SLinus Torvalds #include <linux/pmu.h> 47*1da177e4SLinus Torvalds 48*1da177e4SLinus Torvalds #include <asm/machdep.h> 49*1da177e4SLinus Torvalds #ifdef CONFIG_PPC_PMAC 50*1da177e4SLinus Torvalds #include <asm/pmac_feature.h> 51*1da177e4SLinus Torvalds #endif 52*1da177e4SLinus Torvalds 53*1da177e4SLinus Torvalds #ifdef CONFIG_PMAC_BACKLIGHT 54*1da177e4SLinus Torvalds #include <asm/backlight.h> 55*1da177e4SLinus Torvalds #endif 56*1da177e4SLinus Torvalds 57*1da177e4SLinus Torvalds MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>"); 58*1da177e4SLinus Torvalds 59*1da177e4SLinus Torvalds #define KEYB_KEYREG 0 /* register # for key up/down data */ 60*1da177e4SLinus Torvalds #define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */ 61*1da177e4SLinus Torvalds #define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */ 62*1da177e4SLinus Torvalds 63*1da177e4SLinus Torvalds static int adb_message_handler(struct notifier_block *, unsigned long, void *); 64*1da177e4SLinus Torvalds static struct notifier_block adbhid_adb_notifier = { 65*1da177e4SLinus Torvalds .notifier_call = adb_message_handler, 66*1da177e4SLinus Torvalds }; 67*1da177e4SLinus Torvalds 68*1da177e4SLinus Torvalds /* Some special keys */ 69*1da177e4SLinus Torvalds #define ADB_KEY_DEL 0x33 70*1da177e4SLinus Torvalds #define ADB_KEY_CMD 0x37 71*1da177e4SLinus Torvalds #define ADB_KEY_CAPSLOCK 0x39 72*1da177e4SLinus Torvalds #define ADB_KEY_FN 0x3f 73*1da177e4SLinus Torvalds #define ADB_KEY_FWDEL 0x75 74*1da177e4SLinus Torvalds #define ADB_KEY_POWER_OLD 0x7e 75*1da177e4SLinus Torvalds #define ADB_KEY_POWER 0x7f 76*1da177e4SLinus Torvalds 77*1da177e4SLinus Torvalds u8 adb_to_linux_keycodes[128] = { 78*1da177e4SLinus Torvalds /* 0x00 */ KEY_A, /* 30 */ 79*1da177e4SLinus Torvalds /* 0x01 */ KEY_S, /* 31 */ 80*1da177e4SLinus Torvalds /* 0x02 */ KEY_D, /* 32 */ 81*1da177e4SLinus Torvalds /* 0x03 */ KEY_F, /* 33 */ 82*1da177e4SLinus Torvalds /* 0x04 */ KEY_H, /* 35 */ 83*1da177e4SLinus Torvalds /* 0x05 */ KEY_G, /* 34 */ 84*1da177e4SLinus Torvalds /* 0x06 */ KEY_Z, /* 44 */ 85*1da177e4SLinus Torvalds /* 0x07 */ KEY_X, /* 45 */ 86*1da177e4SLinus Torvalds /* 0x08 */ KEY_C, /* 46 */ 87*1da177e4SLinus Torvalds /* 0x09 */ KEY_V, /* 47 */ 88*1da177e4SLinus Torvalds /* 0x0a */ KEY_102ND, /* 86 */ 89*1da177e4SLinus Torvalds /* 0x0b */ KEY_B, /* 48 */ 90*1da177e4SLinus Torvalds /* 0x0c */ KEY_Q, /* 16 */ 91*1da177e4SLinus Torvalds /* 0x0d */ KEY_W, /* 17 */ 92*1da177e4SLinus Torvalds /* 0x0e */ KEY_E, /* 18 */ 93*1da177e4SLinus Torvalds /* 0x0f */ KEY_R, /* 19 */ 94*1da177e4SLinus Torvalds /* 0x10 */ KEY_Y, /* 21 */ 95*1da177e4SLinus Torvalds /* 0x11 */ KEY_T, /* 20 */ 96*1da177e4SLinus Torvalds /* 0x12 */ KEY_1, /* 2 */ 97*1da177e4SLinus Torvalds /* 0x13 */ KEY_2, /* 3 */ 98*1da177e4SLinus Torvalds /* 0x14 */ KEY_3, /* 4 */ 99*1da177e4SLinus Torvalds /* 0x15 */ KEY_4, /* 5 */ 100*1da177e4SLinus Torvalds /* 0x16 */ KEY_6, /* 7 */ 101*1da177e4SLinus Torvalds /* 0x17 */ KEY_5, /* 6 */ 102*1da177e4SLinus Torvalds /* 0x18 */ KEY_EQUAL, /* 13 */ 103*1da177e4SLinus Torvalds /* 0x19 */ KEY_9, /* 10 */ 104*1da177e4SLinus Torvalds /* 0x1a */ KEY_7, /* 8 */ 105*1da177e4SLinus Torvalds /* 0x1b */ KEY_MINUS, /* 12 */ 106*1da177e4SLinus Torvalds /* 0x1c */ KEY_8, /* 9 */ 107*1da177e4SLinus Torvalds /* 0x1d */ KEY_0, /* 11 */ 108*1da177e4SLinus Torvalds /* 0x1e */ KEY_RIGHTBRACE, /* 27 */ 109*1da177e4SLinus Torvalds /* 0x1f */ KEY_O, /* 24 */ 110*1da177e4SLinus Torvalds /* 0x20 */ KEY_U, /* 22 */ 111*1da177e4SLinus Torvalds /* 0x21 */ KEY_LEFTBRACE, /* 26 */ 112*1da177e4SLinus Torvalds /* 0x22 */ KEY_I, /* 23 */ 113*1da177e4SLinus Torvalds /* 0x23 */ KEY_P, /* 25 */ 114*1da177e4SLinus Torvalds /* 0x24 */ KEY_ENTER, /* 28 */ 115*1da177e4SLinus Torvalds /* 0x25 */ KEY_L, /* 38 */ 116*1da177e4SLinus Torvalds /* 0x26 */ KEY_J, /* 36 */ 117*1da177e4SLinus Torvalds /* 0x27 */ KEY_APOSTROPHE, /* 40 */ 118*1da177e4SLinus Torvalds /* 0x28 */ KEY_K, /* 37 */ 119*1da177e4SLinus Torvalds /* 0x29 */ KEY_SEMICOLON, /* 39 */ 120*1da177e4SLinus Torvalds /* 0x2a */ KEY_BACKSLASH, /* 43 */ 121*1da177e4SLinus Torvalds /* 0x2b */ KEY_COMMA, /* 51 */ 122*1da177e4SLinus Torvalds /* 0x2c */ KEY_SLASH, /* 53 */ 123*1da177e4SLinus Torvalds /* 0x2d */ KEY_N, /* 49 */ 124*1da177e4SLinus Torvalds /* 0x2e */ KEY_M, /* 50 */ 125*1da177e4SLinus Torvalds /* 0x2f */ KEY_DOT, /* 52 */ 126*1da177e4SLinus Torvalds /* 0x30 */ KEY_TAB, /* 15 */ 127*1da177e4SLinus Torvalds /* 0x31 */ KEY_SPACE, /* 57 */ 128*1da177e4SLinus Torvalds /* 0x32 */ KEY_GRAVE, /* 41 */ 129*1da177e4SLinus Torvalds /* 0x33 */ KEY_BACKSPACE, /* 14 */ 130*1da177e4SLinus Torvalds /* 0x34 */ KEY_KPENTER, /* 96 */ 131*1da177e4SLinus Torvalds /* 0x35 */ KEY_ESC, /* 1 */ 132*1da177e4SLinus Torvalds /* 0x36 */ KEY_LEFTCTRL, /* 29 */ 133*1da177e4SLinus Torvalds /* 0x37 */ KEY_LEFTMETA, /* 125 */ 134*1da177e4SLinus Torvalds /* 0x38 */ KEY_LEFTSHIFT, /* 42 */ 135*1da177e4SLinus Torvalds /* 0x39 */ KEY_CAPSLOCK, /* 58 */ 136*1da177e4SLinus Torvalds /* 0x3a */ KEY_LEFTALT, /* 56 */ 137*1da177e4SLinus Torvalds /* 0x3b */ KEY_LEFT, /* 105 */ 138*1da177e4SLinus Torvalds /* 0x3c */ KEY_RIGHT, /* 106 */ 139*1da177e4SLinus Torvalds /* 0x3d */ KEY_DOWN, /* 108 */ 140*1da177e4SLinus Torvalds /* 0x3e */ KEY_UP, /* 103 */ 141*1da177e4SLinus Torvalds /* 0x3f */ 0, 142*1da177e4SLinus Torvalds /* 0x40 */ 0, 143*1da177e4SLinus Torvalds /* 0x41 */ KEY_KPDOT, /* 83 */ 144*1da177e4SLinus Torvalds /* 0x42 */ 0, 145*1da177e4SLinus Torvalds /* 0x43 */ KEY_KPASTERISK, /* 55 */ 146*1da177e4SLinus Torvalds /* 0x44 */ 0, 147*1da177e4SLinus Torvalds /* 0x45 */ KEY_KPPLUS, /* 78 */ 148*1da177e4SLinus Torvalds /* 0x46 */ 0, 149*1da177e4SLinus Torvalds /* 0x47 */ KEY_NUMLOCK, /* 69 */ 150*1da177e4SLinus Torvalds /* 0x48 */ 0, 151*1da177e4SLinus Torvalds /* 0x49 */ 0, 152*1da177e4SLinus Torvalds /* 0x4a */ 0, 153*1da177e4SLinus Torvalds /* 0x4b */ KEY_KPSLASH, /* 98 */ 154*1da177e4SLinus Torvalds /* 0x4c */ KEY_KPENTER, /* 96 */ 155*1da177e4SLinus Torvalds /* 0x4d */ 0, 156*1da177e4SLinus Torvalds /* 0x4e */ KEY_KPMINUS, /* 74 */ 157*1da177e4SLinus Torvalds /* 0x4f */ 0, 158*1da177e4SLinus Torvalds /* 0x50 */ 0, 159*1da177e4SLinus Torvalds /* 0x51 */ KEY_KPEQUAL, /* 117 */ 160*1da177e4SLinus Torvalds /* 0x52 */ KEY_KP0, /* 82 */ 161*1da177e4SLinus Torvalds /* 0x53 */ KEY_KP1, /* 79 */ 162*1da177e4SLinus Torvalds /* 0x54 */ KEY_KP2, /* 80 */ 163*1da177e4SLinus Torvalds /* 0x55 */ KEY_KP3, /* 81 */ 164*1da177e4SLinus Torvalds /* 0x56 */ KEY_KP4, /* 75 */ 165*1da177e4SLinus Torvalds /* 0x57 */ KEY_KP5, /* 76 */ 166*1da177e4SLinus Torvalds /* 0x58 */ KEY_KP6, /* 77 */ 167*1da177e4SLinus Torvalds /* 0x59 */ KEY_KP7, /* 71 */ 168*1da177e4SLinus Torvalds /* 0x5a */ 0, 169*1da177e4SLinus Torvalds /* 0x5b */ KEY_KP8, /* 72 */ 170*1da177e4SLinus Torvalds /* 0x5c */ KEY_KP9, /* 73 */ 171*1da177e4SLinus Torvalds /* 0x5d */ KEY_YEN, /* 124 */ 172*1da177e4SLinus Torvalds /* 0x5e */ KEY_RO, /* 89 */ 173*1da177e4SLinus Torvalds /* 0x5f */ KEY_KPCOMMA, /* 121 */ 174*1da177e4SLinus Torvalds /* 0x60 */ KEY_F5, /* 63 */ 175*1da177e4SLinus Torvalds /* 0x61 */ KEY_F6, /* 64 */ 176*1da177e4SLinus Torvalds /* 0x62 */ KEY_F7, /* 65 */ 177*1da177e4SLinus Torvalds /* 0x63 */ KEY_F3, /* 61 */ 178*1da177e4SLinus Torvalds /* 0x64 */ KEY_F8, /* 66 */ 179*1da177e4SLinus Torvalds /* 0x65 */ KEY_F9, /* 67 */ 180*1da177e4SLinus Torvalds /* 0x66 */ KEY_HANJA, /* 123 */ 181*1da177e4SLinus Torvalds /* 0x67 */ KEY_F11, /* 87 */ 182*1da177e4SLinus Torvalds /* 0x68 */ KEY_HANGUEL, /* 122 */ 183*1da177e4SLinus Torvalds /* 0x69 */ KEY_SYSRQ, /* 99 */ 184*1da177e4SLinus Torvalds /* 0x6a */ 0, 185*1da177e4SLinus Torvalds /* 0x6b */ KEY_SCROLLLOCK, /* 70 */ 186*1da177e4SLinus Torvalds /* 0x6c */ 0, 187*1da177e4SLinus Torvalds /* 0x6d */ KEY_F10, /* 68 */ 188*1da177e4SLinus Torvalds /* 0x6e */ KEY_COMPOSE, /* 127 */ 189*1da177e4SLinus Torvalds /* 0x6f */ KEY_F12, /* 88 */ 190*1da177e4SLinus Torvalds /* 0x70 */ 0, 191*1da177e4SLinus Torvalds /* 0x71 */ KEY_PAUSE, /* 119 */ 192*1da177e4SLinus Torvalds /* 0x72 */ KEY_INSERT, /* 110 */ 193*1da177e4SLinus Torvalds /* 0x73 */ KEY_HOME, /* 102 */ 194*1da177e4SLinus Torvalds /* 0x74 */ KEY_PAGEUP, /* 104 */ 195*1da177e4SLinus Torvalds /* 0x75 */ KEY_DELETE, /* 111 */ 196*1da177e4SLinus Torvalds /* 0x76 */ KEY_F4, /* 62 */ 197*1da177e4SLinus Torvalds /* 0x77 */ KEY_END, /* 107 */ 198*1da177e4SLinus Torvalds /* 0x78 */ KEY_F2, /* 60 */ 199*1da177e4SLinus Torvalds /* 0x79 */ KEY_PAGEDOWN, /* 109 */ 200*1da177e4SLinus Torvalds /* 0x7a */ KEY_F1, /* 59 */ 201*1da177e4SLinus Torvalds /* 0x7b */ KEY_RIGHTSHIFT, /* 54 */ 202*1da177e4SLinus Torvalds /* 0x7c */ KEY_RIGHTALT, /* 100 */ 203*1da177e4SLinus Torvalds /* 0x7d */ KEY_RIGHTCTRL, /* 97 */ 204*1da177e4SLinus Torvalds /* 0x7e */ KEY_RIGHTMETA, /* 126 */ 205*1da177e4SLinus Torvalds /* 0x7f */ KEY_POWER, /* 116 */ 206*1da177e4SLinus Torvalds }; 207*1da177e4SLinus Torvalds 208*1da177e4SLinus Torvalds struct adbhid { 209*1da177e4SLinus Torvalds struct input_dev input; 210*1da177e4SLinus Torvalds int id; 211*1da177e4SLinus Torvalds int default_id; 212*1da177e4SLinus Torvalds int original_handler_id; 213*1da177e4SLinus Torvalds int current_handler_id; 214*1da177e4SLinus Torvalds int mouse_kind; 215*1da177e4SLinus Torvalds unsigned char *keycode; 216*1da177e4SLinus Torvalds char name[64]; 217*1da177e4SLinus Torvalds char phys[32]; 218*1da177e4SLinus Torvalds int flags; 219*1da177e4SLinus Torvalds }; 220*1da177e4SLinus Torvalds 221*1da177e4SLinus Torvalds #define FLAG_FN_KEY_PRESSED 0x00000001 222*1da177e4SLinus Torvalds #define FLAG_POWER_FROM_FN 0x00000002 223*1da177e4SLinus Torvalds #define FLAG_EMU_FWDEL_DOWN 0x00000004 224*1da177e4SLinus Torvalds 225*1da177e4SLinus Torvalds static struct adbhid *adbhid[16]; 226*1da177e4SLinus Torvalds 227*1da177e4SLinus Torvalds static void adbhid_probe(void); 228*1da177e4SLinus Torvalds 229*1da177e4SLinus Torvalds static void adbhid_input_keycode(int, int, int, struct pt_regs *); 230*1da177e4SLinus Torvalds 231*1da177e4SLinus Torvalds static void init_trackpad(int id); 232*1da177e4SLinus Torvalds static void init_trackball(int id); 233*1da177e4SLinus Torvalds static void init_turbomouse(int id); 234*1da177e4SLinus Torvalds static void init_microspeed(int id); 235*1da177e4SLinus Torvalds static void init_ms_a3(int id); 236*1da177e4SLinus Torvalds 237*1da177e4SLinus Torvalds static struct adb_ids keyboard_ids; 238*1da177e4SLinus Torvalds static struct adb_ids mouse_ids; 239*1da177e4SLinus Torvalds static struct adb_ids buttons_ids; 240*1da177e4SLinus Torvalds 241*1da177e4SLinus Torvalds #ifdef CONFIG_PMAC_BACKLIGHT 242*1da177e4SLinus Torvalds /* Exported to via-pmu.c */ 243*1da177e4SLinus Torvalds int disable_kernel_backlight = 0; 244*1da177e4SLinus Torvalds #endif /* CONFIG_PMAC_BACKLIGHT */ 245*1da177e4SLinus Torvalds 246*1da177e4SLinus Torvalds /* Kind of keyboard, see Apple technote 1152 */ 247*1da177e4SLinus Torvalds #define ADB_KEYBOARD_UNKNOWN 0 248*1da177e4SLinus Torvalds #define ADB_KEYBOARD_ANSI 0x0100 249*1da177e4SLinus Torvalds #define ADB_KEYBOARD_ISO 0x0200 250*1da177e4SLinus Torvalds #define ADB_KEYBOARD_JIS 0x0300 251*1da177e4SLinus Torvalds 252*1da177e4SLinus Torvalds /* Kind of mouse */ 253*1da177e4SLinus Torvalds #define ADBMOUSE_STANDARD_100 0 /* Standard 100cpi mouse (handler 1) */ 254*1da177e4SLinus Torvalds #define ADBMOUSE_STANDARD_200 1 /* Standard 200cpi mouse (handler 2) */ 255*1da177e4SLinus Torvalds #define ADBMOUSE_EXTENDED 2 /* Apple Extended mouse (handler 4) */ 256*1da177e4SLinus Torvalds #define ADBMOUSE_TRACKBALL 3 /* TrackBall (handler 4) */ 257*1da177e4SLinus Torvalds #define ADBMOUSE_TRACKPAD 4 /* Apple's PowerBook trackpad (handler 4) */ 258*1da177e4SLinus Torvalds #define ADBMOUSE_TURBOMOUSE5 5 /* Turbomouse 5 (previously req. mousehack) */ 259*1da177e4SLinus Torvalds #define ADBMOUSE_MICROSPEED 6 /* Microspeed mouse (&trackball ?), MacPoint */ 260*1da177e4SLinus Torvalds #define ADBMOUSE_TRACKBALLPRO 7 /* Trackball Pro (special buttons) */ 261*1da177e4SLinus Torvalds #define ADBMOUSE_MS_A3 8 /* Mouse systems A3 trackball (handler 3) */ 262*1da177e4SLinus Torvalds #define ADBMOUSE_MACALLY2 9 /* MacAlly 2-button mouse */ 263*1da177e4SLinus Torvalds 264*1da177e4SLinus Torvalds static void 265*1da177e4SLinus Torvalds adbhid_keyboard_input(unsigned char *data, int nb, struct pt_regs *regs, int apoll) 266*1da177e4SLinus Torvalds { 267*1da177e4SLinus Torvalds int id = (data[0] >> 4) & 0x0f; 268*1da177e4SLinus Torvalds 269*1da177e4SLinus Torvalds if (!adbhid[id]) { 270*1da177e4SLinus Torvalds printk(KERN_ERR "ADB HID on ID %d not yet registered, packet %#02x, %#02x, %#02x, %#02x\n", 271*1da177e4SLinus Torvalds id, data[0], data[1], data[2], data[3]); 272*1da177e4SLinus Torvalds return; 273*1da177e4SLinus Torvalds } 274*1da177e4SLinus Torvalds 275*1da177e4SLinus Torvalds /* first check this is from register 0 */ 276*1da177e4SLinus Torvalds if (nb != 3 || (data[0] & 3) != KEYB_KEYREG) 277*1da177e4SLinus Torvalds return; /* ignore it */ 278*1da177e4SLinus Torvalds adbhid_input_keycode(id, data[1], 0, regs); 279*1da177e4SLinus Torvalds if (!(data[2] == 0xff || (data[2] == 0x7f && data[1] == 0x7f))) 280*1da177e4SLinus Torvalds adbhid_input_keycode(id, data[2], 0, regs); 281*1da177e4SLinus Torvalds } 282*1da177e4SLinus Torvalds 283*1da177e4SLinus Torvalds static void 284*1da177e4SLinus Torvalds adbhid_input_keycode(int id, int keycode, int repeat, struct pt_regs *regs) 285*1da177e4SLinus Torvalds { 286*1da177e4SLinus Torvalds struct adbhid *ahid = adbhid[id]; 287*1da177e4SLinus Torvalds int up_flag; 288*1da177e4SLinus Torvalds 289*1da177e4SLinus Torvalds up_flag = (keycode & 0x80); 290*1da177e4SLinus Torvalds keycode &= 0x7f; 291*1da177e4SLinus Torvalds 292*1da177e4SLinus Torvalds switch (keycode) { 293*1da177e4SLinus Torvalds case ADB_KEY_CAPSLOCK: /* Generate down/up events for CapsLock everytime. */ 294*1da177e4SLinus Torvalds input_regs(&ahid->input, regs); 295*1da177e4SLinus Torvalds input_report_key(&ahid->input, KEY_CAPSLOCK, 1); 296*1da177e4SLinus Torvalds input_report_key(&ahid->input, KEY_CAPSLOCK, 0); 297*1da177e4SLinus Torvalds input_sync(&ahid->input); 298*1da177e4SLinus Torvalds return; 299*1da177e4SLinus Torvalds #ifdef CONFIG_PPC_PMAC 300*1da177e4SLinus Torvalds case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */ 301*1da177e4SLinus Torvalds switch(pmac_call_feature(PMAC_FTR_GET_MB_INFO, 302*1da177e4SLinus Torvalds NULL, PMAC_MB_INFO_MODEL, 0)) { 303*1da177e4SLinus Torvalds case PMAC_TYPE_COMET: 304*1da177e4SLinus Torvalds case PMAC_TYPE_HOOPER: 305*1da177e4SLinus Torvalds case PMAC_TYPE_KANGA: 306*1da177e4SLinus Torvalds keycode = ADB_KEY_POWER; 307*1da177e4SLinus Torvalds } 308*1da177e4SLinus Torvalds break; 309*1da177e4SLinus Torvalds case ADB_KEY_POWER: 310*1da177e4SLinus Torvalds /* Fn + Command will produce a bogus "power" keycode */ 311*1da177e4SLinus Torvalds if (ahid->flags & FLAG_FN_KEY_PRESSED) { 312*1da177e4SLinus Torvalds keycode = ADB_KEY_CMD; 313*1da177e4SLinus Torvalds if (up_flag) 314*1da177e4SLinus Torvalds ahid->flags &= ~FLAG_POWER_FROM_FN; 315*1da177e4SLinus Torvalds else 316*1da177e4SLinus Torvalds ahid->flags |= FLAG_POWER_FROM_FN; 317*1da177e4SLinus Torvalds } else if (ahid->flags & FLAG_POWER_FROM_FN) { 318*1da177e4SLinus Torvalds keycode = ADB_KEY_CMD; 319*1da177e4SLinus Torvalds ahid->flags &= ~FLAG_POWER_FROM_FN; 320*1da177e4SLinus Torvalds } 321*1da177e4SLinus Torvalds break; 322*1da177e4SLinus Torvalds case ADB_KEY_FN: 323*1da177e4SLinus Torvalds /* Keep track of the Fn key state */ 324*1da177e4SLinus Torvalds if (up_flag) { 325*1da177e4SLinus Torvalds ahid->flags &= ~FLAG_FN_KEY_PRESSED; 326*1da177e4SLinus Torvalds /* Emulate Fn+delete = forward delete */ 327*1da177e4SLinus Torvalds if (ahid->flags & FLAG_EMU_FWDEL_DOWN) { 328*1da177e4SLinus Torvalds ahid->flags &= ~FLAG_EMU_FWDEL_DOWN; 329*1da177e4SLinus Torvalds keycode = ADB_KEY_FWDEL; 330*1da177e4SLinus Torvalds break; 331*1da177e4SLinus Torvalds } 332*1da177e4SLinus Torvalds } else 333*1da177e4SLinus Torvalds ahid->flags |= FLAG_FN_KEY_PRESSED; 334*1da177e4SLinus Torvalds /* Swallow the key press */ 335*1da177e4SLinus Torvalds return; 336*1da177e4SLinus Torvalds case ADB_KEY_DEL: 337*1da177e4SLinus Torvalds /* Emulate Fn+delete = forward delete */ 338*1da177e4SLinus Torvalds if (ahid->flags & FLAG_FN_KEY_PRESSED) { 339*1da177e4SLinus Torvalds keycode = ADB_KEY_FWDEL; 340*1da177e4SLinus Torvalds if (up_flag) 341*1da177e4SLinus Torvalds ahid->flags &= ~FLAG_EMU_FWDEL_DOWN; 342*1da177e4SLinus Torvalds else 343*1da177e4SLinus Torvalds ahid->flags |= FLAG_EMU_FWDEL_DOWN; 344*1da177e4SLinus Torvalds } 345*1da177e4SLinus Torvalds break; 346*1da177e4SLinus Torvalds #endif /* CONFIG_PPC_PMAC */ 347*1da177e4SLinus Torvalds } 348*1da177e4SLinus Torvalds 349*1da177e4SLinus Torvalds if (adbhid[id]->keycode[keycode]) { 350*1da177e4SLinus Torvalds input_regs(&adbhid[id]->input, regs); 351*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, 352*1da177e4SLinus Torvalds adbhid[id]->keycode[keycode], !up_flag); 353*1da177e4SLinus Torvalds input_sync(&adbhid[id]->input); 354*1da177e4SLinus Torvalds } else 355*1da177e4SLinus Torvalds printk(KERN_INFO "Unhandled ADB key (scancode %#02x) %s.\n", keycode, 356*1da177e4SLinus Torvalds up_flag ? "released" : "pressed"); 357*1da177e4SLinus Torvalds 358*1da177e4SLinus Torvalds } 359*1da177e4SLinus Torvalds 360*1da177e4SLinus Torvalds static void 361*1da177e4SLinus Torvalds adbhid_mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll) 362*1da177e4SLinus Torvalds { 363*1da177e4SLinus Torvalds int id = (data[0] >> 4) & 0x0f; 364*1da177e4SLinus Torvalds 365*1da177e4SLinus Torvalds if (!adbhid[id]) { 366*1da177e4SLinus Torvalds printk(KERN_ERR "ADB HID on ID %d not yet registered\n", id); 367*1da177e4SLinus Torvalds return; 368*1da177e4SLinus Torvalds } 369*1da177e4SLinus Torvalds 370*1da177e4SLinus Torvalds /* 371*1da177e4SLinus Torvalds Handler 1 -- 100cpi original Apple mouse protocol. 372*1da177e4SLinus Torvalds Handler 2 -- 200cpi original Apple mouse protocol. 373*1da177e4SLinus Torvalds 374*1da177e4SLinus Torvalds For Apple's standard one-button mouse protocol the data array will 375*1da177e4SLinus Torvalds contain the following values: 376*1da177e4SLinus Torvalds 377*1da177e4SLinus Torvalds BITS COMMENTS 378*1da177e4SLinus Torvalds data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd. 379*1da177e4SLinus Torvalds data[1] = bxxx xxxx First button and x-axis motion. 380*1da177e4SLinus Torvalds data[2] = byyy yyyy Second button and y-axis motion. 381*1da177e4SLinus Torvalds 382*1da177e4SLinus Torvalds Handler 4 -- Apple Extended mouse protocol. 383*1da177e4SLinus Torvalds 384*1da177e4SLinus Torvalds For Apple's 3-button mouse protocol the data array will contain the 385*1da177e4SLinus Torvalds following values: 386*1da177e4SLinus Torvalds 387*1da177e4SLinus Torvalds BITS COMMENTS 388*1da177e4SLinus Torvalds data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd. 389*1da177e4SLinus Torvalds data[1] = bxxx xxxx Left button and x-axis motion. 390*1da177e4SLinus Torvalds data[2] = byyy yyyy Second button and y-axis motion. 391*1da177e4SLinus Torvalds data[3] = byyy bxxx Third button and fourth button. Y is additional 392*1da177e4SLinus Torvalds high bits of y-axis motion. XY is additional 393*1da177e4SLinus Torvalds high bits of x-axis motion. 394*1da177e4SLinus Torvalds 395*1da177e4SLinus Torvalds MacAlly 2-button mouse protocol. 396*1da177e4SLinus Torvalds 397*1da177e4SLinus Torvalds For MacAlly 2-button mouse protocol the data array will contain the 398*1da177e4SLinus Torvalds following values: 399*1da177e4SLinus Torvalds 400*1da177e4SLinus Torvalds BITS COMMENTS 401*1da177e4SLinus Torvalds data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd. 402*1da177e4SLinus Torvalds data[1] = bxxx xxxx Left button and x-axis motion. 403*1da177e4SLinus Torvalds data[2] = byyy yyyy Right button and y-axis motion. 404*1da177e4SLinus Torvalds data[3] = ???? ???? unknown 405*1da177e4SLinus Torvalds data[4] = ???? ???? unknown 406*1da177e4SLinus Torvalds 407*1da177e4SLinus Torvalds */ 408*1da177e4SLinus Torvalds 409*1da177e4SLinus Torvalds /* If it's a trackpad, we alias the second button to the first. 410*1da177e4SLinus Torvalds NOTE: Apple sends an ADB flush command to the trackpad when 411*1da177e4SLinus Torvalds the first (the real) button is released. We could do 412*1da177e4SLinus Torvalds this here using async flush requests. 413*1da177e4SLinus Torvalds */ 414*1da177e4SLinus Torvalds switch (adbhid[id]->mouse_kind) 415*1da177e4SLinus Torvalds { 416*1da177e4SLinus Torvalds case ADBMOUSE_TRACKPAD: 417*1da177e4SLinus Torvalds data[1] = (data[1] & 0x7f) | ((data[1] & data[2]) & 0x80); 418*1da177e4SLinus Torvalds data[2] = data[2] | 0x80; 419*1da177e4SLinus Torvalds break; 420*1da177e4SLinus Torvalds case ADBMOUSE_MICROSPEED: 421*1da177e4SLinus Torvalds data[1] = (data[1] & 0x7f) | ((data[3] & 0x01) << 7); 422*1da177e4SLinus Torvalds data[2] = (data[2] & 0x7f) | ((data[3] & 0x02) << 6); 423*1da177e4SLinus Torvalds data[3] = (data[3] & 0x77) | ((data[3] & 0x04) << 5) 424*1da177e4SLinus Torvalds | (data[3] & 0x08); 425*1da177e4SLinus Torvalds break; 426*1da177e4SLinus Torvalds case ADBMOUSE_TRACKBALLPRO: 427*1da177e4SLinus Torvalds data[1] = (data[1] & 0x7f) | (((data[3] & 0x04) << 5) 428*1da177e4SLinus Torvalds & ((data[3] & 0x08) << 4)); 429*1da177e4SLinus Torvalds data[2] = (data[2] & 0x7f) | ((data[3] & 0x01) << 7); 430*1da177e4SLinus Torvalds data[3] = (data[3] & 0x77) | ((data[3] & 0x02) << 6); 431*1da177e4SLinus Torvalds break; 432*1da177e4SLinus Torvalds case ADBMOUSE_MS_A3: 433*1da177e4SLinus Torvalds data[1] = (data[1] & 0x7f) | ((data[3] & 0x01) << 7); 434*1da177e4SLinus Torvalds data[2] = (data[2] & 0x7f) | ((data[3] & 0x02) << 6); 435*1da177e4SLinus Torvalds data[3] = ((data[3] & 0x04) << 5); 436*1da177e4SLinus Torvalds break; 437*1da177e4SLinus Torvalds case ADBMOUSE_MACALLY2: 438*1da177e4SLinus Torvalds data[3] = (data[2] & 0x80) ? 0x80 : 0x00; 439*1da177e4SLinus Torvalds data[2] |= 0x80; /* Right button is mapped as button 3 */ 440*1da177e4SLinus Torvalds nb=4; 441*1da177e4SLinus Torvalds break; 442*1da177e4SLinus Torvalds } 443*1da177e4SLinus Torvalds 444*1da177e4SLinus Torvalds input_regs(&adbhid[id]->input, regs); 445*1da177e4SLinus Torvalds 446*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, BTN_LEFT, !((data[1] >> 7) & 1)); 447*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1)); 448*1da177e4SLinus Torvalds 449*1da177e4SLinus Torvalds if (nb >= 4 && adbhid[id]->mouse_kind != ADBMOUSE_TRACKPAD) 450*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, BTN_RIGHT, !((data[3] >> 7) & 1)); 451*1da177e4SLinus Torvalds 452*1da177e4SLinus Torvalds input_report_rel(&adbhid[id]->input, REL_X, 453*1da177e4SLinus Torvalds ((data[2]&0x7f) < 64 ? (data[2]&0x7f) : (data[2]&0x7f)-128 )); 454*1da177e4SLinus Torvalds input_report_rel(&adbhid[id]->input, REL_Y, 455*1da177e4SLinus Torvalds ((data[1]&0x7f) < 64 ? (data[1]&0x7f) : (data[1]&0x7f)-128 )); 456*1da177e4SLinus Torvalds 457*1da177e4SLinus Torvalds input_sync(&adbhid[id]->input); 458*1da177e4SLinus Torvalds } 459*1da177e4SLinus Torvalds 460*1da177e4SLinus Torvalds static void 461*1da177e4SLinus Torvalds adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll) 462*1da177e4SLinus Torvalds { 463*1da177e4SLinus Torvalds int id = (data[0] >> 4) & 0x0f; 464*1da177e4SLinus Torvalds 465*1da177e4SLinus Torvalds if (!adbhid[id]) { 466*1da177e4SLinus Torvalds printk(KERN_ERR "ADB HID on ID %d not yet registered\n", id); 467*1da177e4SLinus Torvalds return; 468*1da177e4SLinus Torvalds } 469*1da177e4SLinus Torvalds 470*1da177e4SLinus Torvalds input_regs(&adbhid[id]->input, regs); 471*1da177e4SLinus Torvalds 472*1da177e4SLinus Torvalds switch (adbhid[id]->original_handler_id) { 473*1da177e4SLinus Torvalds default: 474*1da177e4SLinus Torvalds case 0x02: /* Adjustable keyboard button device */ 475*1da177e4SLinus Torvalds { 476*1da177e4SLinus Torvalds int down = (data[1] == (data[1] & 0xf)); 477*1da177e4SLinus Torvalds 478*1da177e4SLinus Torvalds switch (data[1] & 0x0f) { 479*1da177e4SLinus Torvalds case 0x0: /* microphone */ 480*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, KEY_SOUND, down); 481*1da177e4SLinus Torvalds break; 482*1da177e4SLinus Torvalds 483*1da177e4SLinus Torvalds case 0x1: /* mute */ 484*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, KEY_MUTE, down); 485*1da177e4SLinus Torvalds break; 486*1da177e4SLinus Torvalds 487*1da177e4SLinus Torvalds case 0x2: /* volume decrease */ 488*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, KEY_VOLUMEDOWN, down); 489*1da177e4SLinus Torvalds break; 490*1da177e4SLinus Torvalds 491*1da177e4SLinus Torvalds case 0x3: /* volume increase */ 492*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, KEY_VOLUMEUP, down); 493*1da177e4SLinus Torvalds break; 494*1da177e4SLinus Torvalds 495*1da177e4SLinus Torvalds default: 496*1da177e4SLinus Torvalds printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n", 497*1da177e4SLinus Torvalds data[0], data[1], data[2], data[3]); 498*1da177e4SLinus Torvalds break; 499*1da177e4SLinus Torvalds } 500*1da177e4SLinus Torvalds } 501*1da177e4SLinus Torvalds break; 502*1da177e4SLinus Torvalds 503*1da177e4SLinus Torvalds case 0x1f: /* Powerbook button device */ 504*1da177e4SLinus Torvalds { 505*1da177e4SLinus Torvalds int down = (data[1] == (data[1] & 0xf)); 506*1da177e4SLinus Torvalds #ifdef CONFIG_PMAC_BACKLIGHT 507*1da177e4SLinus Torvalds int backlight = get_backlight_level(); 508*1da177e4SLinus Torvalds #endif 509*1da177e4SLinus Torvalds /* 510*1da177e4SLinus Torvalds * XXX: Where is the contrast control for the passive? 511*1da177e4SLinus Torvalds * -- Cort 512*1da177e4SLinus Torvalds */ 513*1da177e4SLinus Torvalds 514*1da177e4SLinus Torvalds switch (data[1] & 0x0f) { 515*1da177e4SLinus Torvalds case 0x8: /* mute */ 516*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, KEY_MUTE, down); 517*1da177e4SLinus Torvalds break; 518*1da177e4SLinus Torvalds 519*1da177e4SLinus Torvalds case 0x7: /* volume decrease */ 520*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, KEY_VOLUMEDOWN, down); 521*1da177e4SLinus Torvalds break; 522*1da177e4SLinus Torvalds 523*1da177e4SLinus Torvalds case 0x6: /* volume increase */ 524*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, KEY_VOLUMEUP, down); 525*1da177e4SLinus Torvalds break; 526*1da177e4SLinus Torvalds 527*1da177e4SLinus Torvalds case 0xb: /* eject */ 528*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, KEY_EJECTCD, down); 529*1da177e4SLinus Torvalds break; 530*1da177e4SLinus Torvalds 531*1da177e4SLinus Torvalds case 0xa: /* brightness decrease */ 532*1da177e4SLinus Torvalds #ifdef CONFIG_PMAC_BACKLIGHT 533*1da177e4SLinus Torvalds if (!disable_kernel_backlight) { 534*1da177e4SLinus Torvalds if (down && backlight >= 0) { 535*1da177e4SLinus Torvalds if (backlight > BACKLIGHT_OFF) 536*1da177e4SLinus Torvalds set_backlight_level(backlight-1); 537*1da177e4SLinus Torvalds else 538*1da177e4SLinus Torvalds set_backlight_level(BACKLIGHT_OFF); 539*1da177e4SLinus Torvalds } 540*1da177e4SLinus Torvalds } 541*1da177e4SLinus Torvalds #endif /* CONFIG_PMAC_BACKLIGHT */ 542*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSDOWN, down); 543*1da177e4SLinus Torvalds break; 544*1da177e4SLinus Torvalds 545*1da177e4SLinus Torvalds case 0x9: /* brightness increase */ 546*1da177e4SLinus Torvalds #ifdef CONFIG_PMAC_BACKLIGHT 547*1da177e4SLinus Torvalds if (!disable_kernel_backlight) { 548*1da177e4SLinus Torvalds if (down && backlight >= 0) { 549*1da177e4SLinus Torvalds if (backlight < BACKLIGHT_MAX) 550*1da177e4SLinus Torvalds set_backlight_level(backlight+1); 551*1da177e4SLinus Torvalds else 552*1da177e4SLinus Torvalds set_backlight_level(BACKLIGHT_MAX); 553*1da177e4SLinus Torvalds } 554*1da177e4SLinus Torvalds } 555*1da177e4SLinus Torvalds #endif /* CONFIG_PMAC_BACKLIGHT */ 556*1da177e4SLinus Torvalds input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSUP, down); 557*1da177e4SLinus Torvalds break; 558*1da177e4SLinus Torvalds } 559*1da177e4SLinus Torvalds } 560*1da177e4SLinus Torvalds break; 561*1da177e4SLinus Torvalds } 562*1da177e4SLinus Torvalds 563*1da177e4SLinus Torvalds input_sync(&adbhid[id]->input); 564*1da177e4SLinus Torvalds } 565*1da177e4SLinus Torvalds 566*1da177e4SLinus Torvalds static struct adb_request led_request; 567*1da177e4SLinus Torvalds static int leds_pending[16]; 568*1da177e4SLinus Torvalds static int leds_req_pending; 569*1da177e4SLinus Torvalds static int pending_devs[16]; 570*1da177e4SLinus Torvalds static int pending_led_start=0; 571*1da177e4SLinus Torvalds static int pending_led_end=0; 572*1da177e4SLinus Torvalds static DEFINE_SPINLOCK(leds_lock); 573*1da177e4SLinus Torvalds 574*1da177e4SLinus Torvalds static void leds_done(struct adb_request *req) 575*1da177e4SLinus Torvalds { 576*1da177e4SLinus Torvalds int leds = 0, device = 0, pending = 0; 577*1da177e4SLinus Torvalds unsigned long flags; 578*1da177e4SLinus Torvalds 579*1da177e4SLinus Torvalds spin_lock_irqsave(&leds_lock, flags); 580*1da177e4SLinus Torvalds 581*1da177e4SLinus Torvalds if (pending_led_start != pending_led_end) { 582*1da177e4SLinus Torvalds device = pending_devs[pending_led_start]; 583*1da177e4SLinus Torvalds leds = leds_pending[device] & 0xff; 584*1da177e4SLinus Torvalds leds_pending[device] = 0; 585*1da177e4SLinus Torvalds pending_led_start++; 586*1da177e4SLinus Torvalds pending_led_start = (pending_led_start < 16) ? pending_led_start : 0; 587*1da177e4SLinus Torvalds pending = leds_req_pending; 588*1da177e4SLinus Torvalds } else 589*1da177e4SLinus Torvalds leds_req_pending = 0; 590*1da177e4SLinus Torvalds spin_unlock_irqrestore(&leds_lock, flags); 591*1da177e4SLinus Torvalds if (pending) 592*1da177e4SLinus Torvalds adb_request(&led_request, leds_done, 0, 3, 593*1da177e4SLinus Torvalds ADB_WRITEREG(device, KEYB_LEDREG), 0xff, ~leds); 594*1da177e4SLinus Torvalds } 595*1da177e4SLinus Torvalds 596*1da177e4SLinus Torvalds static void real_leds(unsigned char leds, int device) 597*1da177e4SLinus Torvalds { 598*1da177e4SLinus Torvalds unsigned long flags; 599*1da177e4SLinus Torvalds 600*1da177e4SLinus Torvalds spin_lock_irqsave(&leds_lock, flags); 601*1da177e4SLinus Torvalds if (!leds_req_pending) { 602*1da177e4SLinus Torvalds leds_req_pending = 1; 603*1da177e4SLinus Torvalds spin_unlock_irqrestore(&leds_lock, flags); 604*1da177e4SLinus Torvalds adb_request(&led_request, leds_done, 0, 3, 605*1da177e4SLinus Torvalds ADB_WRITEREG(device, KEYB_LEDREG), 0xff, ~leds); 606*1da177e4SLinus Torvalds return; 607*1da177e4SLinus Torvalds } else { 608*1da177e4SLinus Torvalds if (!(leds_pending[device] & 0x100)) { 609*1da177e4SLinus Torvalds pending_devs[pending_led_end] = device; 610*1da177e4SLinus Torvalds pending_led_end++; 611*1da177e4SLinus Torvalds pending_led_end = (pending_led_end < 16) ? pending_led_end : 0; 612*1da177e4SLinus Torvalds } 613*1da177e4SLinus Torvalds leds_pending[device] = leds | 0x100; 614*1da177e4SLinus Torvalds } 615*1da177e4SLinus Torvalds spin_unlock_irqrestore(&leds_lock, flags); 616*1da177e4SLinus Torvalds } 617*1da177e4SLinus Torvalds 618*1da177e4SLinus Torvalds /* 619*1da177e4SLinus Torvalds * Event callback from the input module. Events that change the state of 620*1da177e4SLinus Torvalds * the hardware are processed here. 621*1da177e4SLinus Torvalds */ 622*1da177e4SLinus Torvalds static int adbhid_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) 623*1da177e4SLinus Torvalds { 624*1da177e4SLinus Torvalds struct adbhid *adbhid = dev->private; 625*1da177e4SLinus Torvalds unsigned char leds; 626*1da177e4SLinus Torvalds 627*1da177e4SLinus Torvalds switch (type) { 628*1da177e4SLinus Torvalds case EV_LED: 629*1da177e4SLinus Torvalds leds = (test_bit(LED_SCROLLL, dev->led) ? 4 : 0) 630*1da177e4SLinus Torvalds | (test_bit(LED_NUML, dev->led) ? 1 : 0) 631*1da177e4SLinus Torvalds | (test_bit(LED_CAPSL, dev->led) ? 2 : 0); 632*1da177e4SLinus Torvalds real_leds(leds, adbhid->id); 633*1da177e4SLinus Torvalds return 0; 634*1da177e4SLinus Torvalds } 635*1da177e4SLinus Torvalds 636*1da177e4SLinus Torvalds return -1; 637*1da177e4SLinus Torvalds } 638*1da177e4SLinus Torvalds 639*1da177e4SLinus Torvalds static int 640*1da177e4SLinus Torvalds adb_message_handler(struct notifier_block *this, unsigned long code, void *x) 641*1da177e4SLinus Torvalds { 642*1da177e4SLinus Torvalds switch (code) { 643*1da177e4SLinus Torvalds case ADB_MSG_PRE_RESET: 644*1da177e4SLinus Torvalds case ADB_MSG_POWERDOWN: 645*1da177e4SLinus Torvalds /* Stop the repeat timer. Autopoll is already off at this point */ 646*1da177e4SLinus Torvalds { 647*1da177e4SLinus Torvalds int i; 648*1da177e4SLinus Torvalds for (i = 1; i < 16; i++) { 649*1da177e4SLinus Torvalds if (adbhid[i]) 650*1da177e4SLinus Torvalds del_timer_sync(&adbhid[i]->input.timer); 651*1da177e4SLinus Torvalds } 652*1da177e4SLinus Torvalds } 653*1da177e4SLinus Torvalds 654*1da177e4SLinus Torvalds /* Stop pending led requests */ 655*1da177e4SLinus Torvalds while(leds_req_pending) 656*1da177e4SLinus Torvalds adb_poll(); 657*1da177e4SLinus Torvalds break; 658*1da177e4SLinus Torvalds 659*1da177e4SLinus Torvalds case ADB_MSG_POST_RESET: 660*1da177e4SLinus Torvalds adbhid_probe(); 661*1da177e4SLinus Torvalds break; 662*1da177e4SLinus Torvalds } 663*1da177e4SLinus Torvalds return NOTIFY_DONE; 664*1da177e4SLinus Torvalds } 665*1da177e4SLinus Torvalds 666*1da177e4SLinus Torvalds static void 667*1da177e4SLinus Torvalds adbhid_input_register(int id, int default_id, int original_handler_id, 668*1da177e4SLinus Torvalds int current_handler_id, int mouse_kind) 669*1da177e4SLinus Torvalds { 670*1da177e4SLinus Torvalds int i; 671*1da177e4SLinus Torvalds 672*1da177e4SLinus Torvalds if (adbhid[id]) { 673*1da177e4SLinus Torvalds printk(KERN_ERR "Trying to reregister ADB HID on ID %d\n", id); 674*1da177e4SLinus Torvalds return; 675*1da177e4SLinus Torvalds } 676*1da177e4SLinus Torvalds 677*1da177e4SLinus Torvalds if (!(adbhid[id] = kmalloc(sizeof(struct adbhid), GFP_KERNEL))) 678*1da177e4SLinus Torvalds return; 679*1da177e4SLinus Torvalds 680*1da177e4SLinus Torvalds memset(adbhid[id], 0, sizeof(struct adbhid)); 681*1da177e4SLinus Torvalds sprintf(adbhid[id]->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id); 682*1da177e4SLinus Torvalds 683*1da177e4SLinus Torvalds init_input_dev(&adbhid[id]->input); 684*1da177e4SLinus Torvalds 685*1da177e4SLinus Torvalds adbhid[id]->id = default_id; 686*1da177e4SLinus Torvalds adbhid[id]->original_handler_id = original_handler_id; 687*1da177e4SLinus Torvalds adbhid[id]->current_handler_id = current_handler_id; 688*1da177e4SLinus Torvalds adbhid[id]->mouse_kind = mouse_kind; 689*1da177e4SLinus Torvalds adbhid[id]->flags = 0; 690*1da177e4SLinus Torvalds adbhid[id]->input.private = adbhid[id]; 691*1da177e4SLinus Torvalds adbhid[id]->input.name = adbhid[id]->name; 692*1da177e4SLinus Torvalds adbhid[id]->input.phys = adbhid[id]->phys; 693*1da177e4SLinus Torvalds adbhid[id]->input.id.bustype = BUS_ADB; 694*1da177e4SLinus Torvalds adbhid[id]->input.id.vendor = 0x0001; 695*1da177e4SLinus Torvalds adbhid[id]->input.id.product = (id << 12) | (default_id << 8) | original_handler_id; 696*1da177e4SLinus Torvalds adbhid[id]->input.id.version = 0x0100; 697*1da177e4SLinus Torvalds 698*1da177e4SLinus Torvalds switch (default_id) { 699*1da177e4SLinus Torvalds case ADB_KEYBOARD: 700*1da177e4SLinus Torvalds if (!(adbhid[id]->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL))) { 701*1da177e4SLinus Torvalds kfree(adbhid[id]); 702*1da177e4SLinus Torvalds return; 703*1da177e4SLinus Torvalds } 704*1da177e4SLinus Torvalds 705*1da177e4SLinus Torvalds sprintf(adbhid[id]->name, "ADB keyboard"); 706*1da177e4SLinus Torvalds 707*1da177e4SLinus Torvalds memcpy(adbhid[id]->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes)); 708*1da177e4SLinus Torvalds 709*1da177e4SLinus Torvalds printk(KERN_INFO "Detected ADB keyboard, type "); 710*1da177e4SLinus Torvalds switch (original_handler_id) { 711*1da177e4SLinus Torvalds default: 712*1da177e4SLinus Torvalds printk("<unknown>.\n"); 713*1da177e4SLinus Torvalds adbhid[id]->input.id.version = ADB_KEYBOARD_UNKNOWN; 714*1da177e4SLinus Torvalds break; 715*1da177e4SLinus Torvalds 716*1da177e4SLinus Torvalds case 0x01: case 0x02: case 0x03: case 0x06: case 0x08: 717*1da177e4SLinus Torvalds case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C: 718*1da177e4SLinus Torvalds case 0xC0: case 0xC3: case 0xC6: 719*1da177e4SLinus Torvalds printk("ANSI.\n"); 720*1da177e4SLinus Torvalds adbhid[id]->input.id.version = ADB_KEYBOARD_ANSI; 721*1da177e4SLinus Torvalds break; 722*1da177e4SLinus Torvalds 723*1da177e4SLinus Torvalds case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D: 724*1da177e4SLinus Torvalds case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1: 725*1da177e4SLinus Torvalds case 0xC4: case 0xC7: 726*1da177e4SLinus Torvalds printk("ISO, swapping keys.\n"); 727*1da177e4SLinus Torvalds adbhid[id]->input.id.version = ADB_KEYBOARD_ISO; 728*1da177e4SLinus Torvalds i = adbhid[id]->keycode[10]; 729*1da177e4SLinus Torvalds adbhid[id]->keycode[10] = adbhid[id]->keycode[50]; 730*1da177e4SLinus Torvalds adbhid[id]->keycode[50] = i; 731*1da177e4SLinus Torvalds break; 732*1da177e4SLinus Torvalds 733*1da177e4SLinus Torvalds case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A: 734*1da177e4SLinus Torvalds case 0x1E: case 0xC2: case 0xC5: case 0xC8: case 0xC9: 735*1da177e4SLinus Torvalds printk("JIS.\n"); 736*1da177e4SLinus Torvalds adbhid[id]->input.id.version = ADB_KEYBOARD_JIS; 737*1da177e4SLinus Torvalds break; 738*1da177e4SLinus Torvalds } 739*1da177e4SLinus Torvalds 740*1da177e4SLinus Torvalds for (i = 0; i < 128; i++) 741*1da177e4SLinus Torvalds if (adbhid[id]->keycode[i]) 742*1da177e4SLinus Torvalds set_bit(adbhid[id]->keycode[i], adbhid[id]->input.keybit); 743*1da177e4SLinus Torvalds 744*1da177e4SLinus Torvalds adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); 745*1da177e4SLinus Torvalds adbhid[id]->input.ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML); 746*1da177e4SLinus Torvalds adbhid[id]->input.event = adbhid_kbd_event; 747*1da177e4SLinus Torvalds adbhid[id]->input.keycodemax = 127; 748*1da177e4SLinus Torvalds adbhid[id]->input.keycodesize = 1; 749*1da177e4SLinus Torvalds break; 750*1da177e4SLinus Torvalds 751*1da177e4SLinus Torvalds case ADB_MOUSE: 752*1da177e4SLinus Torvalds sprintf(adbhid[id]->name, "ADB mouse"); 753*1da177e4SLinus Torvalds 754*1da177e4SLinus Torvalds adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); 755*1da177e4SLinus Torvalds adbhid[id]->input.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); 756*1da177e4SLinus Torvalds adbhid[id]->input.relbit[0] = BIT(REL_X) | BIT(REL_Y); 757*1da177e4SLinus Torvalds break; 758*1da177e4SLinus Torvalds 759*1da177e4SLinus Torvalds case ADB_MISC: 760*1da177e4SLinus Torvalds switch (original_handler_id) { 761*1da177e4SLinus Torvalds case 0x02: /* Adjustable keyboard button device */ 762*1da177e4SLinus Torvalds sprintf(adbhid[id]->name, "ADB adjustable keyboard buttons"); 763*1da177e4SLinus Torvalds adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); 764*1da177e4SLinus Torvalds set_bit(KEY_SOUND, adbhid[id]->input.keybit); 765*1da177e4SLinus Torvalds set_bit(KEY_MUTE, adbhid[id]->input.keybit); 766*1da177e4SLinus Torvalds set_bit(KEY_VOLUMEUP, adbhid[id]->input.keybit); 767*1da177e4SLinus Torvalds set_bit(KEY_VOLUMEDOWN, adbhid[id]->input.keybit); 768*1da177e4SLinus Torvalds break; 769*1da177e4SLinus Torvalds case 0x1f: /* Powerbook button device */ 770*1da177e4SLinus Torvalds sprintf(adbhid[id]->name, "ADB Powerbook buttons"); 771*1da177e4SLinus Torvalds adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); 772*1da177e4SLinus Torvalds set_bit(KEY_MUTE, adbhid[id]->input.keybit); 773*1da177e4SLinus Torvalds set_bit(KEY_VOLUMEUP, adbhid[id]->input.keybit); 774*1da177e4SLinus Torvalds set_bit(KEY_VOLUMEDOWN, adbhid[id]->input.keybit); 775*1da177e4SLinus Torvalds set_bit(KEY_BRIGHTNESSUP, adbhid[id]->input.keybit); 776*1da177e4SLinus Torvalds set_bit(KEY_BRIGHTNESSDOWN, adbhid[id]->input.keybit); 777*1da177e4SLinus Torvalds set_bit(KEY_EJECTCD, adbhid[id]->input.keybit); 778*1da177e4SLinus Torvalds break; 779*1da177e4SLinus Torvalds } 780*1da177e4SLinus Torvalds if (adbhid[id]->name[0]) 781*1da177e4SLinus Torvalds break; 782*1da177e4SLinus Torvalds /* else fall through */ 783*1da177e4SLinus Torvalds 784*1da177e4SLinus Torvalds default: 785*1da177e4SLinus Torvalds printk(KERN_INFO "Trying to register unknown ADB device to input layer.\n"); 786*1da177e4SLinus Torvalds kfree(adbhid[id]); 787*1da177e4SLinus Torvalds return; 788*1da177e4SLinus Torvalds } 789*1da177e4SLinus Torvalds 790*1da177e4SLinus Torvalds adbhid[id]->input.keycode = adbhid[id]->keycode; 791*1da177e4SLinus Torvalds 792*1da177e4SLinus Torvalds input_register_device(&adbhid[id]->input); 793*1da177e4SLinus Torvalds 794*1da177e4SLinus Torvalds printk(KERN_INFO "input: %s on %s\n", 795*1da177e4SLinus Torvalds adbhid[id]->name, adbhid[id]->phys); 796*1da177e4SLinus Torvalds 797*1da177e4SLinus Torvalds if (default_id == ADB_KEYBOARD) { 798*1da177e4SLinus Torvalds /* HACK WARNING!! This should go away as soon there is an utility 799*1da177e4SLinus Torvalds * to control that for event devices. 800*1da177e4SLinus Torvalds */ 801*1da177e4SLinus Torvalds adbhid[id]->input.rep[REP_DELAY] = 500; /* input layer default: 250 */ 802*1da177e4SLinus Torvalds adbhid[id]->input.rep[REP_PERIOD] = 66; /* input layer default: 33 */ 803*1da177e4SLinus Torvalds } 804*1da177e4SLinus Torvalds } 805*1da177e4SLinus Torvalds 806*1da177e4SLinus Torvalds static void adbhid_input_unregister(int id) 807*1da177e4SLinus Torvalds { 808*1da177e4SLinus Torvalds input_unregister_device(&adbhid[id]->input); 809*1da177e4SLinus Torvalds if (adbhid[id]->keycode) 810*1da177e4SLinus Torvalds kfree(adbhid[id]->keycode); 811*1da177e4SLinus Torvalds kfree(adbhid[id]); 812*1da177e4SLinus Torvalds adbhid[id] = NULL; 813*1da177e4SLinus Torvalds } 814*1da177e4SLinus Torvalds 815*1da177e4SLinus Torvalds 816*1da177e4SLinus Torvalds static u16 817*1da177e4SLinus Torvalds adbhid_input_reregister(int id, int default_id, int org_handler_id, 818*1da177e4SLinus Torvalds int cur_handler_id, int mk) 819*1da177e4SLinus Torvalds { 820*1da177e4SLinus Torvalds if (adbhid[id]) { 821*1da177e4SLinus Torvalds if (adbhid[id]->input.id.product != 822*1da177e4SLinus Torvalds ((id << 12)|(default_id << 8)|org_handler_id)) { 823*1da177e4SLinus Torvalds adbhid_input_unregister(id); 824*1da177e4SLinus Torvalds adbhid_input_register(id, default_id, org_handler_id, 825*1da177e4SLinus Torvalds cur_handler_id, mk); 826*1da177e4SLinus Torvalds } 827*1da177e4SLinus Torvalds } else 828*1da177e4SLinus Torvalds adbhid_input_register(id, default_id, org_handler_id, 829*1da177e4SLinus Torvalds cur_handler_id, mk); 830*1da177e4SLinus Torvalds return 1<<id; 831*1da177e4SLinus Torvalds } 832*1da177e4SLinus Torvalds 833*1da177e4SLinus Torvalds static void 834*1da177e4SLinus Torvalds adbhid_input_devcleanup(u16 exist) 835*1da177e4SLinus Torvalds { 836*1da177e4SLinus Torvalds int i; 837*1da177e4SLinus Torvalds for(i=1; i<16; i++) 838*1da177e4SLinus Torvalds if (adbhid[i] && !(exist&(1<<i))) 839*1da177e4SLinus Torvalds adbhid_input_unregister(i); 840*1da177e4SLinus Torvalds } 841*1da177e4SLinus Torvalds 842*1da177e4SLinus Torvalds static void 843*1da177e4SLinus Torvalds adbhid_probe(void) 844*1da177e4SLinus Torvalds { 845*1da177e4SLinus Torvalds struct adb_request req; 846*1da177e4SLinus Torvalds int i, default_id, org_handler_id, cur_handler_id; 847*1da177e4SLinus Torvalds u16 reg = 0; 848*1da177e4SLinus Torvalds 849*1da177e4SLinus Torvalds adb_register(ADB_MOUSE, 0, &mouse_ids, adbhid_mouse_input); 850*1da177e4SLinus Torvalds adb_register(ADB_KEYBOARD, 0, &keyboard_ids, adbhid_keyboard_input); 851*1da177e4SLinus Torvalds adb_register(ADB_MISC, 0, &buttons_ids, adbhid_buttons_input); 852*1da177e4SLinus Torvalds 853*1da177e4SLinus Torvalds for (i = 0; i < keyboard_ids.nids; i++) { 854*1da177e4SLinus Torvalds int id = keyboard_ids.id[i]; 855*1da177e4SLinus Torvalds 856*1da177e4SLinus Torvalds adb_get_infos(id, &default_id, &org_handler_id); 857*1da177e4SLinus Torvalds 858*1da177e4SLinus Torvalds /* turn off all leds */ 859*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 3, 860*1da177e4SLinus Torvalds ADB_WRITEREG(id, KEYB_LEDREG), 0xff, 0xff); 861*1da177e4SLinus Torvalds 862*1da177e4SLinus Torvalds /* Enable full feature set of the keyboard 863*1da177e4SLinus Torvalds ->get it to send separate codes for left and right shift, 864*1da177e4SLinus Torvalds control, option keys */ 865*1da177e4SLinus Torvalds #if 0 /* handler 5 doesn't send separate codes for R modifiers */ 866*1da177e4SLinus Torvalds if (adb_try_handler_change(id, 5)) 867*1da177e4SLinus Torvalds printk("ADB keyboard at %d, handler set to 5\n", id); 868*1da177e4SLinus Torvalds else 869*1da177e4SLinus Torvalds #endif 870*1da177e4SLinus Torvalds if (adb_try_handler_change(id, 3)) 871*1da177e4SLinus Torvalds printk("ADB keyboard at %d, handler set to 3\n", id); 872*1da177e4SLinus Torvalds else 873*1da177e4SLinus Torvalds printk("ADB keyboard at %d, handler 1\n", id); 874*1da177e4SLinus Torvalds 875*1da177e4SLinus Torvalds adb_get_infos(id, &default_id, &cur_handler_id); 876*1da177e4SLinus Torvalds reg |= adbhid_input_reregister(id, default_id, org_handler_id, 877*1da177e4SLinus Torvalds cur_handler_id, 0); 878*1da177e4SLinus Torvalds } 879*1da177e4SLinus Torvalds 880*1da177e4SLinus Torvalds for (i = 0; i < buttons_ids.nids; i++) { 881*1da177e4SLinus Torvalds int id = buttons_ids.id[i]; 882*1da177e4SLinus Torvalds 883*1da177e4SLinus Torvalds adb_get_infos(id, &default_id, &org_handler_id); 884*1da177e4SLinus Torvalds reg |= adbhid_input_reregister(id, default_id, org_handler_id, 885*1da177e4SLinus Torvalds org_handler_id, 0); 886*1da177e4SLinus Torvalds } 887*1da177e4SLinus Torvalds 888*1da177e4SLinus Torvalds /* Try to switch all mice to handler 4, or 2 for three-button 889*1da177e4SLinus Torvalds mode and full resolution. */ 890*1da177e4SLinus Torvalds for (i = 0; i < mouse_ids.nids; i++) { 891*1da177e4SLinus Torvalds int id = mouse_ids.id[i]; 892*1da177e4SLinus Torvalds int mouse_kind; 893*1da177e4SLinus Torvalds 894*1da177e4SLinus Torvalds adb_get_infos(id, &default_id, &org_handler_id); 895*1da177e4SLinus Torvalds 896*1da177e4SLinus Torvalds if (adb_try_handler_change(id, 4)) { 897*1da177e4SLinus Torvalds printk("ADB mouse at %d, handler set to 4", id); 898*1da177e4SLinus Torvalds mouse_kind = ADBMOUSE_EXTENDED; 899*1da177e4SLinus Torvalds } 900*1da177e4SLinus Torvalds else if (adb_try_handler_change(id, 0x2F)) { 901*1da177e4SLinus Torvalds printk("ADB mouse at %d, handler set to 0x2F", id); 902*1da177e4SLinus Torvalds mouse_kind = ADBMOUSE_MICROSPEED; 903*1da177e4SLinus Torvalds } 904*1da177e4SLinus Torvalds else if (adb_try_handler_change(id, 0x42)) { 905*1da177e4SLinus Torvalds printk("ADB mouse at %d, handler set to 0x42", id); 906*1da177e4SLinus Torvalds mouse_kind = ADBMOUSE_TRACKBALLPRO; 907*1da177e4SLinus Torvalds } 908*1da177e4SLinus Torvalds else if (adb_try_handler_change(id, 0x66)) { 909*1da177e4SLinus Torvalds printk("ADB mouse at %d, handler set to 0x66", id); 910*1da177e4SLinus Torvalds mouse_kind = ADBMOUSE_MICROSPEED; 911*1da177e4SLinus Torvalds } 912*1da177e4SLinus Torvalds else if (adb_try_handler_change(id, 0x5F)) { 913*1da177e4SLinus Torvalds printk("ADB mouse at %d, handler set to 0x5F", id); 914*1da177e4SLinus Torvalds mouse_kind = ADBMOUSE_MICROSPEED; 915*1da177e4SLinus Torvalds } 916*1da177e4SLinus Torvalds else if (adb_try_handler_change(id, 3)) { 917*1da177e4SLinus Torvalds printk("ADB mouse at %d, handler set to 3", id); 918*1da177e4SLinus Torvalds mouse_kind = ADBMOUSE_MS_A3; 919*1da177e4SLinus Torvalds } 920*1da177e4SLinus Torvalds else if (adb_try_handler_change(id, 2)) { 921*1da177e4SLinus Torvalds printk("ADB mouse at %d, handler set to 2", id); 922*1da177e4SLinus Torvalds mouse_kind = ADBMOUSE_STANDARD_200; 923*1da177e4SLinus Torvalds } 924*1da177e4SLinus Torvalds else { 925*1da177e4SLinus Torvalds printk("ADB mouse at %d, handler 1", id); 926*1da177e4SLinus Torvalds mouse_kind = ADBMOUSE_STANDARD_100; 927*1da177e4SLinus Torvalds } 928*1da177e4SLinus Torvalds 929*1da177e4SLinus Torvalds if ((mouse_kind == ADBMOUSE_TRACKBALLPRO) 930*1da177e4SLinus Torvalds || (mouse_kind == ADBMOUSE_MICROSPEED)) { 931*1da177e4SLinus Torvalds init_microspeed(id); 932*1da177e4SLinus Torvalds } else if (mouse_kind == ADBMOUSE_MS_A3) { 933*1da177e4SLinus Torvalds init_ms_a3(id); 934*1da177e4SLinus Torvalds } else if (mouse_kind == ADBMOUSE_EXTENDED) { 935*1da177e4SLinus Torvalds /* 936*1da177e4SLinus Torvalds * Register 1 is usually used for device 937*1da177e4SLinus Torvalds * identification. Here, we try to identify 938*1da177e4SLinus Torvalds * a known device and call the appropriate 939*1da177e4SLinus Torvalds * init function. 940*1da177e4SLinus Torvalds */ 941*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, 942*1da177e4SLinus Torvalds ADB_READREG(id, 1)); 943*1da177e4SLinus Torvalds 944*1da177e4SLinus Torvalds if ((req.reply_len) && 945*1da177e4SLinus Torvalds (req.reply[1] == 0x9a) && ((req.reply[2] == 0x21) 946*1da177e4SLinus Torvalds || (req.reply[2] == 0x20))) { 947*1da177e4SLinus Torvalds mouse_kind = ADBMOUSE_TRACKBALL; 948*1da177e4SLinus Torvalds init_trackball(id); 949*1da177e4SLinus Torvalds } 950*1da177e4SLinus Torvalds else if ((req.reply_len >= 4) && 951*1da177e4SLinus Torvalds (req.reply[1] == 0x74) && (req.reply[2] == 0x70) && 952*1da177e4SLinus Torvalds (req.reply[3] == 0x61) && (req.reply[4] == 0x64)) { 953*1da177e4SLinus Torvalds mouse_kind = ADBMOUSE_TRACKPAD; 954*1da177e4SLinus Torvalds init_trackpad(id); 955*1da177e4SLinus Torvalds } 956*1da177e4SLinus Torvalds else if ((req.reply_len >= 4) && 957*1da177e4SLinus Torvalds (req.reply[1] == 0x4b) && (req.reply[2] == 0x4d) && 958*1da177e4SLinus Torvalds (req.reply[3] == 0x4c) && (req.reply[4] == 0x31)) { 959*1da177e4SLinus Torvalds mouse_kind = ADBMOUSE_TURBOMOUSE5; 960*1da177e4SLinus Torvalds init_turbomouse(id); 961*1da177e4SLinus Torvalds } 962*1da177e4SLinus Torvalds else if ((req.reply_len == 9) && 963*1da177e4SLinus Torvalds (req.reply[1] == 0x4b) && (req.reply[2] == 0x4f) && 964*1da177e4SLinus Torvalds (req.reply[3] == 0x49) && (req.reply[4] == 0x54)) { 965*1da177e4SLinus Torvalds if (adb_try_handler_change(id, 0x42)) { 966*1da177e4SLinus Torvalds printk("\nADB MacAlly 2-button mouse at %d, handler set to 0x42", id); 967*1da177e4SLinus Torvalds mouse_kind = ADBMOUSE_MACALLY2; 968*1da177e4SLinus Torvalds } 969*1da177e4SLinus Torvalds } 970*1da177e4SLinus Torvalds } 971*1da177e4SLinus Torvalds printk("\n"); 972*1da177e4SLinus Torvalds 973*1da177e4SLinus Torvalds adb_get_infos(id, &default_id, &cur_handler_id); 974*1da177e4SLinus Torvalds reg |= adbhid_input_reregister(id, default_id, org_handler_id, 975*1da177e4SLinus Torvalds cur_handler_id, mouse_kind); 976*1da177e4SLinus Torvalds } 977*1da177e4SLinus Torvalds adbhid_input_devcleanup(reg); 978*1da177e4SLinus Torvalds } 979*1da177e4SLinus Torvalds 980*1da177e4SLinus Torvalds static void 981*1da177e4SLinus Torvalds init_trackpad(int id) 982*1da177e4SLinus Torvalds { 983*1da177e4SLinus Torvalds struct adb_request req; 984*1da177e4SLinus Torvalds unsigned char r1_buffer[8]; 985*1da177e4SLinus Torvalds 986*1da177e4SLinus Torvalds printk(" (trackpad)"); 987*1da177e4SLinus Torvalds 988*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1, 989*1da177e4SLinus Torvalds ADB_READREG(id,1)); 990*1da177e4SLinus Torvalds if (req.reply_len < 8) 991*1da177e4SLinus Torvalds printk("bad length for reg. 1\n"); 992*1da177e4SLinus Torvalds else 993*1da177e4SLinus Torvalds { 994*1da177e4SLinus Torvalds memcpy(r1_buffer, &req.reply[1], 8); 995*1da177e4SLinus Torvalds 996*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 9, 997*1da177e4SLinus Torvalds ADB_WRITEREG(id,1), 998*1da177e4SLinus Torvalds r1_buffer[0], 999*1da177e4SLinus Torvalds r1_buffer[1], 1000*1da177e4SLinus Torvalds r1_buffer[2], 1001*1da177e4SLinus Torvalds r1_buffer[3], 1002*1da177e4SLinus Torvalds r1_buffer[4], 1003*1da177e4SLinus Torvalds r1_buffer[5], 1004*1da177e4SLinus Torvalds 0x0d, 1005*1da177e4SLinus Torvalds r1_buffer[7]); 1006*1da177e4SLinus Torvalds 1007*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 9, 1008*1da177e4SLinus Torvalds ADB_WRITEREG(id,2), 1009*1da177e4SLinus Torvalds 0x99, 1010*1da177e4SLinus Torvalds 0x94, 1011*1da177e4SLinus Torvalds 0x19, 1012*1da177e4SLinus Torvalds 0xff, 1013*1da177e4SLinus Torvalds 0xb2, 1014*1da177e4SLinus Torvalds 0x8a, 1015*1da177e4SLinus Torvalds 0x1b, 1016*1da177e4SLinus Torvalds 0x50); 1017*1da177e4SLinus Torvalds 1018*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 9, 1019*1da177e4SLinus Torvalds ADB_WRITEREG(id,1), 1020*1da177e4SLinus Torvalds r1_buffer[0], 1021*1da177e4SLinus Torvalds r1_buffer[1], 1022*1da177e4SLinus Torvalds r1_buffer[2], 1023*1da177e4SLinus Torvalds r1_buffer[3], 1024*1da177e4SLinus Torvalds r1_buffer[4], 1025*1da177e4SLinus Torvalds r1_buffer[5], 1026*1da177e4SLinus Torvalds 0x03, /*r1_buffer[6],*/ 1027*1da177e4SLinus Torvalds r1_buffer[7]); 1028*1da177e4SLinus Torvalds 1029*1da177e4SLinus Torvalds /* Without this flush, the trackpad may be locked up */ 1030*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); 1031*1da177e4SLinus Torvalds } 1032*1da177e4SLinus Torvalds } 1033*1da177e4SLinus Torvalds 1034*1da177e4SLinus Torvalds static void 1035*1da177e4SLinus Torvalds init_trackball(int id) 1036*1da177e4SLinus Torvalds { 1037*1da177e4SLinus Torvalds struct adb_request req; 1038*1da177e4SLinus Torvalds 1039*1da177e4SLinus Torvalds printk(" (trackman/mouseman)"); 1040*1da177e4SLinus Torvalds 1041*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 3, 1042*1da177e4SLinus Torvalds ADB_WRITEREG(id,1), 00,0x81); 1043*1da177e4SLinus Torvalds 1044*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 3, 1045*1da177e4SLinus Torvalds ADB_WRITEREG(id,1), 01,0x81); 1046*1da177e4SLinus Torvalds 1047*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 3, 1048*1da177e4SLinus Torvalds ADB_WRITEREG(id,1), 02,0x81); 1049*1da177e4SLinus Torvalds 1050*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 3, 1051*1da177e4SLinus Torvalds ADB_WRITEREG(id,1), 03,0x38); 1052*1da177e4SLinus Torvalds 1053*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 3, 1054*1da177e4SLinus Torvalds ADB_WRITEREG(id,1), 00,0x81); 1055*1da177e4SLinus Torvalds 1056*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 3, 1057*1da177e4SLinus Torvalds ADB_WRITEREG(id,1), 01,0x81); 1058*1da177e4SLinus Torvalds 1059*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 3, 1060*1da177e4SLinus Torvalds ADB_WRITEREG(id,1), 02,0x81); 1061*1da177e4SLinus Torvalds 1062*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 3, 1063*1da177e4SLinus Torvalds ADB_WRITEREG(id,1), 03,0x38); 1064*1da177e4SLinus Torvalds } 1065*1da177e4SLinus Torvalds 1066*1da177e4SLinus Torvalds static void 1067*1da177e4SLinus Torvalds init_turbomouse(int id) 1068*1da177e4SLinus Torvalds { 1069*1da177e4SLinus Torvalds struct adb_request req; 1070*1da177e4SLinus Torvalds 1071*1da177e4SLinus Torvalds printk(" (TurboMouse 5)"); 1072*1da177e4SLinus Torvalds 1073*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); 1074*1da177e4SLinus Torvalds 1075*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(3)); 1076*1da177e4SLinus Torvalds 1077*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 9, 1078*1da177e4SLinus Torvalds ADB_WRITEREG(3,2), 1079*1da177e4SLinus Torvalds 0xe7, 1080*1da177e4SLinus Torvalds 0x8c, 1081*1da177e4SLinus Torvalds 0, 1082*1da177e4SLinus Torvalds 0, 1083*1da177e4SLinus Torvalds 0, 1084*1da177e4SLinus Torvalds 0xff, 1085*1da177e4SLinus Torvalds 0xff, 1086*1da177e4SLinus Torvalds 0x94); 1087*1da177e4SLinus Torvalds 1088*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(3)); 1089*1da177e4SLinus Torvalds 1090*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 9, 1091*1da177e4SLinus Torvalds ADB_WRITEREG(3,2), 1092*1da177e4SLinus Torvalds 0xa5, 1093*1da177e4SLinus Torvalds 0x14, 1094*1da177e4SLinus Torvalds 0, 1095*1da177e4SLinus Torvalds 0, 1096*1da177e4SLinus Torvalds 0x69, 1097*1da177e4SLinus Torvalds 0xff, 1098*1da177e4SLinus Torvalds 0xff, 1099*1da177e4SLinus Torvalds 0x27); 1100*1da177e4SLinus Torvalds } 1101*1da177e4SLinus Torvalds 1102*1da177e4SLinus Torvalds static void 1103*1da177e4SLinus Torvalds init_microspeed(int id) 1104*1da177e4SLinus Torvalds { 1105*1da177e4SLinus Torvalds struct adb_request req; 1106*1da177e4SLinus Torvalds 1107*1da177e4SLinus Torvalds printk(" (Microspeed/MacPoint or compatible)"); 1108*1da177e4SLinus Torvalds 1109*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); 1110*1da177e4SLinus Torvalds 1111*1da177e4SLinus Torvalds /* This will initialize mice using the Microspeed, MacPoint and 1112*1da177e4SLinus Torvalds other compatible firmware. Bit 12 enables extended protocol. 1113*1da177e4SLinus Torvalds 1114*1da177e4SLinus Torvalds Register 1 Listen (4 Bytes) 1115*1da177e4SLinus Torvalds 0 - 3 Button is mouse (set also for double clicking!!!) 1116*1da177e4SLinus Torvalds 4 - 7 Button is locking (affects change speed also) 1117*1da177e4SLinus Torvalds 8 - 11 Button changes speed 1118*1da177e4SLinus Torvalds 12 1 = Extended mouse mode, 0 = normal mouse mode 1119*1da177e4SLinus Torvalds 13 - 15 unused 0 1120*1da177e4SLinus Torvalds 16 - 23 normal speed 1121*1da177e4SLinus Torvalds 24 - 31 changed speed 1122*1da177e4SLinus Torvalds 1123*1da177e4SLinus Torvalds Register 1 talk holds version and product identification information. 1124*1da177e4SLinus Torvalds Register 1 Talk (4 Bytes): 1125*1da177e4SLinus Torvalds 0 - 7 Product code 1126*1da177e4SLinus Torvalds 8 - 23 undefined, reserved 1127*1da177e4SLinus Torvalds 24 - 31 Version number 1128*1da177e4SLinus Torvalds 1129*1da177e4SLinus Torvalds Speed 0 is max. 1 to 255 set speed in increments of 1/256 of max. 1130*1da177e4SLinus Torvalds */ 1131*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 5, 1132*1da177e4SLinus Torvalds ADB_WRITEREG(id,1), 1133*1da177e4SLinus Torvalds 0x20, /* alt speed = 0x20 (rather slow) */ 1134*1da177e4SLinus Torvalds 0x00, /* norm speed = 0x00 (fastest) */ 1135*1da177e4SLinus Torvalds 0x10, /* extended protocol, no speed change */ 1136*1da177e4SLinus Torvalds 0x07); /* all buttons enabled as mouse buttons, no locking */ 1137*1da177e4SLinus Torvalds 1138*1da177e4SLinus Torvalds 1139*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); 1140*1da177e4SLinus Torvalds } 1141*1da177e4SLinus Torvalds 1142*1da177e4SLinus Torvalds static void 1143*1da177e4SLinus Torvalds init_ms_a3(int id) 1144*1da177e4SLinus Torvalds { 1145*1da177e4SLinus Torvalds struct adb_request req; 1146*1da177e4SLinus Torvalds 1147*1da177e4SLinus Torvalds printk(" (Mouse Systems A3 Mouse, or compatible)"); 1148*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 3, 1149*1da177e4SLinus Torvalds ADB_WRITEREG(id, 0x2), 1150*1da177e4SLinus Torvalds 0x00, 1151*1da177e4SLinus Torvalds 0x07); 1152*1da177e4SLinus Torvalds 1153*1da177e4SLinus Torvalds adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); 1154*1da177e4SLinus Torvalds } 1155*1da177e4SLinus Torvalds 1156*1da177e4SLinus Torvalds static int __init adbhid_init(void) 1157*1da177e4SLinus Torvalds { 1158*1da177e4SLinus Torvalds #ifndef CONFIG_MAC 1159*1da177e4SLinus Torvalds if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) 1160*1da177e4SLinus Torvalds return 0; 1161*1da177e4SLinus Torvalds #endif 1162*1da177e4SLinus Torvalds 1163*1da177e4SLinus Torvalds led_request.complete = 1; 1164*1da177e4SLinus Torvalds 1165*1da177e4SLinus Torvalds adbhid_probe(); 1166*1da177e4SLinus Torvalds 1167*1da177e4SLinus Torvalds notifier_chain_register(&adb_client_list, &adbhid_adb_notifier); 1168*1da177e4SLinus Torvalds 1169*1da177e4SLinus Torvalds return 0; 1170*1da177e4SLinus Torvalds } 1171*1da177e4SLinus Torvalds 1172*1da177e4SLinus Torvalds static void __exit adbhid_exit(void) 1173*1da177e4SLinus Torvalds { 1174*1da177e4SLinus Torvalds } 1175*1da177e4SLinus Torvalds 1176*1da177e4SLinus Torvalds module_init(adbhid_init); 1177*1da177e4SLinus Torvalds module_exit(adbhid_exit); 1178