mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-08 15:04:45 +00:00
Input updates for v6.12-rc1
- a couple fixups for adp5589-keys driver - recently added driver for PixArt PS/2 touchpads is dropped temporarily because its detection routine is too greedy and mis-identifies devices from other vendors as PixArt devices. -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQST2eWILY88ieB2DOtAj56VGEWXnAUCZv0LRAAKCRBAj56VGEWX nM7OAP495t23Ay4H7qBnVEv4KHrOkNLwebKudwcokjWQAdnOPgEAu0GfslScWdrO yYofhsjrph1V2dQOWqoLnd1C4iiHVgA= =HQCS -----END PGP SIGNATURE----- Merge tag 'input-for-v6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input Pull input fixes from Dmitry Torokhov: - a couple fixups for adp5589-keys driver - recently added driver for PixArt PS/2 touchpads is dropped temporarily because its detection routine is too greedy and mis-identifies devices from other vendors as PixArt devices * tag 'input-for-v6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: adp5589-keys - fix adp5589_gpio_get_value() Input: adp5589-keys - fix NULL pointer dereference Revert "Input: Add driver for PixArt PS/2 touchpad"
This commit is contained in:
commit
0d2746a208
@ -391,10 +391,17 @@ static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off)
|
||||
struct adp5589_kpad *kpad = gpiochip_get_data(chip);
|
||||
unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
|
||||
unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
|
||||
int val;
|
||||
|
||||
return !!(adp5589_read(kpad->client,
|
||||
kpad->var->reg(ADP5589_GPI_STATUS_A) + bank) &
|
||||
bit);
|
||||
mutex_lock(&kpad->gpio_lock);
|
||||
if (kpad->dir[bank] & bit)
|
||||
val = kpad->dat_out[bank];
|
||||
else
|
||||
val = adp5589_read(kpad->client,
|
||||
kpad->var->reg(ADP5589_GPI_STATUS_A) + bank);
|
||||
mutex_unlock(&kpad->gpio_lock);
|
||||
|
||||
return !!(val & bit);
|
||||
}
|
||||
|
||||
static void adp5589_gpio_set_value(struct gpio_chip *chip,
|
||||
@ -936,10 +943,9 @@ static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid)
|
||||
|
||||
static void adp5589_clear_config(void *data)
|
||||
{
|
||||
struct i2c_client *client = data;
|
||||
struct adp5589_kpad *kpad = i2c_get_clientdata(client);
|
||||
struct adp5589_kpad *kpad = data;
|
||||
|
||||
adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
|
||||
adp5589_write(kpad->client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
|
||||
}
|
||||
|
||||
static int adp5589_probe(struct i2c_client *client)
|
||||
@ -983,7 +989,7 @@ static int adp5589_probe(struct i2c_client *client)
|
||||
}
|
||||
|
||||
error = devm_add_action_or_reset(&client->dev, adp5589_clear_config,
|
||||
client);
|
||||
kpad);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -1010,8 +1016,6 @@ static int adp5589_probe(struct i2c_client *client)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
i2c_set_clientdata(client, kpad);
|
||||
|
||||
dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq);
|
||||
return 0;
|
||||
}
|
||||
|
@ -69,18 +69,6 @@ config MOUSE_PS2_LOGIPS2PP
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config MOUSE_PS2_PIXART
|
||||
bool "PixArt PS/2 touchpad protocol extension" if EXPERT
|
||||
default y
|
||||
depends on MOUSE_PS2
|
||||
help
|
||||
This driver supports the PixArt PS/2 touchpad found in some
|
||||
laptops.
|
||||
Say Y here if you have a PixArt PS/2 TouchPad connected to
|
||||
your system.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config MOUSE_PS2_SYNAPTICS
|
||||
bool "Synaptics PS/2 mouse protocol extension" if EXPERT
|
||||
default y
|
||||
|
@ -32,7 +32,6 @@ psmouse-$(CONFIG_MOUSE_PS2_ELANTECH) += elantech.o
|
||||
psmouse-$(CONFIG_MOUSE_PS2_OLPC) += hgpk.o
|
||||
psmouse-$(CONFIG_MOUSE_PS2_LOGIPS2PP) += logips2pp.o
|
||||
psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o
|
||||
psmouse-$(CONFIG_MOUSE_PS2_PIXART) += pixart_ps2.o
|
||||
psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o
|
||||
psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o
|
||||
psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o
|
||||
|
@ -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;
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#ifndef _PIXART_PS2_H
|
||||
#define _PIXART_PS2_H
|
||||
|
||||
#include "psmouse.h"
|
||||
|
||||
#define PIXART_PAD_WIDTH 1023
|
||||
#define PIXART_PAD_HEIGHT 579
|
||||
#define PIXART_MAX_FINGERS 4
|
||||
|
||||
#define PIXART_CMD_REPORT_FORMAT 0x01d8
|
||||
#define PIXART_CMD_SWITCH_PROTO 0x00de
|
||||
|
||||
#define PIXART_MODE_REL 0
|
||||
#define PIXART_MODE_ABS 1
|
||||
|
||||
#define PIXART_TYPE_CLICKPAD 0
|
||||
#define PIXART_TYPE_TOUCHPAD 1
|
||||
|
||||
#define CONTACT_CNT_MASK GENMASK(6, 4)
|
||||
|
||||
#define SLOT_ID_MASK GENMASK(2, 0)
|
||||
#define ABS_Y_MASK GENMASK(5, 4)
|
||||
#define ABS_X_MASK GENMASK(7, 6)
|
||||
|
||||
struct pixart_data {
|
||||
u8 mode;
|
||||
u8 type;
|
||||
int x_max;
|
||||
int y_max;
|
||||
};
|
||||
|
||||
int pixart_detect(struct psmouse *psmouse, bool set_properties);
|
||||
int pixart_init(struct psmouse *psmouse);
|
||||
|
||||
#endif /* _PIXART_PS2_H */
|
@ -36,7 +36,6 @@
|
||||
#include "focaltech.h"
|
||||
#include "vmmouse.h"
|
||||
#include "byd.h"
|
||||
#include "pixart_ps2.h"
|
||||
|
||||
#define DRIVER_DESC "PS/2 mouse driver"
|
||||
|
||||
@ -906,15 +905,6 @@ static const struct psmouse_protocol psmouse_protocols[] = {
|
||||
.detect = byd_detect,
|
||||
.init = byd_init,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_MOUSE_PS2_PIXART
|
||||
{
|
||||
.type = PSMOUSE_PIXART,
|
||||
.name = "PixArtPS/2",
|
||||
.alias = "pixart",
|
||||
.detect = pixart_detect,
|
||||
.init = pixart_init,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.type = PSMOUSE_AUTO,
|
||||
@ -1182,13 +1172,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Try PixArt touchpad */
|
||||
if (max_proto > PSMOUSE_IMEX &&
|
||||
psmouse_try_protocol(psmouse, PSMOUSE_PIXART, &max_proto,
|
||||
set_properties, true)) {
|
||||
return PSMOUSE_PIXART;
|
||||
}
|
||||
|
||||
if (max_proto > PSMOUSE_IMEX) {
|
||||
if (psmouse_try_protocol(psmouse, PSMOUSE_GENPS,
|
||||
&max_proto, set_properties, true))
|
||||
|
@ -69,7 +69,6 @@ enum psmouse_type {
|
||||
PSMOUSE_BYD,
|
||||
PSMOUSE_SYNAPTICS_SMBUS,
|
||||
PSMOUSE_ELANTECH_SMBUS,
|
||||
PSMOUSE_PIXART,
|
||||
PSMOUSE_AUTO /* This one should always be last */
|
||||
};
|
||||
|
||||
@ -95,7 +94,7 @@ struct psmouse {
|
||||
const char *vendor;
|
||||
const char *name;
|
||||
const struct psmouse_protocol *protocol;
|
||||
unsigned char packet[16];
|
||||
unsigned char packet[8];
|
||||
unsigned char badbyte;
|
||||
unsigned char pktcnt;
|
||||
unsigned char pktsize;
|
||||
|
Loading…
Reference in New Issue
Block a user