mirror of https://gitee.com/openkylin/linux.git
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input fixes from Dmitry Torokhov: "A fix for the warnings/oops when handling HID devices with "unnamed" LEDs and couple of other driver fixups"" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: goodix - fix touch coordinates on WinBook TW100 and TW700 Input: LEDs - skip unnamed LEDs Input: usbtouchscreen - avoid unresponsive TSC-30 touch screen Input: elantech - force resolution of 31 u/mm Input: zforce - don't overwrite the stack
This commit is contained in:
commit
a52bd79e3e
|
@ -71,6 +71,18 @@ static void input_leds_event(struct input_handle *handle, unsigned int type,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int input_leds_get_count(struct input_dev *dev)
|
||||||
|
{
|
||||||
|
unsigned int led_code;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for_each_set_bit(led_code, dev->ledbit, LED_CNT)
|
||||||
|
if (input_led_info[led_code].name)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static int input_leds_connect(struct input_handler *handler,
|
static int input_leds_connect(struct input_handler *handler,
|
||||||
struct input_dev *dev,
|
struct input_dev *dev,
|
||||||
const struct input_device_id *id)
|
const struct input_device_id *id)
|
||||||
|
@ -81,7 +93,7 @@ static int input_leds_connect(struct input_handler *handler,
|
||||||
int led_no;
|
int led_no;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
num_leds = bitmap_weight(dev->ledbit, LED_CNT);
|
num_leds = input_leds_get_count(dev);
|
||||||
if (!num_leds)
|
if (!num_leds)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
|
@ -112,7 +124,7 @@ static int input_leds_connect(struct input_handler *handler,
|
||||||
led->handle = &leds->handle;
|
led->handle = &leds->handle;
|
||||||
led->code = led_code;
|
led->code = led_code;
|
||||||
|
|
||||||
if (WARN_ON(!input_led_info[led_code].name))
|
if (!input_led_info[led_code].name)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s",
|
led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s",
|
||||||
|
|
|
@ -1167,7 +1167,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
|
||||||
struct input_dev *dev = psmouse->dev;
|
struct input_dev *dev = psmouse->dev;
|
||||||
struct elantech_data *etd = psmouse->private;
|
struct elantech_data *etd = psmouse->private;
|
||||||
unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
|
unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
|
||||||
unsigned int x_res = 0, y_res = 0;
|
unsigned int x_res = 31, y_res = 31;
|
||||||
|
|
||||||
if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
|
if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1232,8 +1232,6 @@ static int elantech_set_input_params(struct psmouse *psmouse)
|
||||||
/* For X to recognize me as touchpad. */
|
/* For X to recognize me as touchpad. */
|
||||||
input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
|
input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
|
||||||
input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
|
input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
|
||||||
input_abs_set_res(dev, ABS_X, x_res);
|
|
||||||
input_abs_set_res(dev, ABS_Y, y_res);
|
|
||||||
/*
|
/*
|
||||||
* range of pressure and width is the same as v2,
|
* range of pressure and width is the same as v2,
|
||||||
* report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility.
|
* report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility.
|
||||||
|
@ -1246,8 +1244,6 @@ static int elantech_set_input_params(struct psmouse *psmouse)
|
||||||
input_mt_init_slots(dev, ETP_MAX_FINGERS, 0);
|
input_mt_init_slots(dev, ETP_MAX_FINGERS, 0);
|
||||||
input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
|
input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
|
||||||
input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
|
input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
|
||||||
input_abs_set_res(dev, ABS_MT_POSITION_X, x_res);
|
|
||||||
input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res);
|
|
||||||
input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2,
|
input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2,
|
||||||
ETP_PMAX_V2, 0, 0);
|
ETP_PMAX_V2, 0, 0);
|
||||||
/*
|
/*
|
||||||
|
@ -1259,6 +1255,13 @@ static int elantech_set_input_params(struct psmouse *psmouse)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input_abs_set_res(dev, ABS_X, x_res);
|
||||||
|
input_abs_set_res(dev, ABS_Y, y_res);
|
||||||
|
if (etd->hw_version > 1) {
|
||||||
|
input_abs_set_res(dev, ABS_MT_POSITION_X, x_res);
|
||||||
|
input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res);
|
||||||
|
}
|
||||||
|
|
||||||
etd->y_max = y_max;
|
etd->y_max = y_max;
|
||||||
etd->width = width;
|
etd->width = width;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/dmi.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <linux/input/mt.h>
|
#include <linux/input/mt.h>
|
||||||
|
@ -34,6 +35,7 @@ struct goodix_ts_data {
|
||||||
int abs_y_max;
|
int abs_y_max;
|
||||||
unsigned int max_touch_num;
|
unsigned int max_touch_num;
|
||||||
unsigned int int_trigger_type;
|
unsigned int int_trigger_type;
|
||||||
|
bool rotated_screen;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define GOODIX_MAX_HEIGHT 4096
|
#define GOODIX_MAX_HEIGHT 4096
|
||||||
|
@ -60,6 +62,30 @@ static const unsigned long goodix_irq_flags[] = {
|
||||||
IRQ_TYPE_LEVEL_HIGH,
|
IRQ_TYPE_LEVEL_HIGH,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Those tablets have their coordinates origin at the bottom right
|
||||||
|
* of the tablet, as if rotated 180 degrees
|
||||||
|
*/
|
||||||
|
static const struct dmi_system_id rotated_screen[] = {
|
||||||
|
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
||||||
|
{
|
||||||
|
.ident = "WinBook TW100",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "TW100")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ident = "WinBook TW700",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "TW700")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* goodix_i2c_read - read data from a register of the i2c slave device.
|
* goodix_i2c_read - read data from a register of the i2c slave device.
|
||||||
*
|
*
|
||||||
|
@ -129,6 +155,11 @@ static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)
|
||||||
int input_y = get_unaligned_le16(&coor_data[3]);
|
int input_y = get_unaligned_le16(&coor_data[3]);
|
||||||
int input_w = get_unaligned_le16(&coor_data[5]);
|
int input_w = get_unaligned_le16(&coor_data[5]);
|
||||||
|
|
||||||
|
if (ts->rotated_screen) {
|
||||||
|
input_x = ts->abs_x_max - input_x;
|
||||||
|
input_y = ts->abs_y_max - input_y;
|
||||||
|
}
|
||||||
|
|
||||||
input_mt_slot(ts->input_dev, id);
|
input_mt_slot(ts->input_dev, id);
|
||||||
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
|
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
|
||||||
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
|
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
|
||||||
|
@ -223,6 +254,11 @@ static void goodix_read_config(struct goodix_ts_data *ts)
|
||||||
ts->abs_y_max = GOODIX_MAX_HEIGHT;
|
ts->abs_y_max = GOODIX_MAX_HEIGHT;
|
||||||
ts->max_touch_num = GOODIX_MAX_CONTACTS;
|
ts->max_touch_num = GOODIX_MAX_CONTACTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ts->rotated_screen = dmi_check_system(rotated_screen);
|
||||||
|
if (ts->rotated_screen)
|
||||||
|
dev_dbg(&ts->client->dev,
|
||||||
|
"Applying '180 degrees rotated screen' quirk\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -627,6 +627,9 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TSC-25 data sheet specifies a delay after the RESET command */
|
||||||
|
msleep(150);
|
||||||
|
|
||||||
/* set coordinate output rate */
|
/* set coordinate output rate */
|
||||||
buf[0] = buf[1] = 0xFF;
|
buf[0] = buf[1] = 0xFF;
|
||||||
ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
|
ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
|
||||||
|
|
|
@ -429,7 +429,7 @@ static int zforce_read_packet(struct zforce_ts *ts, u8 *buf)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf[PAYLOAD_LENGTH] == 0) {
|
if (buf[PAYLOAD_LENGTH] == 0 || buf[PAYLOAD_LENGTH] > FRAME_MAXSIZE) {
|
||||||
dev_err(&client->dev, "invalid payload length: %d\n",
|
dev_err(&client->dev, "invalid payload length: %d\n",
|
||||||
buf[PAYLOAD_LENGTH]);
|
buf[PAYLOAD_LENGTH]);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
|
|
Loading…
Reference in New Issue