^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Focaltech TouchPad PS/2 mouse driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2014 Red Hat Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2014 Mathias Gottschlag <mgottschlag@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Red Hat authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Hans de Goede <hdegoede@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/libps2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/input/mt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/serio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "psmouse.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "focaltech.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static const char * const focaltech_pnp_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) "FLT0101",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) "FLT0102",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) "FLT0103",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * Even if the kernel is built without support for Focaltech PS/2 touchpads (or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * when the real driver fails to recognize the device), we still have to detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * them in order to avoid further detection attempts confusing the touchpad.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * This way it at least works in PS/2 mouse compatibility mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) int focaltech_detect(struct psmouse *psmouse, bool set_properties)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if (!psmouse_matches_pnp_id(psmouse, focaltech_pnp_ids))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (set_properties) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) psmouse->vendor = "FocalTech";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) psmouse->name = "Touchpad";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #ifdef CONFIG_MOUSE_PS2_FOCALTECH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * Packet types - the numbers are not consecutive, so we might be missing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * something here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define FOC_TOUCH 0x3 /* bitmap of active fingers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define FOC_ABS 0x6 /* absolute position of one finger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define FOC_REL 0x9 /* relative position of 1-2 fingers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define FOC_MAX_FINGERS 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * Current state of a single finger on the touchpad.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct focaltech_finger_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* The touchpad has generated a touch event for the finger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) bool active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * The touchpad has sent position data for the finger. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * flag is 0 when the finger is not active, and there is a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * time between the first touch event for the finger and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * following absolute position packet for the finger where the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * touchpad has declared the finger to be valid, but we do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * have any valid position yet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) bool valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * Absolute position (from the bottom left corner) of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * finger.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned int y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * Description of the current state of the touchpad hardware.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct focaltech_hw_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * The touchpad tracks the positions of the fingers for us,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * the array indices correspond to the finger indices returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * in the report packages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct focaltech_finger_state fingers[FOC_MAX_FINGERS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * Finger width 0-7 and 15 for a very big contact area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * 15 value stays until the finger is released.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * Width is reported only in absolute packets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * Since hardware reports width only for last touching finger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * there is no need to store width for every specific finger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * so we keep only last value reported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) unsigned int width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* True if the clickpad has been pressed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) bool pressed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct focaltech_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) unsigned int x_max, y_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct focaltech_hw_state state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static void focaltech_report_state(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct focaltech_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct focaltech_hw_state *state = &priv->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct input_dev *dev = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) for (i = 0; i < FOC_MAX_FINGERS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct focaltech_finger_state *finger = &state->fingers[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) bool active = finger->active && finger->valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) input_mt_slot(dev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) input_mt_report_slot_state(dev, MT_TOOL_FINGER, active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) unsigned int clamped_x, clamped_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * The touchpad might report invalid data, so we clamp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * the resulting values so that we do not confuse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * userspace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) clamped_x = clamp(finger->x, 0U, priv->x_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) clamped_y = clamp(finger->y, 0U, priv->y_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) input_report_abs(dev, ABS_MT_POSITION_X, clamped_x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) input_report_abs(dev, ABS_MT_POSITION_Y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) priv->y_max - clamped_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) input_report_abs(dev, ABS_TOOL_WIDTH, state->width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) input_mt_report_pointer_emulation(dev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) input_report_key(dev, BTN_LEFT, state->pressed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static void focaltech_process_touch_packet(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) unsigned char *packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct focaltech_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct focaltech_hw_state *state = &priv->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) unsigned char fingers = packet[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) state->pressed = (packet[0] >> 4) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* the second byte contains a bitmap of all fingers touching the pad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) for (i = 0; i < FOC_MAX_FINGERS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) state->fingers[i].active = fingers & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (!state->fingers[i].active) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * Even when the finger becomes active again, we still
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * will have to wait for the first valid position.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) state->fingers[i].valid = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) fingers >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static void focaltech_process_abs_packet(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) unsigned char *packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct focaltech_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct focaltech_hw_state *state = &priv->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) unsigned int finger;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) finger = (packet[1] >> 4) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (finger >= FOC_MAX_FINGERS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) psmouse_err(psmouse, "Invalid finger in abs packet: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) finger);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) state->pressed = (packet[0] >> 4) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) state->fingers[finger].x = ((packet[1] & 0xf) << 8) | packet[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) state->fingers[finger].y = (packet[3] << 8) | packet[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) state->width = packet[5] >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) state->fingers[finger].valid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static void focaltech_process_rel_packet(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) unsigned char *packet)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct focaltech_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct focaltech_hw_state *state = &priv->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int finger1, finger2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) state->pressed = packet[0] >> 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) finger1 = ((packet[0] >> 4) & 0x7) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (finger1 < FOC_MAX_FINGERS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) state->fingers[finger1].x += (char)packet[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) state->fingers[finger1].y += (char)packet[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) psmouse_err(psmouse, "First finger in rel packet invalid: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) finger1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * If there is an odd number of fingers, the last relative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * packet only contains one finger. In this case, the second
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * finger index in the packet is 0 (we subtract 1 in the lines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * above to create array indices, so the finger will overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * and be above FOC_MAX_FINGERS).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) finger2 = ((packet[3] >> 4) & 0x7) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (finger2 < FOC_MAX_FINGERS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) state->fingers[finger2].x += (char)packet[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) state->fingers[finger2].y += (char)packet[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static void focaltech_process_packet(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) unsigned char *packet = psmouse->packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) switch (packet[0] & 0xf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case FOC_TOUCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) focaltech_process_touch_packet(psmouse, packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) case FOC_ABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) focaltech_process_abs_packet(psmouse, packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) case FOC_REL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) focaltech_process_rel_packet(psmouse, packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) psmouse_err(psmouse, "Unknown packet type: %02x\n", packet[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) focaltech_report_state(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static psmouse_ret_t focaltech_process_byte(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (psmouse->pktcnt >= 6) { /* Full packet received */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) focaltech_process_packet(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return PSMOUSE_FULL_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * We might want to do some validation of the data here, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * we do not know the protocol well enough
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return PSMOUSE_GOOD_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static int focaltech_switch_protocol(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) unsigned char param[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) param[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (ps2_command(ps2dev, param, 0x10f8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (ps2_command(ps2dev, param, 0x10f8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (ps2_command(ps2dev, param, 0x10f8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) param[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (ps2_command(ps2dev, param, 0x10f8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETSCALE11))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (ps2_command(ps2dev, param, PSMOUSE_CMD_ENABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static void focaltech_reset(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) psmouse_reset(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static void focaltech_disconnect(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) focaltech_reset(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) kfree(psmouse->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) psmouse->private = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static int focaltech_reconnect(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) focaltech_reset(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) error = focaltech_switch_protocol(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) psmouse_err(psmouse, "Unable to initialize the device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static void focaltech_set_input_params(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct input_dev *dev = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct focaltech_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * Undo part of setup done for us by psmouse core since touchpad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * is not a relative device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) __clear_bit(EV_REL, dev->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) __clear_bit(REL_X, dev->relbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) __clear_bit(REL_Y, dev->relbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) __clear_bit(BTN_RIGHT, dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) __clear_bit(BTN_MIDDLE, dev->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) * Now set up our capabilities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) __set_bit(EV_ABS, dev->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) input_set_abs_params(dev, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) input_mt_init_slots(dev, 5, INPUT_MT_POINTER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static int focaltech_read_register(struct ps2dev *ps2dev, int reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) unsigned char *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETSCALE11))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) param[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) param[0] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) static int focaltech_read_size(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct focaltech_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) char param[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (focaltech_read_register(ps2dev, 2, param))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* not sure whether this is 100% correct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) priv->x_max = (unsigned char)param[1] * 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) priv->y_max = (unsigned char)param[2] * 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) static void focaltech_set_resolution(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) unsigned int resolution)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /* not supported yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static void focaltech_set_rate(struct psmouse *psmouse, unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* not supported yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static void focaltech_set_scale(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) enum psmouse_scale scale)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /* not supported yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int focaltech_init(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct focaltech_data *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) psmouse->private = priv = kzalloc(sizeof(struct focaltech_data),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) focaltech_reset(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) error = focaltech_read_size(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) psmouse_err(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) "Unable to read the size of the touchpad\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) error = focaltech_switch_protocol(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) psmouse_err(psmouse, "Unable to initialize the device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) focaltech_set_input_params(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) psmouse->protocol_handler = focaltech_process_byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) psmouse->pktsize = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) psmouse->disconnect = focaltech_disconnect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) psmouse->reconnect = focaltech_reconnect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) psmouse->cleanup = focaltech_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* resync is not supported yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) psmouse->resync_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * rate/resolution/scale changes are not supported yet, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * the generic implementations of these functions seem to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * confuse some touchpads
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) psmouse->set_resolution = focaltech_set_resolution;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) psmouse->set_rate = focaltech_set_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) psmouse->set_scale = focaltech_set_scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) focaltech_reset(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) #endif /* CONFIG_MOUSE_PS2_FOCALTECH */