adbhid.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,178 行 · 第 1/3 页

C
1,178
字号
    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_regs(&adbhid[id]->input, regs);	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 && adbhid[id]->mouse_kind != ADBMOUSE_TRACKPAD)		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 ));	input_sync(&adbhid[id]->input);}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;	}	input_regs(&adbhid[id]->input, regs);	switch (adbhid[id]->original_handler_id) {	default:	case 0x02: /* Adjustable keyboard button device */	  {		int down = (data[1] == (data[1] & 0xf));		switch (data[1] & 0x0f) {		case 0x0:	/* microphone */			input_report_key(&adbhid[id]->input, KEY_SOUND, down);			break;		case 0x1:	/* mute */			input_report_key(&adbhid[id]->input, KEY_MUTE, down);			break;		case 0x2:	/* volume decrease */			input_report_key(&adbhid[id]->input, KEY_VOLUMEDOWN, down);			break;		case 0x3:	/* volume increase */			input_report_key(&adbhid[id]->input, KEY_VOLUMEUP, down);			break;		default:			printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",			       data[0], data[1], data[2], data[3]);			break;		}	  }	  break;	case 0x1f: /* Powerbook button device */	  {		int down = (data[1] == (data[1] & 0xf));#ifdef CONFIG_PMAC_BACKLIGHT		int backlight = get_backlight_level();#endif		/*		 * XXX: Where is the contrast control for the passive?		 *  -- Cort		 */		switch (data[1] & 0x0f) {		case 0x8:	/* mute */			input_report_key(&adbhid[id]->input, KEY_MUTE, down);			break;		case 0x7:	/* volume decrease */			input_report_key(&adbhid[id]->input, KEY_VOLUMEDOWN, down);			break;		case 0x6:	/* volume increase */			input_report_key(&adbhid[id]->input, KEY_VOLUMEUP, down);			break;		case 0xb:	/* eject */			input_report_key(&adbhid[id]->input, KEY_EJECTCD, down);			break;		case 0xa:	/* brightness decrease */#ifdef CONFIG_PMAC_BACKLIGHT			if (!disable_kernel_backlight) {				if (down && backlight >= 0) {					if (backlight > BACKLIGHT_OFF)						set_backlight_level(backlight-1);					else						set_backlight_level(BACKLIGHT_OFF);				}			}#endif /* CONFIG_PMAC_BACKLIGHT */			input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);			break;		case 0x9:	/* brightness increase */#ifdef CONFIG_PMAC_BACKLIGHT			if (!disable_kernel_backlight) {				if (down && backlight >= 0) {					if (backlight < BACKLIGHT_MAX)						set_backlight_level(backlight+1);					else 						set_backlight_level(BACKLIGHT_MAX);				}			}#endif /* CONFIG_PMAC_BACKLIGHT */			input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSUP, down);			break;		}	  }	  break;	}	input_sync(&adbhid[id]->input);}static struct adb_request led_request;static int leds_pending[16];static int leds_req_pending;static int pending_devs[16];static int pending_led_start=0;static int pending_led_end=0;static spinlock_t leds_lock  = SPIN_LOCK_UNLOCKED;static void leds_done(struct adb_request *req){	int leds = 0, device = 0, pending = 0;	unsigned long flags;	spin_lock_irqsave(&leds_lock, flags);	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;		pending = leds_req_pending;	} else		leds_req_pending = 0;	spin_unlock_irqrestore(&leds_lock, flags);	if (pending)		adb_request(&led_request, leds_done, 0, 3,			    ADB_WRITEREG(device, KEYB_LEDREG), 0xff, ~leds);}static void real_leds(unsigned char leds, int device){	unsigned long flags;	spin_lock_irqsave(&leds_lock, flags);	if (!leds_req_pending) {		leds_req_pending = 1;		spin_unlock_irqrestore(&leds_lock, flags);	       		adb_request(&led_request, leds_done, 0, 3,			    ADB_WRITEREG(device, KEYB_LEDREG), 0xff, ~leds);		return;	} 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;	}	spin_unlock_irqrestore(&leds_lock, flags);	       }/* * 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 intadb_message_handler(struct notifier_block *this, unsigned long code, void *x){	switch (code) {	case ADB_MSG_PRE_RESET:	case ADB_MSG_POWERDOWN:	    	/* Stop the repeat timer. Autopoll is already off at this point */		{			int i;			for (i = 1; i < 16; i++) {				if (adbhid[i])					del_timer_sync(&adbhid[i]->input.timer);			}		}		/* Stop pending led requests */		while(leds_req_pending)			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));	sprintf(adbhid[id]->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);	init_input_dev(&adbhid[id]->input);	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]->flags = 0;	adbhid[id]->input.private = adbhid[id];	adbhid[id]->input.name = adbhid[id]->name;	adbhid[id]->input.phys = adbhid[id]->phys;	adbhid[id]->input.id.bustype = BUS_ADB;	adbhid[id]->input.id.vendor = 0x0001;	adbhid[id]->input.id.product = (id << 12) | (default_id << 8) | original_handler_id;	adbhid[id]->input.id.version = 0x0100;	switch (default_id) {	case ADB_KEYBOARD:		if (!(adbhid[id]->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL))) {			kfree(adbhid[id]);			return;		}		sprintf(adbhid[id]->name, "ADB keyboard");		memcpy(adbhid[id]->keycode, adb_to_linux_keycodes, sizeof(adb_to_linux_keycodes));		printk(KERN_INFO "Detected ADB keyboard, type ");		switch (original_handler_id) {		default:			printk("<unknown>.\n");			adbhid[id]->input.id.version = ADB_KEYBOARD_UNKNOWN;			break;		case 0x01: case 0x02: case 0x03: case 0x06: case 0x08:		case 0x0C: case 0x10: case 0x18: case 0x1B: case 0x1C:		case 0xC0: case 0xC3: case 0xC6:			printk("ANSI.\n");			adbhid[id]->input.id.version = ADB_KEYBOARD_ANSI;			break;		case 0x04: case 0x05: case 0x07: case 0x09: case 0x0D:		case 0x11: case 0x14: case 0x19: case 0x1D: case 0xC1:		case 0xC4: case 0xC7:			printk("ISO, swapping keys.\n");			adbhid[id]->input.id.version = ADB_KEYBOARD_ISO;			i = adbhid[id]->keycode[10];			adbhid[id]->keycode[10] = adbhid[id]->keycode[50];			adbhid[id]->keycode[50] = i;			break;		case 0x12: case 0x15: case 0x16: case 0x17: case 0x1A:		case 0x1E: case 0xC2: case 0xC5: case 0xC8: case 0xC9:			printk("JIS.\n");			adbhid[id]->input.id.version = ADB_KEYBOARD_JIS;			break;		}		for (i = 0; i < 128; i++)			if (adbhid[id]->keycode[i])				set_bit(adbhid[id]->keycode[i], adbhid[id]->input.keybit);		adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);		adbhid[id]->input.ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML);		adbhid[id]->input.event = adbhid_kbd_event;		adbhid[id]->input.keycodemax = 127;		adbhid[id]->input.keycodesize = 1;		break;	case ADB_MOUSE:		sprintf(adbhid[id]->name, "ADB mouse");		adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);		adbhid[id]->input.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);		adbhid[id]->input.relbit[0] = BIT(REL_X) | BIT(REL_Y);		break;	case ADB_MISC:		switch (original_handler_id) {		case 0x02: /* Adjustable keyboard button device */			sprintf(adbhid[id]->name, "ADB adjustable keyboard buttons");			adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);			set_bit(KEY_SOUND, adbhid[id]->input.keybit);			set_bit(KEY_MUTE, adbhid[id]->input.keybit);			set_bit(KEY_VOLUMEUP, adbhid[id]->input.keybit);			set_bit(KEY_VOLUMEDOWN, adbhid[id]->input.keybit);			break;		case 0x1f: /* Powerbook button device */			sprintf(adbhid[id]->name, "ADB Powerbook buttons");			adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);			set_bit(KEY_MUTE, adbhid[id]->input.keybit);			set_bit(KEY_VOLUMEUP, adbhid[id]->input.keybit);			set_bit(KEY_VOLUMEDOWN, adbhid[id]->input.keybit);			set_bit(KEY_BRIGHTNESSUP, adbhid[id]->input.keybit);			set_bit(KEY_BRIGHTNESSDOWN, adbhid[id]->input.keybit);			set_bit(KEY_EJECTCD, adbhid[id]->input.keybit);			break;		}		if (adbhid[id]->name[0])			break;		/* else fall through */	default:		printk(KERN_INFO "Trying to register unknown ADB device to input layer.\n");		kfree(adbhid[id]);

⌨️ 快捷键说明

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