OSDN Git Service

Add updated driver from Stephane Lajeunesse
authorFunky Android Ltd <al@funkyandroid.com>
Wed, 17 Nov 2010 06:59:16 +0000 (06:59 +0000)
committerFunky Android Ltd <al@funkyandroid.com>
Wed, 17 Nov 2010 07:00:14 +0000 (07:00 +0000)
drivers/hid/hid-hanvon.c

index 87da0ca..e9bedd7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  HID driver for the Pixcir multitouch controller
+ *  HID driver for the multitouch panel on the Hanvon tablet
  *
  *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
  *
 #include "usbhid/usbhid.h"
 
 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("Pixcir dual-touch controller");
+MODULE_DESCRIPTION("Hanvon dual-touch panel");
 MODULE_LICENSE("GPL");
 
 #include "hid-ids.h"
 
-struct pixcir_data {
+struct hanvon_data {
        __u16 x, y;
        __u8 id;
-       bool valid;             /* valid finger data, or just placeholder? */
-       bool first;             /* is this the first finger in this frame? */
 };
 
-static int pixcir_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+static int hanvon_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
 {
@@ -62,23 +60,36 @@ static int pixcir_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        case HID_UP_DIGITIZER:
                switch (usage->hid) {
                case HID_DG_TIPSWITCH:
-                       hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
+                       hid_map_usage(hi, usage, bit, max, EV_ABS,
+                                               ABS_MT_TOUCH_MAJOR);
                        return 1;
 
-               /* these ones are not reliable */
                case HID_DG_INRANGE:
+                       hid_map_usage(hi, usage, bit, max, EV_ABS,
+                                               ABS_MT_TOUCH_MINOR);
+                       return 1;
+
                case HID_DG_CONFIDENCE:
-               case HID_DG_CONTACTCOUNT:
-                       return -1;
+                       hid_map_usage(hi, usage, bit, max, EV_ABS,
+                                               ABS_MT_WIDTH_MAJOR);
+                       return 1;
 
                case HID_DG_CONTACTID:
                        hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_TRACKING_ID);
                        return 1;
 
-               /* ignore this feature for now */
+                case HID_DG_CONTACTCOUNT:
+                        hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR);
+                        input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0);
+                        hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MINOR);
+                        input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0);
+                        return 1;
+
                case HID_DG_CONTACTMAX:
-                       return -1;
+                       hid_map_usage(hi, usage, bit, max, EV_ABS,
+                                               ABS_MT_ORIENTATION);
+                       return 1;
                }
                return 0;
        }
@@ -86,7 +97,7 @@ static int pixcir_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        return 0;
 }
 
