]> git.openfabrics.org - ~shefty/rdma-dev.git/blob - drivers/hid/hid-egalax.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[~shefty/rdma-dev.git] / drivers / hid / hid-egalax.c
1 /*
2  *  HID driver for eGalax dual-touch panels
3  *
4  *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
5  *  Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
6  *  Copyright (c) 2010 Canonical, Ltd.
7  *
8  */
9
10 /*
11  * This program is free software; you can redistribute it and/or modify it
12  * under the terms of the GNU General Public License as published by the Free
13  * Software Foundation; either version 2 of the License, or (at your option)
14  * any later version.
15  */
16
17 #include <linux/device.h>
18 #include <linux/hid.h>
19 #include <linux/module.h>
20 #include <linux/usb.h>
21 #include <linux/input/mt.h>
22 #include <linux/slab.h>
23 #include "usbhid/usbhid.h"
24
25 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
26 MODULE_DESCRIPTION("eGalax dual-touch panel");
27 MODULE_LICENSE("GPL");
28
29 #include "hid-ids.h"
30
31 #define MAX_SLOTS               2
32
33 /* estimated signal-to-noise ratios */
34 #define SN_MOVE                 4096
35 #define SN_PRESSURE             32
36
37 struct egalax_data {
38         int valid;
39         int slot;
40         int touch;
41         int x, y, z;
42 };
43
44 static void set_abs(struct input_dev *input, unsigned int code,
45                     struct hid_field *field, int snratio)
46 {
47         int fmin = field->logical_minimum;
48         int fmax = field->logical_maximum;
49         int fuzz = snratio ? (fmax - fmin) / snratio : 0;
50         input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
51 }
52
53 static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
54                 struct hid_field *field, struct hid_usage *usage,
55                 unsigned long **bit, int *max)
56 {
57         struct input_dev *input = hi->input;
58
59         switch (usage->hid & HID_USAGE_PAGE) {
60
61         case HID_UP_GENDESK:
62                 switch (usage->hid) {
63                 case HID_GD_X:
64                         field->logical_maximum = 32760;
65                         hid_map_usage(hi, usage, bit, max,
66                                         EV_ABS, ABS_MT_POSITION_X);
67                         set_abs(input, ABS_MT_POSITION_X, field, SN_MOVE);
68                         /* touchscreen emulation */
69                         set_abs(input, ABS_X, field, SN_MOVE);
70                         return 1;
71                 case HID_GD_Y:
72                         field->logical_maximum = 32760;
73                         hid_map_usage(hi, usage, bit, max,
74                                         EV_ABS, ABS_MT_POSITION_Y);
75                         set_abs(input, ABS_MT_POSITION_Y, field, SN_MOVE);
76                         /* touchscreen emulation */
77                         set_abs(input, ABS_Y, field, SN_MOVE);
78                         return 1;
79                 }
80                 return 0;
81
82         case HID_UP_DIGITIZER:
83                 switch (usage->hid) {
84                 case HID_DG_TIPSWITCH:
85                         /* touchscreen emulation */
86                         hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
87                         input_set_capability(input, EV_KEY, BTN_TOUCH);
88                         return 1;
89                 case HID_DG_INRANGE:
90                 case HID_DG_CONFIDENCE:
91                 case HID_DG_CONTACTCOUNT:
92                 case HID_DG_CONTACTMAX:
93                         return -1;
94                 case HID_DG_CONTACTID:
95                         input_mt_init_slots(input, MAX_SLOTS);
96                         return 1;
97                 case HID_DG_TIPPRESSURE:
98                         field->logical_minimum = 0;
99                         hid_map_usage(hi, usage, bit, max,
100                                         EV_ABS, ABS_MT_PRESSURE);
101                         set_abs(input, ABS_MT_PRESSURE, field, SN_PRESSURE);
102                         /* touchscreen emulation */
103                         set_abs(input, ABS_PRESSURE, field, SN_PRESSURE);
104                         return 1;
105                 }
106                 return 0;
107         }
108
109         /* ignore others (from other reports we won't get anyway) */
110         return -1;
111 }
112
113 static int egalax_input_mapped(struct hid_device *hdev, struct hid_input *hi,
114                 struct hid_field *field, struct hid_usage *usage,
115                 unsigned long **bit, int *max)
116 {
117         /* tell hid-input to skip setup of these event types */
118         if (usage->type == EV_KEY || usage->type == EV_ABS)
119                 set_bit(usage->type, hi->input->evbit);
120         return -1;
121 }
122
123 /*
124  * this function is called when a whole finger has been parsed,
125  * so that it can decide what to send to the input layer.
126  */
127 static void egalax_filter_event(struct egalax_data *td, struct input_dev *input)
128 {
129         input_mt_slot(input, td->slot);
130         input_mt_report_slot_state(input, MT_TOOL_FINGER, td->touch);
131         if (td->touch) {
132                 input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
133                 input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
134                 input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z);
135         }
136         input_mt_report_pointer_emulation(input, true);
137 }
138
139 static int egalax_event(struct hid_device *hid, struct hid_field *field,
140                                 struct hid_usage *usage, __s32 value)
141 {
142         struct egalax_data *td = hid_get_drvdata(hid);
143
144         /* Note, eGalax has two product lines: the first is resistive and
145          * uses a standard parallel multitouch protocol (product ID ==
146          * 48xx).  The second is capacitive and uses an unusual "serial"
147          * protocol with a different message for each multitouch finger
148          * (product ID == 72xx).
149          */
150         if (hid->claimed & HID_CLAIMED_INPUT) {
151                 struct input_dev *input = field->hidinput->input;
152
153                 switch (usage->hid) {
154                 case HID_DG_INRANGE:
155                         td->valid = value;
156                         break;
157                 case HID_DG_CONFIDENCE:
158                         /* avoid interference from generic hidinput handling */
159                         break;
160                 case HID_DG_TIPSWITCH:
161                         td->touch = value;
162                         break;
163                 case HID_DG_TIPPRESSURE:
164                         td->z = value;
165                         break;
166                 case HID_DG_CONTACTID:
167                         td->slot = clamp_val(value, 0, MAX_SLOTS - 1);
168                         break;
169                 case HID_GD_X:
170                         td->x = value;
171                         break;
172                 case HID_GD_Y:
173                         td->y = value;
174                         /* this is the last field in a finger */
175                         if (td->valid)
176                                 egalax_filter_event(td, input);
177                         break;
178                 case HID_DG_CONTACTCOUNT:
179                         /* touch emulation: this is the last field in a frame */
180                         break;
181
182                 default:
183                         /* fallback to the generic hidinput handling */
184                         return 0;
185                 }
186         }
187
188         /* we have handled the hidinput part, now remains hiddev */
189         if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
190                 hid->hiddev_hid_event(hid, field, usage, value);
191
192         return 1;
193 }
194
195 static int egalax_probe(struct hid_device *hdev, const struct hid_device_id *id)
196 {
197         int ret;
198         struct egalax_data *td;
199         struct hid_report *report;
200
201         td = kzalloc(sizeof(struct egalax_data), GFP_KERNEL);
202         if (!td) {
203                 dev_err(&hdev->dev, "cannot allocate eGalax data\n");
204                 return -ENOMEM;
205         }
206         hid_set_drvdata(hdev, td);
207
208         ret = hid_parse(hdev);
209         if (ret)
210                 goto end;
211
212         ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
213         if (ret)
214                 goto end;
215
216         report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[5]; 
217         if (report) {
218                 report->field[0]->value[0] = 2;
219                 usbhid_submit_report(hdev, report, USB_DIR_OUT);
220         }
221
222 end:
223         if (ret)
224                 kfree(td);
225
226         return ret;
227 }
228
229 static void egalax_remove(struct hid_device *hdev)
230 {
231         hid_hw_stop(hdev);
232         kfree(hid_get_drvdata(hdev));
233         hid_set_drvdata(hdev, NULL);
234 }
235
236 static const struct hid_device_id egalax_devices[] = {
237         { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
238                         USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
239         { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
240                         USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
241         { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
242                         USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
243         { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
244                         USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
245         { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
246                         USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
247         { }
248 };
249 MODULE_DEVICE_TABLE(hid, egalax_devices);
250
251 static const struct hid_usage_id egalax_grabbed_usages[] = {
252         { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
253         { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
254 };
255
256 static struct hid_driver egalax_driver = {
257         .name = "egalax-touch",
258         .id_table = egalax_devices,
259         .probe = egalax_probe,
260         .remove = egalax_remove,
261         .input_mapping = egalax_input_mapping,
262         .input_mapped = egalax_input_mapped,
263         .usage_table = egalax_grabbed_usages,
264         .event = egalax_event,
265 };
266
267 static int __init egalax_init(void)
268 {
269         return hid_register_driver(&egalax_driver);
270 }
271
272 static void __exit egalax_exit(void)
273 {
274         hid_unregister_driver(&egalax_driver);
275 }
276
277 module_init(egalax_init);
278 module_exit(egalax_exit);
279