⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adbhid.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * drivers/input/adbhid.c * * ADB HID driver for Power Macintosh computers. * * Adapted from drivers/macintosh/mac_keyb.c by Franz Sirl * (see that file for its authors and contributors). * * 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. */#include <linux/config.h>#include <linux/module.h>#include <linux/malloc.h>#include <linux/init.h>#include <linux/notifier.h>#include <linux/input.h>#include <linux/kbd_ll.h>#include <linux/adb.h>#include <linux/cuda.h>#include <linux/pmu.h>#ifdef CONFIG_PMAC_BACKLIGHT#include <asm/backlight.h>#endifMODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>");#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,};unsigned char adb_to_linux_keycodes[128] = {	 30, 31, 32, 33, 35, 34, 44, 45, 46, 47, 86, 48, 16, 17, 18, 19,	 21, 20,  2,  3,  4,  5,  7,  6, 13, 10,  8, 12,  9, 11, 27, 24,	 22, 26, 23, 25, 28, 38, 36, 40, 37, 39, 43, 51, 53, 49, 50, 52,	 15, 57, 41, 14, 96,  1, 29,125, 42, 58, 56,105,106,108,103,  0,	  0, 83,  0, 55,  0, 78,  0, 69,  0,  0,  0, 98, 96,  0, 74,  0,	  0,117, 82, 79, 80, 81, 75, 76, 77, 71,  0, 72, 73,183,181,124,	 63, 64, 65, 61, 66, 67,191, 87,190, 99,  0, 70,  0, 68,101, 88,	  0,119,110,102,104,111, 62,107, 60,109, 59, 54,100, 97,116,116};struct adbhid {	struct input_dev input;	int id;	int default_id;	int original_handler_id;	int current_handler_id;	int mouse_kind;	unsigned char *keycode;	char name[64];};static struct adbhid *adbhid[16] = { 0 };static void adbhid_probe(void);static void adbhid_input_keycode(int, int, int);static void leds_done(struct adb_request *);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, struct pt_regs *regs, 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 */	kbd_pt_regs = regs;	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 keycode, int repeat){	int up_flag;	up_flag = (keycode & 0x80);	keycode &= 0x7f;	switch (keycode) {	case 0x39: /* Generate down/up events for CapsLock everytime. */		input_report_key(&adbhid[id]->input, KEY_CAPSLOCK, 1);		input_report_key(&adbhid[id]->input, KEY_CAPSLOCK, 0);		return;	case 0x3f: /* ignore Powerbook Fn key */		return;	}	if (adbhid[id]->keycode[keycode])		input_report_key(&adbhid[id]->input,				 adbhid[id]->keycode[keycode], !up_flag);	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, struct pt_regs *regs, 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.    data[2] = byyy yyyy Second button and y-axis motion.    data[3] = byyy bxxx Third button and fourth button.  Y is additional	      high bits of y-axis motion.  XY is additional	      high bits of x-axis motion.    MacAlly 2-button mouse protocol.    For MacAlly 2-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.    data[2] = byyy yyyy Right button and y-axis motion.    data[3] = ???? ???? unknown    data[4] = ???? ???? unknown  */	/* If it's a trackpad, we alias the second button to the first.	   NOTE: Apple sends an ADB flush command to the trackpad when	         the first (the real) button is released. We could do		 this here using async flush requests.	*/	switch (adbhid[id]->mouse_kind)	{	    case ADBMOUSE_TRACKPAD:		data[1] = (data[1] & 0x7f) | ((data[1] & data[2]) & 0x80);		data[2] = data[2] | 0x80;		break;	    case ADBMOUSE_MICROSPEED:		data[1] = (data[1] & 0x7f) | ((data[3] & 0x01) << 7);		data[2] = (data[2] & 0x7f) | ((data[3] & 0x02) << 6);		data[3] = (data[3] & 0x77) | ((data[3] & 0x04) << 5)			| (data[3] & 0x08);		break;	    case ADBMOUSE_TRACKBALLPRO:		data[1] = (data[1] & 0x7f) | (((data[3] & 0x04) << 5)			& ((data[3] & 0x08) << 4));		data[2] = (data[2] & 0x7f) | ((data[3] & 0x01) << 7);		data[3] = (data[3] & 0x77) | ((data[3] & 0x02) << 6);		break;	    case ADBMOUSE_MS_A3:		data[1] = (data[1] & 0x7f) | ((data[3] & 0x01) << 7);		data[2] = (data[2] & 0x7f) | ((data[3] & 0x02) << 6);		data[3] = ((data[3] & 0x04) << 5);		break;            case ADBMOUSE_MACALLY2:		data[3] = (data[2] & 0x80) ? 0x80 : 0x00;		data[2] |= 0x80;  /* Right button is mapped as button 3 */		nb=4;                break;	}	input_report_key(&adbhid[id]->input, BTN_LEFT,   !((data[1] >> 7) & 1));	input_report_key(&adbhid[id]->input, BTN_MIDDLE, !((data[2] >> 7) & 1));	if (nb >= 4)		input_report_key(&adbhid[id]->input, BTN_RIGHT,  !((data[3] >> 7) & 1));	input_report_rel(&adbhid[id]->input, REL_X,			 ((data[2]&0x7f) < 64 ? (data[2]&0x7f) : (data[2]&0x7f)-128 ));	input_report_rel(&adbhid[id]->input, REL_Y,			 ((data[1]&0x7f) < 64 ? (data[1]&0x7f) : (data[1]&0x7f)-128 ));}static voidadbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, 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;	}	switch (adbhid[id]->original_handler_id) {	default:	case 0x02: /* Adjustable keyboard button device */		printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",		       data[0], data[1], data[2], data[3]);		break;	case 0x1f: /* Powerbook button device */	  {#ifdef CONFIG_PMAC_BACKLIGHT		int backlight = get_backlight_level();		/*		 * XXX: Where is the contrast control for the passive?		 *  -- Cort		 */		switch (data[1]) {		case 0x8:	/* mute */			break;		case 0x7:	/* contrast decrease */			break;		case 0x6:	/* contrast increase */			break;		case 0xa:	/* brightness decrease */			if (backlight < 0)				break;			if (backlight > BACKLIGHT_OFF)				set_backlight_level(backlight-1);			else				set_backlight_level(BACKLIGHT_OFF);			break;		case 0x9:	/* brightness increase */			if (backlight < 0)				break;			if (backlight < BACKLIGHT_MAX)				set_backlight_level(backlight+1);			else 				set_backlight_level(BACKLIGHT_MAX);			break;		}#endif /* CONFIG_PMAC_BACKLIGHT */	  }	  break;	}}static struct adb_request led_request;static int leds_pending[16];static int pending_devs[16];static int pending_led_start=0;static int pending_led_end=0;static void real_leds(unsigned char leds, int device){    if (led_request.complete) {	adb_request(&led_request, leds_done, 0, 3,		    ADB_WRITEREG(device, KEYB_LEDREG), 0xff,		    ~leds);    } else {	if (!(leds_pending[device] & 0x100)) {	    pending_devs[pending_led_end] = device;	    pending_led_end++;	    pending_led_end = (pending_led_end < 16) ? pending_led_end : 0;	}	leds_pending[device] = leds | 0x100;    }}/* * Event callback from the input module. Events that change the state of * the hardware are processed here. */static int adbhid_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value){	struct adbhid *adbhid = dev->private;	unsigned char leds;	switch (type) {	case EV_LED:	  leds = (test_bit(LED_SCROLLL, dev->led) ? 4 : 0)	       | (test_bit(LED_NUML,    dev->led) ? 1 : 0)	       | (test_bit(LED_CAPSL,   dev->led) ? 2 : 0);	  real_leds(leds, adbhid->id);	  return 0;	}	return -1;}static void leds_done(struct adb_request *req){    int leds,device;    if (pending_led_start != pending_led_end) {	device = pending_devs[pending_led_start];	leds = leds_pending[device] & 0xff;	leds_pending[device] = 0;	pending_led_start++;	pending_led_start = (pending_led_start < 16) ? pending_led_start : 0;	real_leds(leds,device);    }}static intadb_message_handler(struct notifier_block *this, unsigned long code, void *x){	unsigned long flags;	switch (code) {	case ADB_MSG_PRE_RESET:	case ADB_MSG_POWERDOWN:	    	/* Stop the repeat timer. Autopoll is already off at this point */		save_flags(flags);		cli();		{			int i;			for (i = 1; i < 16; i++) {				if (adbhid[i])					del_timer(&adbhid[i]->input.timer);			}		}		restore_flags(flags);		/* Stop pending led requests */		while(!led_request.complete)			adb_poll();		break;	case ADB_MSG_POST_RESET:		adbhid_probe();		break;	}	return NOTIFY_DONE;}static voidadbhid_input_register(int id, int default_id, int original_handler_id,		      int current_handler_id, int mouse_kind){	int i;	if (adbhid[id]) {		printk(KERN_ERR "Trying to reregister ADB HID on ID %d\n", id);		return;	}	if (!(adbhid[id] = kmalloc(sizeof(struct adbhid), GFP_KERNEL)))		return;	memset(adbhid[id], 0, sizeof(struct adbhid));	adbhid[id]->id = default_id;	adbhid[id]->original_handler_id = original_handler_id;	adbhid[id]->current_handler_id = current_handler_id;	adbhid[id]->mouse_kind = mouse_kind;	adbhid[id]->input.private = adbhid[id];	adbhid[id]->input.name = adbhid[id]->name;	adbhid[id]->input.idbus = BUS_ADB;	adbhid[id]->input.idvendor = 0x0001;	adbhid[id]->input.idproduct = (id << 12) | (default_id << 8) | original_handler_id;	adbhid[id]->input.idversion = 0x0100;	switch (default_id) {	case ADB_KEYBOARD:		if (!(adbhid[id]->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL))) {			kfree(adbhid[id]);

⌨️ 快捷键说明

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