-static int pixcir_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+static int hanvon_input_mapped(struct hid_device *hdev, struct hid_input *hi,
                struct hid_field *field, struct hid_usage *usage,
                unsigned long **bit, int *max)
 {
@@ -96,69 +107,40 @@ static int pixcir_input_mapped(struct hid_device *hdev, struct hid_input *hi,
        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 pixcir_filter_event(struct pixcir_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
-                * this is a release
-                */
-               if (td->first)
-                       input_event(input, EV_KEY, BTN_TOUCH, 0);
-               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 finger in this frame... */
-       if (td->first) {
-               /* this is our preferred finger */
-               input_event(input, EV_KEY, BTN_TOUCH, 1);
-               input_event(input, EV_ABS, ABS_X, td->x);
-               input_event(input, EV_ABS, ABS_Y, td->y);
-       }
-}
-
-static int pixcir_event(struct hid_device *hid, struct hid_field *field,
+static int hanvon_event(struct hid_device *hid, struct hid_field *field,
                                struct hid_usage *usage, __s32 value)
 {
-       struct pixcir_data *td = hid_get_drvdata(hid);
+//     struct hanvon_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_TIPSWITCH:
-                       td->valid = value;
+                       input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, value);
                        break;
                case HID_DG_INRANGE:
-               case HID_DG_CONFIDENCE:
-               case HID_DG_CONTACTCOUNT:
-                       /* avoid interference from generic hidinput handling */
+                       input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, value);
                        break;
-               case HID_DG_CONTACTID:
-                       td->id = value;
+               case HID_DG_CONFIDENCE:
+                       input_event(input, EV_ABS, ABS_MT_WIDTH_MAJOR, value);
                        break;
                case HID_GD_X:
-                       td->x = value;
+                       input_event(input, EV_ABS, ABS_MT_POSITION_X, value);
                        break;
                case HID_GD_Y:
-                       td->y = value;
-                       pixcir_filter_event(td, input);
+                       input_event(input, EV_ABS, ABS_MT_POSITION_Y, value);
+                       input_mt_sync(input);
+                       break;
+               case HID_DG_CONTACTID:
+                       input_event(input, EV_ABS, ABS_MT_TRACKING_ID, value);
+                       break;
+               case HID_DG_CONTACTCOUNT:
+                       input_event(input, EV_ABS, ABS_MT_WIDTH_MINOR, value);
                        break;
                case HID_DG_CONTACTMAX:
                        break;
+                       input_event(input, EV_ABS, ABS_MT_ORIENTATION, value);
 
                default:
                        /* fallback to the generic hidinput handling */
@@ -173,15 +155,15 @@ static int pixcir_event(struct hid_device *hid, struct hid_field *field,
        return 1;
 }
 
-static int pixcir_probe(struct hid_device *hdev, const struct hid_device_id *id)
+static int hanvon_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
        int ret;
-       struct pixcir_data *td;
+       struct hanvon_data *td;
 
 
-       td = kzalloc(sizeof(struct pixcir_data), GFP_KERNEL);
+       td = kmalloc(sizeof(struct hanvon_data), GFP_KERNEL);
        if (!td) {
-               dev_err(&hdev->dev, "cannot allocate Pixcir data\n");
+               dev_err(&hdev->dev, "cannot allocate Hanvon data\n");
                return -ENOMEM;
        }
        hid_set_drvdata(hdev, td);
@@ -196,44 +178,45 @@ static int pixcir_probe(struct hid_device *hdev, const struct hid_device_id *id)
        return ret;
 }
 
-static void pixcir_remove(struct hid_device *hdev)
+static void hanvon_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 pixcir_devices[] = {
+static const struct hid_device_id hanvon_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
        { }
 };
-MODULE_DEVICE_TABLE(hid, pixcir_devices);
+MODULE_DEVICE_TABLE(hid, hanvon_devices);
 
-static const struct hid_usage_id pixcir_grabbed_usages[] = {
+static const struct hid_usage_id hanvon_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 pixcir_driver = {
-       .name = "pixcir",
-       .id_table = pixcir_devices,
-       .probe = pixcir_probe,
-       .remove = pixcir_remove,
-       .input_mapping = pixcir_input_mapping,
-       .input_mapped = pixcir_input_mapped,
-       .usage_table = pixcir_grabbed_usages,
-       .event = pixcir_event,
+static struct hid_driver hanvon_driver = {
+       .name = "hanvon",
+       .id_table = hanvon_devices,
+       .probe = hanvon_probe,
+       .remove = hanvon_remove,
+       .input_mapping = hanvon_input_mapping,
+       .input_mapped = hanvon_input_mapped,
+       .usage_table = hanvon_grabbed_usages,
+       .event = hanvon_event,
 };
 
-static int __init pixcir_init(void)
+static int __init hanvon_init(void)
 {
-       return hid_register_driver(&pixcir_driver);
+       return hid_register_driver(&hanvon_driver);
 }
 
-static void __exit pixcir_exit(void)
+static void __exit hanvon_exit(void)
 {
-       hid_unregister_driver(&pixcir_driver);
+       hid_unregister_driver(&hanvon_driver);
 }
 
-module_init(pixcir_init);
-module_exit(pixcir_exit);
+module_init(hanvon_init);
+module_exit(hanvon_exit);
+