📄 alps.c
字号:
return NULL;}/* * For DualPoint devices select the device that should respond to * subsequent commands. It looks like glidepad is behind stickpointer, * I'd thought it would be other way around... */static int alps_passthrough_mode(struct psmouse *psmouse, int enable){ struct ps2dev *ps2dev = &psmouse->ps2dev; int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; if (ps2_command(ps2dev, NULL, cmd) || ps2_command(ps2dev, NULL, cmd) || ps2_command(ps2dev, NULL, cmd) || ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE)) return -1; /* we may get 3 more bytes, just ignore them */ ps2_drain(ps2dev, 3, 100); return 0;}static int alps_absolute_mode(struct psmouse *psmouse){ struct ps2dev *ps2dev = &psmouse->ps2dev; /* Try ALPS magic knock - 4 disable before enable */ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) return -1; /* * Switch mouse to poll (remote) mode so motion data will not * get in our way */ return ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETPOLL);}static int alps_get_status(struct psmouse *psmouse, char *param){ struct ps2dev *ps2dev = &psmouse->ps2dev; /* Get status: 0xF5 0xF5 0xF5 0xE9 */ if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) return -1; dbg("Status: %2.2x %2.2x %2.2x", param[0], param[1], param[2]); return 0;}/* * Turn touchpad tapping on or off. The sequences are: * 0xE9 0xF5 0xF5 0xF3 0x0A to enable, * 0xE9 0xF5 0xF5 0xE8 0x00 to disable. * My guess that 0xE9 (GetInfo) is here as a sync point. * For models that also have stickpointer (DualPoints) its tapping * is controlled separately (0xE6 0xE6 0xE6 0xF3 0x14|0x0A) but * we don't fiddle with it. */static int alps_tap_mode(struct psmouse *psmouse, int enable){ struct ps2dev *ps2dev = &psmouse->ps2dev; int cmd = enable ? PSMOUSE_CMD_SETRATE : PSMOUSE_CMD_SETRES; unsigned char tap_arg = enable ? 0x0A : 0x00; unsigned char param[4]; if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) || ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || ps2_command(ps2dev, &tap_arg, cmd)) return -1; if (alps_get_status(psmouse, param)) return -1; return 0;}/* * alps_poll() - poll the touchpad for current motion packet. * Used in resync. */static int alps_poll(struct psmouse *psmouse){ struct alps_data *priv = psmouse->private; unsigned char buf[6]; int poll_failed; if (priv->i->flags & ALPS_PASS) alps_passthrough_mode(psmouse, 1); poll_failed = ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; if (priv->i->flags & ALPS_PASS) alps_passthrough_mode(psmouse, 0); if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) return -1; if ((psmouse->badbyte & 0xc8) == 0x08) {/* * Poll the track stick ... */ if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8))) return -1; } memcpy(psmouse->packet, buf, sizeof(buf)); return 0;}static int alps_hw_init(struct psmouse *psmouse, int *version){ struct alps_data *priv = psmouse->private; priv->i = alps_get_model(psmouse, version); if (!priv->i) return -1; if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1)) return -1; if (alps_tap_mode(psmouse, 1)) { printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n"); return -1; } if (alps_absolute_mode(psmouse)) { printk(KERN_ERR "alps.c: Failed to enable absolute mode\n"); return -1; } if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0)) return -1; /* ALPS needs stream mode, otherwise it won't report any data */ if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) { printk(KERN_ERR "alps.c: Failed to enable stream mode\n"); return -1; } return 0;}static int alps_reconnect(struct psmouse *psmouse){ psmouse_reset(psmouse); if (alps_hw_init(psmouse, NULL)) return -1; return 0;}static void alps_disconnect(struct psmouse *psmouse){ struct alps_data *priv = psmouse->private; psmouse_reset(psmouse); input_unregister_device(priv->dev2); kfree(priv);}int alps_init(struct psmouse *psmouse){ struct alps_data *priv; struct input_dev *dev1 = psmouse->dev, *dev2; int version; priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); dev2 = input_allocate_device(); if (!priv || !dev2) goto init_fail; priv->dev2 = dev2; psmouse->private = priv; if (alps_hw_init(psmouse, &version)) goto init_fail; dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); dev1->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); if (priv->i->flags & ALPS_WHEEL) { dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); } if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); } snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); dev2->phys = priv->phys; dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; dev2->id.bustype = BUS_I8042; dev2->id.vendor = 0x0002; dev2->id.product = PSMOUSE_ALPS; dev2->id.version = 0x0000; dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); dev2->relbit[BIT_WORD(REL_X)] |= BIT_MASK(REL_X) | BIT_MASK(REL_Y); dev2->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); if (input_register_device(priv->dev2)) goto init_fail; psmouse->protocol_handler = alps_process_byte; psmouse->poll = alps_poll; psmouse->disconnect = alps_disconnect; psmouse->reconnect = alps_reconnect; psmouse->pktsize = 6; /* We are having trouble resyncing ALPS touchpads so disable it for now */ psmouse->resync_time = 0; return 0;init_fail: psmouse_reset(psmouse); input_free_device(dev2); kfree(priv); psmouse->private = NULL; return -1;}int alps_detect(struct psmouse *psmouse, int set_properties){ int version; const struct alps_model_info *model; model = alps_get_model(psmouse, &version); if (!model) return -1; if (set_properties) { psmouse->vendor = "ALPS"; psmouse->name = model->flags & ALPS_DUALPOINT ? "DualPoint TouchPad" : "GlidePoint"; psmouse->model = version; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -