Commit 79d11f2a authored by Hans de Goede's avatar Hans de Goede Committed by Jiri Kosina

HID: elan: Query device max_x and max_y value from touchpad

Query the device's max_x and max_y value from the touchpad rather then
hardcoding it. This makes adding support for other USB ids a lot easier.
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 314f04e8
...@@ -27,20 +27,22 @@ ...@@ -27,20 +27,22 @@
#define ELAN_MAX_PRESSURE 255 #define ELAN_MAX_PRESSURE 255
#define ELAN_TP_USB_INTF 1 #define ELAN_TP_USB_INTF 1
#define ELAN_FEATURE_REPORT 0x0d
#define ELAN_FEATURE_SIZE 5
#define ELAN_PARAM_MAX_X 6
#define ELAN_PARAM_MAX_Y 7
#define ELAN_PARAM_RES 8
#define ELAN_MUTE_LED_REPORT 0xBC #define ELAN_MUTE_LED_REPORT 0xBC
#define ELAN_LED_REPORT_SIZE 8 #define ELAN_LED_REPORT_SIZE 8
struct elan_touchpad_settings {
u16 max_x;
u16 max_y;
};
struct elan_drvdata { struct elan_drvdata {
struct input_dev *input; struct input_dev *input;
u8 prev_report[ELAN_INPUT_REPORT_SIZE]; u8 prev_report[ELAN_INPUT_REPORT_SIZE];
struct led_classdev mute_led; struct led_classdev mute_led;
u8 mute_led_state; u8 mute_led_state;
struct elan_touchpad_settings *settings; u16 max_x;
u16 max_y;
}; };
static int is_not_elan_touchpad(struct hid_device *hdev) static int is_not_elan_touchpad(struct hid_device *hdev)
...@@ -65,6 +67,63 @@ static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -65,6 +67,63 @@ static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 0; return 0;
} }
static int elan_get_device_param(struct hid_device *hdev,
unsigned char *dmabuf, unsigned char param)
{
int ret;
dmabuf[0] = ELAN_FEATURE_REPORT;
dmabuf[1] = 0x05;
dmabuf[2] = 0x03;
dmabuf[3] = param;
dmabuf[4] = 0x01;
ret = hid_hw_raw_request(hdev, ELAN_FEATURE_REPORT, dmabuf,
ELAN_FEATURE_SIZE, HID_FEATURE_REPORT,
HID_REQ_SET_REPORT);
if (ret != ELAN_FEATURE_SIZE) {
hid_err(hdev, "Set report error for parm %d: %d\n", param, ret);
return ret;
}
ret = hid_hw_raw_request(hdev, ELAN_FEATURE_REPORT, dmabuf,
ELAN_FEATURE_SIZE, HID_FEATURE_REPORT,
HID_REQ_GET_REPORT);
if (ret != ELAN_FEATURE_SIZE) {
hid_err(hdev, "Get report error for parm %d: %d\n", param, ret);
return ret;
}
return 0;
}
static int elan_get_device_params(struct hid_device *hdev)
{
struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
unsigned char *dmabuf;
int ret;
dmabuf = kmalloc(ELAN_FEATURE_SIZE, GFP_KERNEL);
if (!dmabuf)
return -ENOMEM;
ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_MAX_X);
if (ret)
goto err;
drvdata->max_x = (dmabuf[4] << 8) | dmabuf[3];
ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_MAX_Y);
if (ret)
goto err;
drvdata->max_y = (dmabuf[4] << 8) | dmabuf[3];
err:
kfree(dmabuf);
return ret;
}
static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi) static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
{ {
int ret; int ret;
...@@ -74,6 +133,10 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi) ...@@ -74,6 +133,10 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
if (is_not_elan_touchpad(hdev)) if (is_not_elan_touchpad(hdev))
return 0; return 0;
ret = elan_get_device_params(hdev);
if (ret)
return ret;
input = devm_input_allocate_device(&hdev->dev); input = devm_input_allocate_device(&hdev->dev);
if (!input) if (!input)
return -ENOMEM; return -ENOMEM;
...@@ -87,10 +150,10 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi) ...@@ -87,10 +150,10 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
input->id.version = hdev->version; input->id.version = hdev->version;
input->dev.parent = &hdev->dev; input->dev.parent = &hdev->dev;
input_set_abs_params(input, ABS_MT_POSITION_X, 0, input_set_abs_params(input, ABS_MT_POSITION_X, 0, drvdata->max_x,
drvdata->settings->max_x, 0, 0); 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, input_set_abs_params(input, ABS_MT_POSITION_Y, 0, drvdata->max_y,
drvdata->settings->max_y, 0, 0); 0, 0);
input_set_abs_params(input, ABS_MT_PRESSURE, 0, ELAN_MAX_PRESSURE, input_set_abs_params(input, ABS_MT_PRESSURE, 0, ELAN_MAX_PRESSURE,
0, 0); 0, 0);
...@@ -128,7 +191,7 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data, ...@@ -128,7 +191,7 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
input_mt_report_slot_state(input, MT_TOOL_FINGER, active); input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
if (active) { if (active) {
x = ((data[0] & 0xF0) << 4) | data[1]; x = ((data[0] & 0xF0) << 4) | data[1];
y = drvdata->settings->max_y - y = drvdata->max_y -
(((data[0] & 0x07) << 8) | data[2]); (((data[0] & 0x07) << 8) | data[2]);
p = data[4]; p = data[4];
...@@ -339,7 +402,6 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -339,7 +402,6 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (!drvdata) if (!drvdata)
return -ENOMEM; return -ENOMEM;
drvdata->settings = (struct elan_touchpad_settings *)id->driver_data;
hid_set_drvdata(hdev, drvdata); hid_set_drvdata(hdev, drvdata);
ret = hid_parse(hdev); ret = hid_parse(hdev);
...@@ -382,17 +444,10 @@ static void elan_remove(struct hid_device *hdev) ...@@ -382,17 +444,10 @@ static void elan_remove(struct hid_device *hdev)
hid_hw_stop(hdev); hid_hw_stop(hdev);
} }
static const struct elan_touchpad_settings hp_x2_10_touchpad_data = {
.max_x = 2930,
.max_y = 1250,
};
static const struct hid_device_id elan_devices[] = { static const struct hid_device_id elan_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER), { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER) },
(kernel_ulong_t)&hp_x2_10_touchpad_data},
{ } { }
}; };
MODULE_DEVICE_TABLE(hid, elan_devices); MODULE_DEVICE_TABLE(hid, elan_devices);
static struct hid_driver elan_driver = { static struct hid_driver elan_driver = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment