diff options
Diffstat (limited to 'drivers/input/mouse/pixart_ps2.c')
-rw-r--r-- | drivers/input/mouse/pixart_ps2.c | 300 |
1 files changed, 0 insertions, 300 deletions
diff --git a/drivers/input/mouse/pixart_ps2.c b/drivers/input/mouse/pixart_ps2.c deleted file mode 100644 index 1993fc760d7b..000000000000 --- a/drivers/input/mouse/pixart_ps2.c +++ /dev/null @@ -1,300 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Pixart Touchpad Controller 1336U PS2 driver - * - * Author: Jon Xie <jon_xie@pixart.com> - * Jay Lee <jay_lee@pixart.com> - * Further cleanup and restructuring by: - * Binbin Zhou <zhoubinbin@loongson.cn> - * - * Copyright (C) 2021-2024 Pixart Imaging. - * Copyright (C) 2024 Loongson Technology Corporation Limited. - * - */ - -#include <linux/bitfield.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/input.h> -#include <linux/input/mt.h> -#include <linux/libps2.h> -#include <linux/serio.h> -#include <linux/slab.h> - -#include "pixart_ps2.h" - -static int pixart_read_tp_mode(struct ps2dev *ps2dev, u8 *mode) -{ - int error; - u8 param[1] = { 0 }; - - error = ps2_command(ps2dev, param, PIXART_CMD_REPORT_FORMAT); - if (error) - return error; - - *mode = param[0] == 1 ? PIXART_MODE_ABS : PIXART_MODE_REL; - - return 0; -} - -static int pixart_read_tp_type(struct ps2dev *ps2dev, u8 *type) -{ - int error; - u8 param[3] = { 0 }; - - param[0] = 0x0a; - error = ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); - if (error) - return error; - - param[0] = 0x0; - error = ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - if (error) - return error; - - error = ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - if (error) - return error; - - error = ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - if (error) - return error; - - param[0] = 0x03; - error = ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES); - if (error) - return error; - - error = ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO); - if (error) - return error; - - *type = param[0] == 0x0e ? PIXART_TYPE_TOUCHPAD : PIXART_TYPE_CLICKPAD; - - return 0; -} - -static void pixart_reset(struct psmouse *psmouse) -{ - ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); - - /* according to PixArt, 100ms is required for the upcoming reset */ - msleep(100); - psmouse_reset(psmouse); -} - -static void pixart_process_packet(struct psmouse *psmouse) -{ - struct pixart_data *priv = psmouse->private; - struct input_dev *dev = psmouse->dev; - const u8 *pkt = psmouse->packet; - unsigned int contact_cnt = FIELD_GET(CONTACT_CNT_MASK, pkt[0]); - unsigned int i, id, abs_x, abs_y; - bool tip; - - for (i = 0; i < contact_cnt; i++) { - const u8 *p = &pkt[i * 3]; - - id = FIELD_GET(SLOT_ID_MASK, p[3]); - abs_y = FIELD_GET(ABS_Y_MASK, p[3]) << 8 | p[1]; - abs_x = FIELD_GET(ABS_X_MASK, p[3]) << 8 | p[2]; - - if (i == PIXART_MAX_FINGERS - 1) - tip = pkt[14] & BIT(1); - else - tip = pkt[3 * contact_cnt + 1] & BIT(2 * i + 1); - - input_mt_slot(dev, id); - if (input_mt_report_slot_state(dev, MT_TOOL_FINGER, tip)) { - input_report_abs(dev, ABS_MT_POSITION_Y, abs_y); - input_report_abs(dev, ABS_MT_POSITION_X, abs_x); - } - } - - input_mt_sync_frame(dev); - - if (priv->type == PIXART_TYPE_CLICKPAD) { - input_report_key(dev, BTN_LEFT, pkt[0] & 0x03); - } else { - input_report_key(dev, BTN_LEFT, pkt[0] & BIT(0)); - input_report_key(dev, BTN_RIGHT, pkt[0] & BIT(1)); - } - - input_sync(dev); -} - -static psmouse_ret_t pixart_protocol_handler(struct psmouse *psmouse) -{ - u8 *pkt = psmouse->packet; - u8 contact_cnt; - - if ((pkt[0] & 0x8c) != 0x80) - return PSMOUSE_BAD_DATA; - - contact_cnt = FIELD_GET(CONTACT_CNT_MASK, pkt[0]); - if (contact_cnt > PIXART_MAX_FINGERS) - return PSMOUSE_BAD_DATA; - - if (contact_cnt == PIXART_MAX_FINGERS && - psmouse->pktcnt < psmouse->pktsize) { - return PSMOUSE_GOOD_DATA; - } - - if (contact_cnt == 0 && psmouse->pktcnt < 5) - return PSMOUSE_GOOD_DATA; - - if (psmouse->pktcnt < 3 * contact_cnt + 2) - return PSMOUSE_GOOD_DATA; - - pixart_process_packet(psmouse); - - return PSMOUSE_FULL_PACKET; -} - -static void pixart_disconnect(struct psmouse *psmouse) -{ - pixart_reset(psmouse); - kfree(psmouse->private); - psmouse->private = NULL; -} - -static int pixart_reconnect(struct psmouse *psmouse) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - u8 mode; - int error; - - pixart_reset(psmouse); - - error = pixart_read_tp_mode(ps2dev, &mode); - if (error) - return error; - - if (mode != PIXART_MODE_ABS) - return -EIO; - - error = ps2_command(ps2dev, NULL, PIXART_CMD_SWITCH_PROTO); - if (error) - return error; - - return 0; -} - -static int pixart_set_input_params(struct input_dev *dev, - struct pixart_data *priv) -{ - /* No relative support */ - __clear_bit(EV_REL, dev->evbit); - __clear_bit(REL_X, dev->relbit); - __clear_bit(REL_Y, dev->relbit); - __clear_bit(BTN_MIDDLE, dev->keybit); - - /* Buttons */ - __set_bit(EV_KEY, dev->evbit); - __set_bit(BTN_LEFT, dev->keybit); - if (priv->type == PIXART_TYPE_CLICKPAD) - __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); - else - __set_bit(BTN_RIGHT, dev->keybit); - - /* Absolute position */ - input_set_abs_params(dev, ABS_X, 0, PIXART_PAD_WIDTH, 0, 0); - input_set_abs_params(dev, ABS_Y, 0, PIXART_PAD_HEIGHT, 0, 0); - - input_set_abs_params(dev, ABS_MT_POSITION_X, - 0, PIXART_PAD_WIDTH, 0, 0); - input_set_abs_params(dev, ABS_MT_POSITION_Y, - 0, PIXART_PAD_HEIGHT, 0, 0); - - return input_mt_init_slots(dev, PIXART_MAX_FINGERS, INPUT_MT_POINTER); -} - -static int pixart_query_hardware(struct ps2dev *ps2dev, u8 *mode, u8 *type) -{ - int error; - - error = pixart_read_tp_type(ps2dev, type); - if (error) - return error; - - error = pixart_read_tp_mode(ps2dev, mode); - if (error) - return error; - - return 0; -} - -int pixart_detect(struct psmouse *psmouse, bool set_properties) -{ - u8 type; - int error; - - pixart_reset(psmouse); - - error = pixart_read_tp_type(&psmouse->ps2dev, &type); - if (error) - return error; - - if (set_properties) { - psmouse->vendor = "PixArt"; - psmouse->name = (type == PIXART_TYPE_TOUCHPAD) ? - "touchpad" : "clickpad"; - } - - return 0; -} - -int pixart_init(struct psmouse *psmouse) -{ - int error; - struct pixart_data *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - psmouse->private = priv; - pixart_reset(psmouse); - - error = pixart_query_hardware(&psmouse->ps2dev, - &priv->mode, &priv->type); - if (error) { - psmouse_err(psmouse, "init: Unable to query PixArt touchpad hardware.\n"); - goto err_exit; - } - - /* Relative mode follows standard PS/2 mouse protocol */ - if (priv->mode != PIXART_MODE_ABS) { - error = -EIO; - goto err_exit; - } - - /* Set absolute mode */ - error = ps2_command(&psmouse->ps2dev, NULL, PIXART_CMD_SWITCH_PROTO); - if (error) { - psmouse_err(psmouse, "init: Unable to initialize PixArt absolute mode.\n"); - goto err_exit; - } - - error = pixart_set_input_params(psmouse->dev, priv); - if (error) { - psmouse_err(psmouse, "init: Unable to set input params.\n"); - goto err_exit; - } - - psmouse->pktsize = 15; - psmouse->protocol_handler = pixart_protocol_handler; - psmouse->disconnect = pixart_disconnect; - psmouse->reconnect = pixart_reconnect; - psmouse->cleanup = pixart_reset; - /* resync is not supported yet */ - psmouse->resync_time = 0; - - return 0; - -err_exit: - pixart_reset(psmouse); - kfree(priv); - psmouse->private = NULL; - return error; -} |