adbhid.c

来自「linux 内核源代码」· C语言 代码 · 共 1,247 行 · 第 1/3 页

C
1,247
字号
/* * drivers/macintosh/adbhid.c * * ADB HID driver for Power Macintosh computers. * * Adapted from drivers/macintosh/mac_keyb.c by Franz Sirl. * drivers/macintosh/mac_keyb.c was Copyright (C) 1996 Paul Mackerras * with considerable contributions from Ben Herrenschmidt and others. * * Copyright (C) 2000 Franz Sirl. * * Adapted to ADB changes and support for more devices by * Benjamin Herrenschmidt. Adapted from code in MkLinux * and reworked. *  * Supported devices: * * - Standard 1 button mouse * - All standard Apple Extended protocol (handler ID 4) * - mouseman and trackman mice & trackballs  * - PowerBook Trackpad (default setup: enable tapping) * - MicroSpeed mouse & trackball (needs testing) * - CH Products Trackball Pro (needs testing) * - Contour Design (Contour Mouse) * - Hunter digital (NoHandsMouse) * - Kensignton TurboMouse 5 (needs testing) * - Mouse Systems A3 mice and trackballs <aidan@kublai.com> * - MacAlly 2-buttons mouse (needs testing) <pochini@denise.shiny.it> * * To do: * * Improve Kensington support. * Split mouse/kbd * Move to syfs */#include <linux/module.h>#include <linux/slab.h>#include <linux/init.h>#include <linux/notifier.h>#include <linux/input.h>#include <linux/adb.h>#include <linux/cuda.h>#include <linux/pmu.h>#include <asm/machdep.h>#ifdef CONFIG_PPC_PMAC#include <asm/backlight.h>#include <asm/pmac_feature.h>#endifMODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>");static int restore_capslock_events;module_param(restore_capslock_events, int, 0644);MODULE_PARM_DESC(restore_capslock_events,	"Produce keypress events for capslock on both keyup and keydown.");#define KEYB_KEYREG	0	/* register # for key up/down data */#define KEYB_LEDREG	2	/* register # for leds on ADB keyboard */#define MOUSE_DATAREG	0	/* reg# for movement/button codes from mouse */static int adb_message_handler(struct notifier_block *, unsigned long, void *);static struct notifier_block adbhid_adb_notifier = {	.notifier_call	= adb_message_handler,};/* Some special keys */#define ADB_KEY_DEL		0x33#define ADB_KEY_CMD		0x37#define ADB_KEY_CAPSLOCK	0x39#define ADB_KEY_FN		0x3f#define ADB_KEY_FWDEL		0x75#define ADB_KEY_POWER_OLD	0x7e#define ADB_KEY_POWER		0x7fu16 adb_to_linux_keycodes[128] = {	/* 0x00 */ KEY_A, 		/*  30 */	/* 0x01 */ KEY_S, 		/*  31 */	/* 0x02 */ KEY_D,		/*  32 */	/* 0x03 */ KEY_F,		/*  33 */	/* 0x04 */ KEY_H,		/*  35 */	/* 0x05 */ KEY_G,		/*  34 */	/* 0x06 */ KEY_Z,		/*  44 */	/* 0x07 */ KEY_X,		/*  45 */	/* 0x08 */ KEY_C,		/*  46 */	/* 0x09 */ KEY_V,		/*  47 */	/* 0x0a */ KEY_102ND,		/*  86 */	/* 0x0b */ KEY_B,		/*  48 */	/* 0x0c */ KEY_Q,		/*  16 */	/* 0x0d */ KEY_W,		/*  17 */	/* 0x0e */ KEY_E,		/*  18 */	/* 0x0f */ KEY_R,		/*  19 */	/* 0x10 */ KEY_Y,		/*  21 */	/* 0x11 */ KEY_T,		/*  20 */	/* 0x12 */ KEY_1,		/*   2 */	/* 0x13 */ KEY_2,		/*   3 */	/* 0x14 */ KEY_3,		/*   4 */	/* 0x15 */ KEY_4,		/*   5 */	/* 0x16 */ KEY_6,		/*   7 */	/* 0x17 */ KEY_5,		/*   6 */	/* 0x18 */ KEY_EQUAL,		/*  13 */	/* 0x19 */ KEY_9,		/*  10 */	/* 0x1a */ KEY_7,		/*   8 */	/* 0x1b */ KEY_MINUS,		/*  12 */	/* 0x1c */ KEY_8,		/*   9 */	/* 0x1d */ KEY_0,		/*  11 */	/* 0x1e */ KEY_RIGHTBRACE,	/*  27 */	/* 0x1f */ KEY_O,		/*  24 */	/* 0x20 */ KEY_U,		/*  22 */	/* 0x21 */ KEY_LEFTBRACE,	/*  26 */	/* 0x22 */ KEY_I,		/*  23 */	/* 0x23 */ KEY_P,		/*  25 */	/* 0x24 */ KEY_ENTER,		/*  28 */	/* 0x25 */ KEY_L,		/*  38 */	/* 0x26 */ KEY_J,		/*  36 */	/* 0x27 */ KEY_APOSTROPHE,	/*  40 */	/* 0x28 */ KEY_K,		/*  37 */	/* 0x29 */ KEY_SEMICOLON,	/*  39 */	/* 0x2a */ KEY_BACKSLASH,	/*  43 */	/* 0x2b */ KEY_COMMA,		/*  51 */	/* 0x2c */ KEY_SLASH,		/*  53 */	/* 0x2d */ KEY_N,		/*  49 */	/* 0x2e */ KEY_M,		/*  50 */	/* 0x2f */ KEY_DOT,		/*  52 */	/* 0x30 */ KEY_TAB,		/*  15 */	/* 0x31 */ KEY_SPACE,		/*  57 */	/* 0x32 */ KEY_GRAVE,		/*  41 */	/* 0x33 */ KEY_BACKSPACE,	/*  14 */	/* 0x34 */ KEY_KPENTER,		/*  96 */	/* 0x35 */ KEY_ESC,		/*   1 */	/* 0x36 */ KEY_LEFTCTRL,	/*  29 */	/* 0x37 */ KEY_LEFTMETA,	/* 125 */	/* 0x38 */ KEY_LEFTSHIFT,	/*  42 */	/* 0x39 */ KEY_CAPSLOCK,	/*  58 */	/* 0x3a */ KEY_LEFTALT,		/*  56 */	/* 0x3b */ KEY_LEFT,		/* 105 */	/* 0x3c */ KEY_RIGHT,		/* 106 */	/* 0x3d */ KEY_DOWN,		/* 108 */	/* 0x3e */ KEY_UP,		/* 103 */	/* 0x3f */ KEY_FN,		/* 0x1d0 */	/* 0x40 */ 0,	/* 0x41 */ KEY_KPDOT,		/*  83 */	/* 0x42 */ 0,	/* 0x43 */ KEY_KPASTERISK,	/*  55 */	/* 0x44 */ 0,	/* 0x45 */ KEY_KPPLUS,		/*  78 */	/* 0x46 */ 0,	/* 0x47 */ KEY_NUMLOCK,		/*  69 */	/* 0x48 */ 0,	/* 0x49 */ 0,	/* 0x4a */ 0,	/* 0x4b */ KEY_KPSLASH,		/*  98 */	/* 0x4c */ KEY_KPENTER,		/*  96 */	/* 0x4d */ 0,	/* 0x4e */ KEY_KPMINUS,		/*  74 */	/* 0x4f */ 0,	/* 0x50 */ 0,	/* 0x51 */ KEY_KPEQUAL,		/* 117 */	/* 0x52 */ KEY_KP0,		/*  82 */	/* 0x53 */ KEY_KP1,		/*  79 */	/* 0x54 */ KEY_KP2,		/*  80 */	/* 0x55 */ KEY_KP3,		/*  81 */	/* 0x56 */ KEY_KP4,		/*  75 */	/* 0x57 */ KEY_KP5,		/*  76 */	/* 0x58 */ KEY_KP6,		/*  77 */	/* 0x59 */ KEY_KP7,		/*  71 */	/* 0x5a */ 0,	/* 0x5b */ KEY_KP8,		/*  72 */	/* 0x5c */ KEY_KP9,		/*  73 */	/* 0x5d */ KEY_YEN,		/* 124 */	/* 0x5e */ KEY_RO,		/*  89 */	/* 0x5f */ KEY_KPCOMMA,		/* 121 */	/* 0x60 */ KEY_F5,		/*  63 */	/* 0x61 */ KEY_F6,		/*  64 */	/* 0x62 */ KEY_F7,		/*  65 */	/* 0x63 */ KEY_F3,		/*  61 */	/* 0x64 */ KEY_F8,		/*  66 */	/* 0x65 */ KEY_F9,		/*  67 */	/* 0x66 */ KEY_HANJA,		/* 123 */	/* 0x67 */ KEY_F11,		/*  87 */	/* 0x68 */ KEY_HANGEUL,		/* 122 */	/* 0x69 */ KEY_SYSRQ,		/*  99 */	/* 0x6a */ 0,	/* 0x6b */ KEY_SCROLLLOCK,	/*  70 */	/* 0x6c */ 0,	/* 0x6d */ KEY_F10,		/*  68 */	/* 0x6e */ KEY_COMPOSE,		/* 127 */	/* 0x6f */ KEY_F12,		/*  88 */	/* 0x70 */ 0,	/* 0x71 */ KEY_PAUSE,		/* 119 */	/* 0x72 */ KEY_INSERT,		/* 110 */	/* 0x73 */ KEY_HOME,		/* 102 */	/* 0x74 */ KEY_PAGEUP,		/* 104 */	/* 0x75 */ KEY_DELETE,		/* 111 */	/* 0x76 */ KEY_F4,		/*  62 */	/* 0x77 */ KEY_END,		/* 107 */	/* 0x78 */ KEY_F2,		/*  60 */	/* 0x79 */ KEY_PAGEDOWN,	/* 109 */	/* 0x7a */ KEY_F1,		/*  59 */	/* 0x7b */ KEY_RIGHTSHIFT,	/*  54 */	/* 0x7c */ KEY_RIGHTALT,	/* 100 */	/* 0x7d */ KEY_RIGHTCTRL,	/*  97 */	/* 0x7e */ KEY_RIGHTMETA,	/* 126 */	/* 0x7f */ KEY_POWER,		/* 116 */};struct adbhid {	struct input_dev *input;	int id;	int default_id;	int original_handler_id;	int current_handler_id;	int mouse_kind;	u16 *keycode;	char name[64];	char phys[32];	int flags;};#define FLAG_FN_KEY_PRESSED	0x00000001#define FLAG_POWER_FROM_FN	0x00000002#define FLAG_EMU_FWDEL_DOWN	0x00000004#define FLAG_CAPSLOCK_TRANSLATE	0x00000008#define FLAG_CAPSLOCK_DOWN	0x00000010static struct adbhid *adbhid[16];static void adbhid_probe(void);static void adbhid_input_keycode(int, int, int);static void init_trackpad(int id);static void init_trackball(int id);static void init_turbomouse(int id);static void init_microspeed(int id);static void init_ms_a3(int id);static struct adb_ids keyboard_ids;static struct adb_ids mouse_ids;static struct adb_ids buttons_ids;/* Kind of keyboard, see Apple technote 1152  */#define ADB_KEYBOARD_UNKNOWN	0#define ADB_KEYBOARD_ANSI	0x0100#define ADB_KEYBOARD_ISO	0x0200#define ADB_KEYBOARD_JIS	0x0300/* Kind of mouse  */#define ADBMOUSE_STANDARD_100	0	/* Standard 100cpi mouse (handler 1) */#define ADBMOUSE_STANDARD_200	1	/* Standard 200cpi mouse (handler 2) */#define ADBMOUSE_EXTENDED	2	/* Apple Extended mouse (handler 4) */#define ADBMOUSE_TRACKBALL	3	/* TrackBall (handler 4) */#define ADBMOUSE_TRACKPAD       4	/* Apple's PowerBook trackpad (handler 4) */#define ADBMOUSE_TURBOMOUSE5    5	/* Turbomouse 5 (previously req. mousehack) */#define ADBMOUSE_MICROSPEED	6	/* Microspeed mouse (&trackball ?), MacPoint */#define ADBMOUSE_TRACKBALLPRO	7	/* Trackball Pro (special buttons) */#define ADBMOUSE_MS_A3		8	/* Mouse systems A3 trackball (handler 3) */#define ADBMOUSE_MACALLY2	9	/* MacAlly 2-button mouse */static voidadbhid_keyboard_input(unsigned char *data, int nb, int apoll){	int id = (data[0] >> 4) & 0x0f;	if (!adbhid[id]) {		printk(KERN_ERR "ADB HID on ID %d not yet registered, packet %#02x, %#02x, %#02x, %#02x\n",		       id, data[0], data[1], data[2], data[3]);		return;	}	/* first check this is from register 0 */	if (nb != 3 || (data[0] & 3) != KEYB_KEYREG)		return;		/* ignore it */	adbhid_input_keycode(id, data[1], 0);	if (!(data[2] == 0xff || (data[2] == 0x7f && data[1] == 0x7f)))		adbhid_input_keycode(id, data[2], 0);}static voidadbhid_input_keycode(int id, int scancode, int repeat){	struct adbhid *ahid = adbhid[id];	int keycode, up_flag, key;	keycode = scancode & 0x7f;	up_flag = scancode & 0x80;	if (restore_capslock_events) {		if (keycode == ADB_KEY_CAPSLOCK && !up_flag) {			/* Key pressed, turning on the CapsLock LED.			 * The next 0xff will be interpreted as a release. */			ahid->flags |= FLAG_CAPSLOCK_TRANSLATE					| FLAG_CAPSLOCK_DOWN;		} else if (scancode == 0xff) {			/* Scancode 0xff usually signifies that the capslock			 * key was either pressed or released. */			if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE) {				keycode = ADB_KEY_CAPSLOCK;				if (ahid->flags & FLAG_CAPSLOCK_DOWN) {					/* Key released */					up_flag = 1;					ahid->flags &= ~FLAG_CAPSLOCK_DOWN;				} else {					/* Key pressed */					up_flag = 0;					ahid->flags &= ~FLAG_CAPSLOCK_TRANSLATE;				}			} else {				printk(KERN_INFO "Spurious caps lock event "						"(scancode 0xff).");			}		}	}	switch (keycode) {	case ADB_KEY_CAPSLOCK:		if (!restore_capslock_events) {			/* Generate down/up events for CapsLock everytime. */			input_report_key(ahid->input, KEY_CAPSLOCK, 1);			input_sync(ahid->input);			input_report_key(ahid->input, KEY_CAPSLOCK, 0);			input_sync(ahid->input);			return;		}		break;#ifdef CONFIG_PPC_PMAC	case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */		switch(pmac_call_feature(PMAC_FTR_GET_MB_INFO,			NULL, PMAC_MB_INFO_MODEL, 0)) {		case PMAC_TYPE_COMET:		case PMAC_TYPE_HOOPER:		case PMAC_TYPE_KANGA:			keycode = ADB_KEY_POWER;		}		break;	case ADB_KEY_POWER:		/* Fn + Command will produce a bogus "power" keycode */		if (ahid->flags & FLAG_FN_KEY_PRESSED) {			keycode = ADB_KEY_CMD;			if (up_flag)				ahid->flags &= ~FLAG_POWER_FROM_FN;			else				ahid->flags |= FLAG_POWER_FROM_FN;		} else if (ahid->flags & FLAG_POWER_FROM_FN) {			keycode = ADB_KEY_CMD;			ahid->flags &= ~FLAG_POWER_FROM_FN;		}		break;	case ADB_KEY_FN:		/* Keep track of the Fn key state */		if (up_flag) {			ahid->flags &= ~FLAG_FN_KEY_PRESSED;			/* Emulate Fn+delete = forward delete */			if (ahid->flags & FLAG_EMU_FWDEL_DOWN) {				ahid->flags &= ~FLAG_EMU_FWDEL_DOWN;				keycode = ADB_KEY_FWDEL;				break;			}		} else			ahid->flags |= FLAG_FN_KEY_PRESSED;		break;	case ADB_KEY_DEL:		/* Emulate Fn+delete = forward delete */		if (ahid->flags & FLAG_FN_KEY_PRESSED) {			keycode = ADB_KEY_FWDEL;			if (up_flag)				ahid->flags &= ~FLAG_EMU_FWDEL_DOWN;			else				ahid->flags |= FLAG_EMU_FWDEL_DOWN;		}		break;#endif /* CONFIG_PPC_PMAC */	}	key = adbhid[id]->keycode[keycode];	if (key) {		input_report_key(adbhid[id]->input, key, !up_flag);		input_sync(adbhid[id]->input);	} else		printk(KERN_INFO "Unhandled ADB key (scancode %#02x) %s.\n", keycode,		       up_flag ? "released" : "pressed");}static voidadbhid_mouse_input(unsigned char *data, int nb, int autopoll){	int id = (data[0] >> 4) & 0x0f;	if (!adbhid[id]) {		printk(KERN_ERR "ADB HID on ID %d not yet registered\n", id);		return;	}  /*    Handler 1 -- 100cpi original Apple mouse protocol.    Handler 2 -- 200cpi original Apple mouse protocol.    For Apple's standard one-button mouse protocol the data array will    contain the following values:                BITS    COMMENTS    data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd.    data[1] = bxxx xxxx First button and x-axis motion.    data[2] = byyy yyyy Second button and y-axis motion.    Handler 4 -- Apple Extended mouse protocol.    For Apple's 3-button mouse protocol the data array will contain the    following values:		BITS    COMMENTS    data[0] = dddd 1100 ADB command: Talk, register 0, for device dddd.    data[1] = bxxx xxxx Left button and x-axis motion.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?