From 043b403aede4a528ed99ceaf050f567f1283a23e Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 18 Mar 2011 14:27:53 +0100 Subject: HID: hid-multitouch: migrate support for Stantum panels to the unified driver. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch merges hid-stantum to the generic multitouch driver. Signed-off-by: Benjamin Tissoires Reviewed-by: Stéphane Chatty Reviewed-by: Henrik Rydberg Signed-off-by: Jiri Kosina --- drivers/hid/Makefile | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/hid/Makefile') diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 06c68ae3abe..a13cb4e99ff 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -66,7 +66,6 @@ obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o obj-$(CONFIG_HID_SONY) += hid-sony.o -obj-$(CONFIG_HID_STANTUM) += hid-stantum.o obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o -- cgit v1.2.3-70-g09d2 From a841b62c5d5f75ce3676fde755696d30cc8de99a Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 18 Mar 2011 14:27:54 +0100 Subject: HID: hid-multitouch: migrate Cando dual touch panels to hid-multitouch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch merges hid-cando into the unified multitouch driver. Signed-off-by: Benjamin Tissoires Reviewed-by: Stéphane Chatty Reviewed-by: Henrik Rydberg Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 7 +- drivers/hid/Makefile | 1 - drivers/hid/hid-cando.c | 276 ------------------------------------------- drivers/hid/hid-multitouch.c | 14 +++ 4 files changed, 15 insertions(+), 283 deletions(-) delete mode 100644 drivers/hid/hid-cando.c (limited to 'drivers/hid/Makefile') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 3c72f16e725..1edb0bd72a6 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -100,12 +100,6 @@ config HID_BELKIN ---help--- Support for Belkin Flip KVM and Wireless keyboard. -config HID_CANDO - tristate "Cando dual touch panel" - depends on USB_HID - ---help--- - Support for Cando dual touch panel. - config HID_CHERRY tristate "Cherry Cymotion keyboard" if EXPERT depends on USB_HID @@ -320,6 +314,7 @@ config HID_MULTITOUCH Generic support for HID multitouch panels. Say Y here if you have one of the following devices: + - Cando dual touch panel - Cypress TrueTouch panels - Hanvon dual touch panels - IrTouch Infrared USB panels diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index a13cb4e99ff..f8b90e4e484 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -30,7 +30,6 @@ obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o obj-$(CONFIG_HID_ACRUX) += hid-axff.o obj-$(CONFIG_HID_APPLE) += hid-apple.o obj-$(CONFIG_HID_BELKIN) += hid-belkin.o -obj-$(CONFIG_HID_CANDO) += hid-cando.o obj-$(CONFIG_HID_CHERRY) += hid-cherry.o obj-$(CONFIG_HID_CHICONY) += hid-chicony.o obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o diff --git a/drivers/hid/hid-cando.c b/drivers/hid/hid-cando.c deleted file mode 100644 index 1ea066c5520..00000000000 --- a/drivers/hid/hid-cando.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * HID driver for Cando dual-touch panels - * - * Copyright (c) 2010 Stephane Chatty - * - */ - -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - */ - -#include -#include -#include -#include - -MODULE_AUTHOR("Stephane Chatty "); -MODULE_DESCRIPTION("Cando dual-touch panel"); -MODULE_LICENSE("GPL"); - -#include "hid-ids.h" - -struct cando_data { - __u16 x, y; - __u8 id; - __s8 oldest; /* id of the oldest finger in previous frame */ - bool valid; /* valid finger data, or just placeholder? */ - bool first; /* is this the first finger in this frame? */ - __s8 firstid; /* id of the first finger in the frame */ - __u16 firstx, firsty; /* (x, y) of the first finger in the frame */ -}; - -static int cando_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - switch (usage->hid & HID_USAGE_PAGE) { - - case HID_UP_GENDESK: - switch (usage->hid) { - case HID_GD_X: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_X); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_X, - field->logical_minimum, - field->logical_maximum, 0, 0); - return 1; - case HID_GD_Y: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_Y); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_Y, - field->logical_minimum, - field->logical_maximum, 0, 0); - return 1; - } - return 0; - - case HID_UP_DIGITIZER: - switch (usage->hid) { - case HID_DG_TIPSWITCH: - case HID_DG_CONTACTMAX: - return -1; - case HID_DG_INRANGE: - /* touchscreen emulation */ - hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); - return 1; - case HID_DG_CONTACTID: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TRACKING_ID); - return 1; - } - return 0; - } - - return 0; -} - -static int cando_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if (usage->type == EV_KEY || usage->type == EV_ABS) - clear_bit(usage->code, *bit); - - return 0; -} - -/* - * this function is called when a whole finger has been parsed, - * so that it can decide what to send to the input layer. - */ -static void cando_filter_event(struct cando_data *td, struct input_dev *input) -{ - td->first = !td->first; /* touchscreen emulation */ - - if (!td->valid) { - /* - * touchscreen emulation: if this is the second finger and - * the first was valid, the first was the oldest; if the - * first was not valid and there was a valid finger in the - * previous frame, this is a release. - */ - if (td->first) { - td->firstid = -1; - } else if (td->firstid >= 0) { - input_event(input, EV_ABS, ABS_X, td->firstx); - input_event(input, EV_ABS, ABS_Y, td->firsty); - td->oldest = td->firstid; - } else if (td->oldest >= 0) { - input_event(input, EV_KEY, BTN_TOUCH, 0); - td->oldest = -1; - } - - return; - } - - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); - input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); - - input_mt_sync(input); - - /* - * touchscreen emulation: if there was no touching finger previously, - * emit touch event - */ - if (td->oldest < 0) { - input_event(input, EV_KEY, BTN_TOUCH, 1); - td->oldest = td->id; - } - - /* - * touchscreen emulation: if this is the first finger, wait for the - * second; the oldest is then the second if it was the oldest already - * or if there was no first, the first otherwise. - */ - if (td->first) { - td->firstx = td->x; - td->firsty = td->y; - td->firstid = td->id; - } else { - int x, y, oldest; - if (td->id == td->oldest || td->firstid < 0) { - x = td->x; - y = td->y; - oldest = td->id; - } else { - x = td->firstx; - y = td->firsty; - oldest = td->firstid; - } - input_event(input, EV_ABS, ABS_X, x); - input_event(input, EV_ABS, ABS_Y, y); - td->oldest = oldest; - } -} - - -static int cando_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - struct cando_data *td = hid_get_drvdata(hid); - - if (hid->claimed & HID_CLAIMED_INPUT) { - struct input_dev *input = field->hidinput->input; - - switch (usage->hid) { - case HID_DG_INRANGE: - td->valid = value; - break; - case HID_DG_CONTACTID: - td->id = value; - break; - case HID_GD_X: - td->x = value; - break; - case HID_GD_Y: - td->y = value; - cando_filter_event(td, input); - break; - case HID_DG_TIPSWITCH: - /* avoid interference from generic hidinput handling */ - break; - - default: - /* fallback to the generic hidinput handling */ - return 0; - } - } - - /* we have handled the hidinput part, now remains hiddev */ - if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) - hid->hiddev_hid_event(hid, field, usage, value); - - return 1; -} - -static int cando_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - struct cando_data *td; - - td = kmalloc(sizeof(struct cando_data), GFP_KERNEL); - if (!td) { - hid_err(hdev, "cannot allocate Cando Touch data\n"); - return -ENOMEM; - } - hid_set_drvdata(hdev, td); - td->first = false; - td->oldest = -1; - td->valid = false; - - ret = hid_parse(hdev); - if (!ret) - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - - if (ret) - kfree(td); - - return ret; -} - -static void cando_remove(struct hid_device *hdev) -{ - hid_hw_stop(hdev); - kfree(hid_get_drvdata(hdev)); - hid_set_drvdata(hdev, NULL); -} - -static const struct hid_device_id cando_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, - USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, - USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, - USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, - { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, - USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, - { } -}; -MODULE_DEVICE_TABLE(hid, cando_devices); - -static const struct hid_usage_id cando_grabbed_usages[] = { - { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, - { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} -}; - -static struct hid_driver cando_driver = { - .name = "cando-touch", - .id_table = cando_devices, - .probe = cando_probe, - .remove = cando_remove, - .input_mapping = cando_input_mapping, - .input_mapped = cando_input_mapped, - .usage_table = cando_grabbed_usages, - .event = cando_event, -}; - -static int __init cando_init(void) -{ - return hid_register_driver(&cando_driver); -} - -static void __exit cando_exit(void) -{ - hid_unregister_driver(&cando_driver); -} - -module_init(cando_init); -module_exit(cando_exit); - diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 5983e5559e8..e6e1ea25149 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -514,6 +514,20 @@ static void mt_remove(struct hid_device *hdev) static const struct hid_device_id mt_devices[] = { + /* Cando panels */ + { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, + HID_USB_DEVICE(USB_VENDOR_ID_CANDO, + USB_DEVICE_ID_CANDO_MULTI_TOUCH) }, + { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, + HID_USB_DEVICE(USB_VENDOR_ID_CANDO, + USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) }, + { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, + HID_USB_DEVICE(USB_VENDOR_ID_CANDO, + USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) }, + { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, + HID_USB_DEVICE(USB_VENDOR_ID_CANDO, + USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, + /* Cypress panel */ { .driver_data = MT_CLS_CYPRESS, HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, -- cgit v1.2.3-70-g09d2 From f786bba4499cf3de20da345ce090457ebcef03b0 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 22 Mar 2011 17:34:01 +0100 Subject: HID: hid-multitouch: migrate 3M PCT touch screens to hid-multitouch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch merges the hid-3m-pct driver into hid-multitouch. To keep devices working the same way they used to with hid-3m-pct, we need to add two signal/noise ratios for width and height. We also need to work on width/height to send proper ABS_MT_ORIENTATION flag. Importing 3M into hid-multitouch also solved the bug in which devices handling width and height in their report descriptors did not show ABS_MT_TOUCH_MAJOR and ABS_MT_TOUCH_MINOR. Signed-off-by: Benjamin Tissoires Reviewed-by: Stéphane Chatty Reviewed-and-tested-by: Henrik Rydberg Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 7 +- drivers/hid/Makefile | 1 - drivers/hid/hid-3m-pct.c | 305 ------------------------------------------- drivers/hid/hid-multitouch.c | 47 ++++++- 4 files changed, 46 insertions(+), 314 deletions(-) delete mode 100644 drivers/hid/hid-3m-pct.c (limited to 'drivers/hid/Makefile') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 1edb0bd72a6..996ae3ac324 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -55,12 +55,6 @@ source "drivers/hid/usbhid/Kconfig" menu "Special HID drivers" depends on HID -config HID_3M_PCT - tristate "3M PCT touchscreen" - depends on USB_HID - ---help--- - Support for 3M PCT touch screens. - config HID_A4TECH tristate "A4 tech mice" if EXPERT depends on USB_HID @@ -314,6 +308,7 @@ config HID_MULTITOUCH Generic support for HID multitouch panels. Say Y here if you have one of the following devices: + - 3M PCT touch screens - Cando dual touch panel - Cypress TrueTouch panels - Hanvon dual touch panels diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index f8b90e4e484..11c9f0b127e 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -25,7 +25,6 @@ ifdef CONFIG_LOGIWII_FF hid-logitech-y += hid-lg4ff.o endif -obj-$(CONFIG_HID_3M_PCT) += hid-3m-pct.o obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o obj-$(CONFIG_HID_ACRUX) += hid-axff.o obj-$(CONFIG_HID_APPLE) += hid-apple.o diff --git a/drivers/hid/hid-3m-pct.c b/drivers/hid/hid-3m-pct.c deleted file mode 100644 index 5243ae2d373..00000000000 --- a/drivers/hid/hid-3m-pct.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * HID driver for 3M PCT multitouch panels - * - * Copyright (c) 2009-2010 Stephane Chatty - * Copyright (c) 2010 Henrik Rydberg - * Copyright (c) 2010 Canonical, Ltd. - * - */ - -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - */ - -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Stephane Chatty "); -MODULE_DESCRIPTION("3M PCT multitouch panels"); -MODULE_LICENSE("GPL"); - -#include "hid-ids.h" - -#define MAX_SLOTS 60 - -/* estimated signal-to-noise ratios */ -#define SN_MOVE 2048 -#define SN_WIDTH 128 - -struct mmm_finger { - __s32 x, y, w, h; - bool touch, valid; -}; - -struct mmm_data { - struct mmm_finger f[MAX_SLOTS]; - __u8 curid; - __u8 nexp, nreal; - bool touch, valid; -}; - -static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - int f1 = field->logical_minimum; - int f2 = field->logical_maximum; - int df = f2 - f1; - - switch (usage->hid & HID_USAGE_PAGE) { - - case HID_UP_BUTTON: - return -1; - - case HID_UP_GENDESK: - switch (usage->hid) { - case HID_GD_X: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_X); - input_set_abs_params(hi->input, ABS_MT_POSITION_X, - f1, f2, df / SN_MOVE, 0); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_X, - f1, f2, df / SN_MOVE, 0); - return 1; - case HID_GD_Y: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_Y); - input_set_abs_params(hi->input, ABS_MT_POSITION_Y, - f1, f2, df / SN_MOVE, 0); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_Y, - f1, f2, df / SN_MOVE, 0); - return 1; - } - return 0; - - case HID_UP_DIGITIZER: - switch (usage->hid) { - /* we do not want to map these: no input-oriented meaning */ - case 0x14: - case 0x23: - case HID_DG_INPUTMODE: - case HID_DG_DEVICEINDEX: - case HID_DG_CONTACTCOUNT: - case HID_DG_CONTACTMAX: - case HID_DG_INRANGE: - case HID_DG_CONFIDENCE: - return -1; - case HID_DG_TIPSWITCH: - /* touchscreen emulation */ - hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); - input_set_capability(hi->input, EV_KEY, BTN_TOUCH); - return 1; - case HID_DG_WIDTH: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MAJOR); - input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR, - f1, f2, df / SN_WIDTH, 0); - return 1; - case HID_DG_HEIGHT: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MINOR); - input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR, - f1, f2, df / SN_WIDTH, 0); - input_set_abs_params(hi->input, ABS_MT_ORIENTATION, - 0, 1, 0, 0); - return 1; - case HID_DG_CONTACTID: - input_mt_init_slots(hi->input, MAX_SLOTS); - return 1; - } - /* let hid-input decide for the others */ - return 0; - - case 0xff000000: - /* we do not want to map these: no input-oriented meaning */ - return -1; - } - - return 0; -} - -static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - /* tell hid-input to skip setup of these event types */ - if (usage->type == EV_KEY || usage->type == EV_ABS) - set_bit(usage->type, hi->input->evbit); - return -1; -} - -/* - * this function is called when a whole packet has been received and processed, - * so that it can decide what to send to the input layer. - */ -static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) -{ - int i; - for (i = 0; i < MAX_SLOTS; ++i) { - struct mmm_finger *f = &md->f[i]; - if (!f->valid) { - /* this finger is just placeholder data, ignore */ - continue; - } - input_mt_slot(input, i); - input_mt_report_slot_state(input, MT_TOOL_FINGER, f->touch); - if (f->touch) { - /* this finger is on the screen */ - int wide = (f->w > f->h); - /* divided by two to match visual scale of touch */ - int major = max(f->w, f->h) >> 1; - int minor = min(f->w, f->h) >> 1; - - input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); - input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); - input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); - input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); - } - f->valid = 0; - } - - input_mt_report_pointer_emulation(input, true); - input_sync(input); -} - -/* - * this function is called upon all reports - * so that we can accumulate contact point information, - * and call input_mt_sync after each point. - */ -static int mmm_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - struct mmm_data *md = hid_get_drvdata(hid); - /* - * strangely, this function can be called before - * field->hidinput is initialized! - */ - if (hid->claimed & HID_CLAIMED_INPUT) { - struct input_dev *input = field->hidinput->input; - switch (usage->hid) { - case HID_DG_TIPSWITCH: - md->touch = value; - break; - case HID_DG_CONFIDENCE: - md->valid = value; - break; - case HID_DG_WIDTH: - if (md->valid) - md->f[md->curid].w = value; - break; - case HID_DG_HEIGHT: - if (md->valid) - md->f[md->curid].h = value; - break; - case HID_DG_CONTACTID: - value = clamp_val(value, 0, MAX_SLOTS - 1); - if (md->valid) { - md->curid = value; - md->f[value].touch = md->touch; - md->f[value].valid = 1; - md->nreal++; - } - break; - case HID_GD_X: - if (md->valid) - md->f[md->curid].x = value; - break; - case HID_GD_Y: - if (md->valid) - md->f[md->curid].y = value; - break; - case HID_DG_CONTACTCOUNT: - if (value) - md->nexp = value; - if (md->nreal >= md->nexp) { - mmm_filter_event(md, input); - md->nreal = 0; - } - break; - } - } - - /* we have handled the hidinput part, now remains hiddev */ - if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) - hid->hiddev_hid_event(hid, field, usage, value); - - return 1; -} - -static int mmm_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - struct mmm_data *md; - - hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; - - md = kzalloc(sizeof(struct mmm_data), GFP_KERNEL); - if (!md) { - hid_err(hdev, "cannot allocate 3M data\n"); - return -ENOMEM; - } - hid_set_drvdata(hdev, md); - - ret = hid_parse(hdev); - if (!ret) - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - - if (ret) - kfree(md); - return ret; -} - -static void mmm_remove(struct hid_device *hdev) -{ - hid_hw_stop(hdev); - kfree(hid_get_drvdata(hdev)); - hid_set_drvdata(hdev, NULL); -} - -static const struct hid_device_id mmm_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M1968) }, - { HID_USB_DEVICE(USB_VENDOR_ID_3M, USB_DEVICE_ID_3M2256) }, - { } -}; -MODULE_DEVICE_TABLE(hid, mmm_devices); - -static const struct hid_usage_id mmm_grabbed_usages[] = { - { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, - { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} -}; - -static struct hid_driver mmm_driver = { - .name = "3m-pct", - .id_table = mmm_devices, - .probe = mmm_probe, - .remove = mmm_remove, - .input_mapping = mmm_input_mapping, - .input_mapped = mmm_input_mapped, - .usage_table = mmm_grabbed_usages, - .event = mmm_event, -}; - -static int __init mmm_init(void) -{ - return hid_register_driver(&mmm_driver); -} - -static void __exit mmm_exit(void) -{ - hid_unregister_driver(&mmm_driver); -} - -module_init(mmm_init); -module_exit(mmm_exit); - diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index d31301e85c5..0175f858309 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -11,6 +11,12 @@ * Copyright (c) 2010 Henrik Rydberg * Copyright (c) 2010 Canonical, Ltd. * + * This code is partly based on hid-3m-pct.c: + * + * Copyright (c) 2009-2010 Stephane Chatty + * Copyright (c) 2010 Henrik Rydberg + * Copyright (c) 2010 Canonical, Ltd. + * */ /* @@ -69,6 +75,8 @@ struct mt_class { __s32 name; /* MT_CLS */ __s32 quirks; __s32 sn_move; /* Signal/noise ratio for move events */ + __s32 sn_width; /* Signal/noise ratio for width events */ + __s32 sn_height; /* Signal/noise ratio for height events */ __s32 sn_pressure; /* Signal/noise ratio for pressure events */ __u8 maxcontacts; }; @@ -80,6 +88,7 @@ struct mt_class { #define MT_CLS_CYPRESS 4 #define MT_CLS_EGALAX 5 #define MT_CLS_STANTUM 6 +#define MT_CLS_3M 7 #define MT_DEFAULT_MAXCONTACT 10 @@ -141,6 +150,12 @@ struct mt_class mt_classes[] = { }, { .name = MT_CLS_STANTUM, .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, + { .name = MT_CLS_3M, + .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | + MT_QUIRK_SLOT_IS_CONTACTID, + .sn_move = 2048, + .sn_width = 128, + .sn_height = 128 }, { } }; @@ -230,11 +245,15 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR); + set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, + cls->sn_width); td->last_slot_field = usage->hid; return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MINOR); + set_abs(hi->input, ABS_MT_TOUCH_MINOR, field, + cls->sn_height); input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 0, 1, 0, 0); td->last_slot_field = usage->hid; @@ -332,11 +351,18 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input) input_mt_report_slot_state(input, MT_TOOL_FINGER, s->touch_state); if (s->touch_state) { + /* this finger is on the screen */ + int wide = (s->w > s->h); + /* divided by two to match visual scale of touch */ + int major = max(s->w, s->h) >> 1; + int minor = min(s->w, s->h) >> 1; + input_event(input, EV_ABS, ABS_MT_POSITION_X, s->x); input_event(input, EV_ABS, ABS_MT_POSITION_Y, s->y); + input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); - input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, s->w); - input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, s->h); + input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); + input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); } s->seen_in_this_frame = false; @@ -398,6 +424,15 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, break; default: + if (td->last_field_index + && field->index == td->last_field_index) + /* we reach here when the last field in the + * report is not related to multitouch. + * This is not good. As a temporary solution, + * we trigger our mt event completion and + * ignore the field. + */ + break; /* fallback to the generic hidinput handling */ return 0; } @@ -513,6 +548,14 @@ static void mt_remove(struct hid_device *hdev) static const struct hid_device_id mt_devices[] = { + /* 3M panels */ + { .driver_data = MT_CLS_3M, + HID_USB_DEVICE(USB_VENDOR_ID_3M, + USB_DEVICE_ID_3M1968) }, + { .driver_data = MT_CLS_3M, + HID_USB_DEVICE(USB_VENDOR_ID_3M, + USB_DEVICE_ID_3M2256) }, + /* Cando panels */ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, HID_USB_DEVICE(USB_VENDOR_ID_CANDO, -- cgit v1.2.3-70-g09d2 From 4a6ee685fbcba4a440cf86f41557752ba81e2ccf Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 22 Apr 2011 11:51:48 +0200 Subject: HID: hid-multitouch: merge hid-mosart into hid-multitouch This patch include MosArt devices into hid-multitouch. MosArt devices now support mt-protocol B. We also need to introduce a new quirk for mosart devices to support their contactID. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 7 +- drivers/hid/Makefile | 1 - drivers/hid/hid-mosart.c | 296 ------------------------------------------- drivers/hid/hid-multitouch.c | 20 ++- 4 files changed, 20 insertions(+), 304 deletions(-) delete mode 100644 drivers/hid/hid-mosart.c (limited to 'drivers/hid/Makefile') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 8058cf1ba83..d2d4e5f1911 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -288,12 +288,6 @@ config HID_MICROSOFT ---help--- Support for Microsoft devices that are not fully compliant with HID standard. -config HID_MOSART - tristate "MosArt dual-touch panels" - depends on USB_HID - ---help--- - Support for MosArt dual-touch panels. - config HID_MONTEREY tristate "Monterey Genius KB29E keyboard" if EXPERT depends on USB_HID @@ -313,6 +307,7 @@ config HID_MULTITOUCH - Cypress TrueTouch panels - Hanvon dual touch panels - IrTouch Infrared USB panels + - MosArt dual-touch panels - PenMount dual touch panels - Pixcir dual touch panels - 'Sensing Win7-TwoFinger' panel by GeneralTouch diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 11c9f0b127e..f8cc4ea7335 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -45,7 +45,6 @@ obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o -obj-$(CONFIG_HID_MOSART) += hid-mosart.o obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o obj-$(CONFIG_HID_NTRIG) += hid-ntrig.o obj-$(CONFIG_HID_ORTEK) += hid-ortek.o diff --git a/drivers/hid/hid-mosart.c b/drivers/hid/hid-mosart.c deleted file mode 100644 index aed7ffe3628..00000000000 --- a/drivers/hid/hid-mosart.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * HID driver for the multitouch panel on the ASUS EeePC T91MT - * - * Copyright (c) 2009-2010 Stephane Chatty - * Copyright (c) 2010 Teemu Tuominen - * - */ - -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - */ - -#include -#include -#include -#include -#include -#include "usbhid/usbhid.h" - -MODULE_AUTHOR("Stephane Chatty "); -MODULE_DESCRIPTION("MosArt dual-touch panel"); -MODULE_LICENSE("GPL"); - -#include "hid-ids.h" - -struct mosart_data { - __u16 x, y; - __u8 id; - bool valid; /* valid finger data, or just placeholder? */ - bool first; /* is this the first finger in this frame? */ - bool activity_now; /* at least one active finger in this frame? */ - bool activity; /* at least one active finger previously? */ -}; - -static int mosart_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - switch (usage->hid & HID_USAGE_PAGE) { - - case HID_UP_GENDESK: - switch (usage->hid) { - case HID_GD_X: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_X); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_X, - field->logical_minimum, - field->logical_maximum, 0, 0); - return 1; - case HID_GD_Y: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_Y); - /* touchscreen emulation */ - input_set_abs_params(hi->input, ABS_Y, - field->logical_minimum, - field->logical_maximum, 0, 0); - return 1; - } - return 0; - - case HID_UP_DIGITIZER: - switch (usage->hid) { - case HID_DG_CONFIDENCE: - case HID_DG_TIPSWITCH: - case HID_DG_INPUTMODE: - case HID_DG_DEVICEINDEX: - case HID_DG_CONTACTCOUNT: - case HID_DG_CONTACTMAX: - case HID_DG_TIPPRESSURE: - case HID_DG_WIDTH: - case HID_DG_HEIGHT: - return -1; - case HID_DG_INRANGE: - /* touchscreen emulation */ - hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); - return 1; - - case HID_DG_CONTACTID: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TRACKING_ID); - return 1; - - } - return 0; - - case 0xff000000: - /* ignore HID features */ - return -1; - - case HID_UP_BUTTON: - /* ignore buttons */ - return -1; - } - - return 0; -} - -static int mosart_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) -{ - if (usage->type == EV_KEY || usage->type == EV_ABS) - clear_bit(usage->code, *bit); - - return 0; -} - -/* - * this function is called when a whole finger has been parsed, - * so that it can decide what to send to the input layer. - */ -static void mosart_filter_event(struct mosart_data *td, struct input_dev *input) -{ - td->first = !td->first; /* touchscreen emulation */ - - if (!td->valid) { - /* - * touchscreen emulation: if no finger in this frame is valid - * and there previously was finger activity, this is a release - */ - if (!td->first && !td->activity_now && td->activity) { - input_event(input, EV_KEY, BTN_TOUCH, 0); - td->activity = false; - } - return; - } - - input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); - input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); - - input_mt_sync(input); - td->valid = false; - - /* touchscreen emulation: if first active finger in this frame... */ - if (!td->activity_now) { - /* if there was no previous activity, emit touch event */ - if (!td->activity) { - input_event(input, EV_KEY, BTN_TOUCH, 1); - td->activity = true; - } - td->activity_now = true; - /* and in any case this is our preferred finger */ - input_event(input, EV_ABS, ABS_X, td->x); - input_event(input, EV_ABS, ABS_Y, td->y); - } -} - - -static int mosart_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) -{ - struct mosart_data *td = hid_get_drvdata(hid); - - if (hid->claimed & HID_CLAIMED_INPUT) { - struct input_dev *input = field->hidinput->input; - switch (usage->hid) { - case HID_DG_INRANGE: - td->valid = !!value; - break; - case HID_GD_X: - td->x = value; - break; - case HID_GD_Y: - td->y = value; - mosart_filter_event(td, input); - break; - case HID_DG_CONTACTID: - td->id = value; - break; - case HID_DG_CONTACTCOUNT: - /* touch emulation: this is the last field in a frame */ - td->first = false; - td->activity_now = false; - break; - case HID_DG_CONFIDENCE: - case HID_DG_TIPSWITCH: - /* avoid interference from generic hidinput handling */ - break; - - default: - /* fallback to the generic hidinput handling */ - return 0; - } - } - - /* we have handled the hidinput part, now remains hiddev */ - if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) - hid->hiddev_hid_event(hid, field, usage, value); - - return 1; -} - -static int mosart_probe(struct hid_device *hdev, const struct hid_device_id *id) -{ - int ret; - struct mosart_data *td; - - - td = kmalloc(sizeof(struct mosart_data), GFP_KERNEL); - if (!td) { - hid_err(hdev, "cannot allocate MosArt data\n"); - return -ENOMEM; - } - td->valid = false; - td->activity = false; - td->activity_now = false; - td->first = false; - hid_set_drvdata(hdev, td); - - /* currently, it's better to have one evdev device only */ -#if 0 - hdev->quirks |= HID_QUIRK_MULTI_INPUT; -#endif - - ret = hid_parse(hdev); - if (ret == 0) - ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); - - if (ret == 0) { - struct hid_report_enum *re = hdev->report_enum - + HID_FEATURE_REPORT; - struct hid_report *r = re->report_id_hash[7]; - - r->field[0]->value[0] = 0x02; - usbhid_submit_report(hdev, r, USB_DIR_OUT); - } else - kfree(td); - - return ret; -} - -#ifdef CONFIG_PM -static int mosart_reset_resume(struct hid_device *hdev) -{ - struct hid_report_enum *re = hdev->report_enum - + HID_FEATURE_REPORT; - struct hid_report *r = re->report_id_hash[7]; - - r->field[0]->value[0] = 0x02; - usbhid_submit_report(hdev, r, USB_DIR_OUT); - return 0; -} -#endif - -static void mosart_remove(struct hid_device *hdev) -{ - hid_hw_stop(hdev); - kfree(hid_get_drvdata(hdev)); - hid_set_drvdata(hdev, NULL); -} - -static const struct hid_device_id mosart_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, - { } -}; -MODULE_DEVICE_TABLE(hid, mosart_devices); - -static const struct hid_usage_id mosart_grabbed_usages[] = { - { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID }, - { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} -}; - -static struct hid_driver mosart_driver = { - .name = "mosart", - .id_table = mosart_devices, - .probe = mosart_probe, - .remove = mosart_remove, - .input_mapping = mosart_input_mapping, - .input_mapped = mosart_input_mapped, - .usage_table = mosart_grabbed_usages, - .event = mosart_event, -#ifdef CONFIG_PM - .reset_resume = mosart_reset_resume, -#endif -}; - -static int __init mosart_init(void) -{ - return hid_register_driver(&mosart_driver); -} - -static void __exit mosart_exit(void) -{ - hid_unregister_driver(&mosart_driver); -} - -module_init(mosart_init); -module_exit(mosart_exit); - diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 51b5d272458..bf46804670c 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -50,6 +50,7 @@ MODULE_LICENSE("GPL"); #define MT_QUIRK_VALID_IS_INRANGE (1 << 4) #define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 5) #define MT_QUIRK_EGALAX_XYZ_FIXUP (1 << 6) +#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 7) struct mt_slot { __s32 x, y, p, w, h; @@ -90,6 +91,7 @@ struct mt_class { #define MT_CLS_STANTUM 6 #define MT_CLS_3M 7 #define MT_CLS_CONFIDENCE 8 +#define MT_CLS_CONFIDENCE_MINUS_ONE 9 #define MT_DEFAULT_MAXCONTACT 10 @@ -140,7 +142,9 @@ struct mt_class mt_classes[] = { .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | MT_QUIRK_CYPRESS, .maxcontacts = 10 }, - + { .name = MT_CLS_CONFIDENCE_MINUS_ONE, + .quirks = MT_QUIRK_VALID_IS_CONFIDENCE | + MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE }, { .name = MT_CLS_EGALAX, .quirks = MT_QUIRK_SLOT_IS_CONTACTID | MT_QUIRK_VALID_IS_INRANGE | @@ -325,6 +329,9 @@ static int mt_compute_slot(struct mt_device *td) if (quirks & MT_QUIRK_SLOT_IS_CONTACTNUMBER) return td->num_received; + if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE) + return td->curdata.contactid - 1; + return find_slot_from_contactid(td); } @@ -587,6 +594,17 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, + /* MosArt panels */ + { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, + HID_USB_DEVICE(USB_VENDOR_ID_ASUS, + USB_DEVICE_ID_ASUS_T91MT)}, + { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, + HID_USB_DEVICE(USB_VENDOR_ID_ASUS, + USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, + { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, + HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, + USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) }, + /* PenMount panels */ { .driver_data = MT_CLS_CONFIDENCE, HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, -- cgit v1.2.3-70-g09d2