diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 12:03:13 +0200 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 12:03:13 +0200 |
| commit | 31dced41c6822ce751c033a53502ea4d8d399422 (patch) | |
| tree | 53f6abc56c517a6dcb790bf9b3a71ac42694233a /drivers/hid/hid-multitouch.c | |
| parent | 7c1953ddb609f1c161bf4a11a5e4e4577e82e557 (diff) | |
| parent | b3aec7b686329e6bb65aa08c7f9458f7fd512f06 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (61 commits)
HID: hid-magicmouse: Magic Trackpad has 1 button, not 2
HID: Add device IDs for more SJOY adapters
HID: primax: remove spurious dependency
HID: support primax keyboards violating USB HID spec
HID: usbhid: cancel timer for retry synchronously
HID: wacom: Set input bits before registration
HID: consolidate MacbookAir 4,1 mappings
HID: MacbookAir4,1 and MacbookAir4,2 need entry in hid_mouse_ignore_list[]
HID: Add support MacbookAir 4,1 keyboard
HID: hidraw: open count should not increase if error
HID: hiddev: potential info leak in hiddev_ioctl()
HID: multitouch: decide if hid-multitouch needs to handle mt devices
HID: add autodetection of multitouch devices
HID: "hid-logitech" driver with Logitech Driving Force GT
HID: hid-logitech-dj: fix off by one
HID: hidraw: protect hidraw_disconnect() better
HID: hid-multitouch: add support for the IDEACOM 6650 chip
HID: Add full support for Logitech Unifying receivers
HID: hidraw: free list for all error in hidraw_open
HID: roccat: Kone now reports external profile changes via roccat device
...
Diffstat (limited to 'drivers/hid/hid-multitouch.c')
| -rw-r--r-- | drivers/hid/hid-multitouch.c | 93 |
1 files changed, 79 insertions, 14 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 58d0e7aaf08..fa5d7a1ffa9 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -47,10 +47,11 @@ MODULE_LICENSE("GPL"); #define MT_QUIRK_SLOT_IS_CONTACTID (1 << 1) #define MT_QUIRK_CYPRESS (1 << 2) #define MT_QUIRK_SLOT_IS_CONTACTNUMBER (1 << 3) -#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) +#define MT_QUIRK_ALWAYS_VALID (1 << 4) +#define MT_QUIRK_VALID_IS_INRANGE (1 << 5) +#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6) +#define MT_QUIRK_EGALAX_XYZ_FIXUP (1 << 7) +#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8) struct mt_slot { __s32 x, y, p, w, h; @@ -86,11 +87,12 @@ struct mt_class { /* classes of device behavior */ #define MT_CLS_DEFAULT 0x0001 -#define MT_CLS_CONFIDENCE 0x0002 -#define MT_CLS_CONFIDENCE_MINUS_ONE 0x0003 -#define MT_CLS_DUAL_INRANGE_CONTACTID 0x0004 -#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0005 -#define MT_CLS_DUAL_NSMU_CONTACTID 0x0006 +#define MT_CLS_SERIAL 0x0002 +#define MT_CLS_CONFIDENCE 0x0003 +#define MT_CLS_CONFIDENCE_MINUS_ONE 0x0004 +#define MT_CLS_DUAL_INRANGE_CONTACTID 0x0005 +#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER 0x0006 +#define MT_CLS_DUAL_NSMU_CONTACTID 0x0007 /* vendor specific classes */ #define MT_CLS_3M 0x0101 @@ -134,6 +136,8 @@ static int find_slot_from_contactid(struct mt_device *td) struct mt_class mt_classes[] = { { .name = MT_CLS_DEFAULT, .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP }, + { .name = MT_CLS_SERIAL, + .quirks = MT_QUIRK_ALWAYS_VALID}, { .name = MT_CLS_CONFIDENCE, .quirks = MT_QUIRK_VALID_IS_CONFIDENCE }, { .name = MT_CLS_CONFIDENCE_MINUS_ONE, @@ -213,6 +217,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct mt_class *cls = td->mtclass; __s32 quirks = cls->quirks; + /* Only map fields from TouchScreen or TouchPad collections. + * We need to ignore fields that belong to other collections + * such as Mouse that might have the same GenericDesktop usages. */ + if (field->application == HID_DG_TOUCHSCREEN) + set_bit(INPUT_PROP_DIRECT, hi->input->propbit); + else if (field->application == HID_DG_TOUCHPAD) + set_bit(INPUT_PROP_POINTER, hi->input->propbit); + else + return 0; + switch (usage->hid & HID_USAGE_PAGE) { case HID_UP_GENDESK: @@ -277,6 +291,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, td->last_slot_field = usage->hid; td->last_field_index = field->index; td->last_mt_collection = usage->collection_index; + hdev->quirks &= ~HID_QUIRK_MULTITOUCH; return 1; case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, @@ -435,7 +450,9 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, if (hid->claimed & HID_CLAIMED_INPUT && td->slots) { switch (usage->hid) { case HID_DG_INRANGE: - if (quirks & MT_QUIRK_VALID_IS_INRANGE) + if (quirks & MT_QUIRK_ALWAYS_VALID) + td->curvalid = true; + else if (quirks & MT_QUIRK_VALID_IS_INRANGE) td->curvalid = value; break; case HID_DG_TIPSWITCH: @@ -513,12 +530,44 @@ static void mt_set_input_mode(struct hid_device *hdev) } } +/* a list of devices for which there is a specialized multitouch driver */ +static const struct hid_device_id mt_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, 0x0001) }, + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, 0x0006) }, + { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, + USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) }, + { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, + USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) }, + { } +}; + +static bool mt_match_one_id(struct hid_device *hdev, + const struct hid_device_id *id) +{ + return id->bus == hdev->bus && + (id->vendor == HID_ANY_ID || id->vendor == hdev->vendor) && + (id->product == HID_ANY_ID || id->product == hdev->product); +} + +static const struct hid_device_id *mt_match_id(struct hid_device *hdev, + const struct hid_device_id *id) +{ + for (; id->bus; id++) + if (mt_match_one_id(hdev, id)) + return id; + + return NULL; +} + static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) { int ret, i; struct mt_device *td; struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */ + if (mt_match_id(hdev, mt_have_special_driver)) + return -ENODEV; + for (i = 0; mt_classes[i].name ; i++) { if (id->driver_data == mt_classes[i].name) { mtclass = &(mt_classes[i]); @@ -526,10 +575,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) } } - /* This allows the driver to correctly support devices - * that emit events over several HID messages. - */ - hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; td = kzalloc(sizeof(struct mt_device), GFP_KERNEL); if (!td) { @@ -545,10 +590,16 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) if (ret != 0) goto fail; + hdev->quirks |= HID_QUIRK_MULTITOUCH; ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) goto fail; + /* This allows the driver to correctly support devices + * that emit events over several HID messages. + */ + hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; + td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), GFP_KERNEL); if (!td->slots) { @@ -662,6 +713,11 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH, USB_DEVICE_ID_GOODTOUCH_000f) }, + /* Ideacom panel */ + { .driver_data = MT_CLS_SERIAL, + HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, + USB_DEVICE_ID_IDEACOM_IDC6650) }, + /* Ilitek dual touch panel */ { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, @@ -672,6 +728,11 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, + /* LG Display panels */ + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_LG, + USB_DEVICE_ID_LG_MULTITOUCH) }, + /* Lumio panels */ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, @@ -732,6 +793,10 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) }, + /* Rest of the world */ + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) }, + { } }; MODULE_DEVICE_TABLE(hid, mt_devices); |
