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 + -
显示快捷键?