adbhid.c

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

C
1,247
字号
    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 && 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, 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 */	  {		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));		/*		 * 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 (down)				pmac_backlight_key_down();#endif			input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);			break;		case 0x9:	/* brightness increase */#ifdef CONFIG_PMAC_BACKLIGHT			if (down)				pmac_backlight_key_up();#endif			input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down);			break;		case 0xc:	/* videomode switch */			input_report_key(adbhid[id]->input, KEY_SWITCHVIDEOMODE, down);			break;		case 0xd:	/* keyboard illumination toggle */			input_report_key(adbhid[id]->input, KEY_KBDILLUMTOGGLE, down);			break;		case 0xe:	/* keyboard illumination decrease */			input_report_key(adbhid[id]->input, KEY_KBDILLUMDOWN, down);			break;		case 0xf:			switch (data[1]) {			case 0x8f:			case 0x0f:				/* keyboard illumination increase */				input_report_key(adbhid[id]->input, KEY_KBDILLUMUP, down);				break;			case 0x7f:			case 0xff:				/* keypad overlay toogle */				break;			default:				printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",				       data[0], data[1], data[2], data[3]);				break;			}			break;		default:			printk(KERN_INFO "Unhandled ADB_MISC event %02x, %02x, %02x, %02x\n",			       data[0], data[1], data[2], data[3]);			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;static int pending_led_end;static DEFINE_SPINLOCK(leds_lock);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 = input_get_drvdata(dev);	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 intadbhid_input_register(int id, int default_id, int original_handler_id,		      int current_handler_id, int mouse_kind){	struct adbhid *hid;	struct input_dev *input_dev;	int err;	int i;	if (adbhid[id]) {		printk(KERN_ERR "Trying to reregister ADB HID on ID %d\n", id);		return -EEXIST;	}	adbhid[id] = hid = kzalloc(sizeof(struct adbhid), GFP_KERNEL);	input_dev = input_allocate_device();	if (!hid || !input_dev) {		err = -ENOMEM;		goto fail;	}	sprintf(hid->phys, "adb%d:%d.%02x/input", id, default_id, original_handler_id);	hid->input = input_dev;	hid->id = default_id;	hid->original_handler_id = original_handler_id;	hid->current_handler_id = current_handler_id;	hid->mouse_kind = mouse_kind;	hid->flags = 0;	input_set_drvdata(input_dev, hid);	input_dev->name = hid->name;	input_dev->phys = hid->phys;	input_dev->id.bustype = BUS_ADB;	input_dev->id.vendor = 0x0001;	input_dev->id.product = (id << 12) | (default_id << 8) | original_handler_id;	input_dev->id.version = 0x0100;	switch (default_id) {	case ADB_KEYBOARD:		hid->keycode = kmalloc(sizeof(adb_to_linux_keycodes), GFP_KERNEL);		if (!hid->keycode) {			err = -ENOMEM;			goto fail;		}		sprintf(hid->name, "ADB keyboard");		memcpy(hid->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");			input_dev->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");			input_dev->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");			input_dev->id.version = ADB_KEYBOARD_ISO;			i = hid->keycode[10];			hid->keycode[10] = hid->keycode[50];			hid->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");			input_dev->id.version = ADB_KEYBOARD_JIS;			break;		}		for (i = 0; i < 128; i++)			if (hid->keycode[i])				set_bit(hid->keycode[i], input_dev->keybit);		input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) |			BIT_MASK(EV_REP);		input_dev->ledbit[0] = BIT_MASK(LED_SCROLLL) |			BIT_MASK(LED_CAPSL) | BIT_MASK(LED_NUML);		input_dev->event = adbhid_kbd_event;		input_dev->keycodemax = KEY_FN;		input_dev->keycodesize = sizeof(hid->keycode[0]);		break;	case ADB_MOUSE:		sprintf(hid->name, "ADB mouse");		input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);		input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |			BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);		input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);		break;	case ADB_MISC:		switch (original_handler_id) {		case 0x02: /* Adjustable keyboard button device */			sprintf(hid->name, "ADB adjustable keyboard buttons");			input_dev->evbit[0] = BIT_MASK(EV_KEY) |				BIT_MASK(EV_REP);			set_bit(KEY_SOUND, input_dev->keybit);			set_bit(KEY_MUTE, input_dev->keybit);			set_bit(KEY_VOLUMEUP, input_dev->keybit);			set_bit(KEY_VOLUMEDOWN, input_dev->keybit);			break;		case 0x1f: /* Powerbook button device */			sprintf(hid->name, "ADB Powerbook buttons");			input_dev->evbit[0] = BIT_MASK(EV_KEY) |				BIT_MASK(EV_REP);			set_bit(KEY_MUTE, input_dev->keybit);			set_bit(KEY_VOLUMEUP, input_dev->keybit);			set_bit(KEY_VOLUMEDOWN, input_dev->keybit);			set_bit(KEY_BRIGHTNESSUP, input_dev->keybit);			set_bit(KEY_BRIGHTNESSDOWN, input_dev->keybit);

⌨️ 快捷键说明

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