1 /*
2  *  HID driver for Cando dual-touch panels
3  *
4  *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
5  *
6  */
7 
8 /*
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by the Free
11  * Software Foundation; either version 2 of the License, or (at your option)
12  * any later version.
13  */
14 
15 #include <linux/device.h>
16 #include <linux/hid.h>
17 #include <linux/module.h>
18 #include <linux/slab.h>
19 
20 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
21 MODULE_DESCRIPTION("Cando dual-touch panel");
22 MODULE_LICENSE("GPL");
23 
24 #include "hid-ids.h"
25 
26 struct cando_data {
27 	__u16 x, y;
28 	__u8 id;
29 	__s8 oldest;		/* id of the oldest finger in previous frame */
30 	bool valid;		/* valid finger data, or just placeholder? */
31 	bool first;		/* is this the first finger in this frame? */
32 	__s8 firstid;		/* id of the first finger in the frame */
33 	__u16 firstx, firsty;	/* (x, y) of the first finger in the frame */
34 };
35 
cando_input_mapping(struct hid_device * hdev,struct hid_input * hi,struct hid_field * field,struct hid_usage * usage,unsigned long ** bit,int * max)36 static int cando_input_mapping(struct hid_device *hdev, struct hid_input *hi,
37 		struct hid_field *field, struct hid_usage *usage,
38 		unsigned long **bit, int *max)
39 {
40 	switch (usage->hid & HID_USAGE_PAGE) {
41 
42 	case HID_UP_GENDESK:
43 		switch (usage->hid) {
44 		case HID_GD_X:
45 			hid_map_usage(hi, usage, bit, max,
46 					EV_ABS, ABS_MT_POSITION_X);
47 			/* touchscreen emulation */
48 			input_set_abs_params(hi->input, ABS_X,
49 						field->logical_minimum,
50 						field->logical_maximum, 0, 0);
51 			return 1;
52 		case HID_GD_Y:
53 			hid_map_usage(hi, usage, bit, max,
54 					EV_ABS, ABS_MT_POSITION_Y);
55 			/* touchscreen emulation */
56 			input_set_abs_params(hi->input, ABS_Y,
57 						field->logical_minimum,
58 						field->logical_maximum, 0, 0);
59 			return 1;
60 		}
61 		return 0;
62 
63 	case HID_UP_DIGITIZER:
64 		switch (usage->hid) {
65 		case HID_DG_TIPSWITCH:
66 		case HID_DG_CONTACTMAX:
67 			return -1;
68 		case HID_DG_INRANGE:
69 			/* touchscreen emulation */
70 			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
71 			return 1;
72 		case HID_DG_CONTACTID:
73 			hid_map_usage(hi, usage, bit, max,
74 					EV_ABS, ABS_MT_TRACKING_ID);
75 			return 1;
76 		}
77 		return 0;
78 	}
79 
80 	return 0;
81 }
82 
cando_input_mapped(struct hid_device * hdev,struct hid_input * hi,struct hid_field * field,struct hid_usage * usage,unsigned long ** bit,int * max)83 static int cando_input_mapped(struct hid_device *hdev, struct hid_input *hi,
84 		struct hid_field *field, struct hid_usage *usage,
85 		unsigned long **bit, int *max)
86 {
87 	if (usage->type == EV_KEY || usage->type == EV_ABS)
88 		clear_bit(usage->code, *bit);
89 
90 	return 0;
91 }
92 
93 /*
94  * this function is called when a whole finger has been parsed,
95  * so that it can decide what to send to the input layer.
96  */
cando_filter_event(struct cando_data * td,struct input_dev * input)97 static void cando_filter_event(struct cando_data *td, struct input_dev *input)
98 {
99 	td->first = !td->first; /* touchscreen emulation */
100 
101 	if (!td->valid) {
102 		/*
103 		 * touchscreen emulation: if this is the second finger and
104 		 * the first was valid, the first was the oldest; if the
105 		 * first was not valid and there was a valid finger in the
106 		 * previous frame, this is a release.
107 		 */
108 		if (td->first) {
109 			td->firstid = -1;
110 		} else if (td->firstid >= 0) {
111 			input_event(input, EV_ABS, ABS_X, td->firstx);
112 			input_event(input, EV_ABS, ABS_Y, td->firsty);
113 			td->oldest = td->firstid;
114 		} else if (td->oldest >= 0) {
115 			input_event(input, EV_KEY, BTN_TOUCH, 0);
116 			td->oldest = -1;
117 		}
118 
119 		return;
120 	}
121 
122 	input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
123 	input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
124 	input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
125 
126 	input_mt_sync(input);
127 
128 	/*
129 	 * touchscreen emulation: if there was no touching finger previously,
130 	 * emit touch event
131 	 */
132 	if (td->oldest < 0) {
133 		input_event(input, EV_KEY, BTN_TOUCH, 1);
134 		td->oldest = td->id;
135 	}
136 
137 	/*
138 	 * touchscreen emulation: if this is the first finger, wait for the
139 	 * second; the oldest is then the second if it was the oldest already
140 	 * or if there was no first, the first otherwise.
141 	 */
142 	if (td->first) {
143 		td->firstx = td->x;
144 		td->firsty = td->y;
145 		td->firstid = td->id;
146 	} else {
147 		int x, y, oldest;
148 		if (td->id == td->oldest || td->firstid < 0) {
149 			x = td->x;
150 			y = td->y;
151 			oldest = td->id;
152 		} else {
153 			x = td->firstx;
154 			y = td->firsty;
155 			oldest = td->firstid;
156 		}
157 		input_event(input, EV_ABS, ABS_X, x);
158 		input_event(input, EV_ABS, ABS_Y, y);
159 		td->oldest = oldest;
160 	}
161 }
162 
163 
cando_event(struct hid_device * hid,struct hid_field * field,struct hid_usage * usage,__s32 value)164 static int cando_event(struct hid_device *hid, struct hid_field *field,
165 				struct hid_usage *usage, __s32 value)
166 {
167 	struct cando_data *td = hid_get_drvdata(hid);
168 
169 	if (hid->claimed & HID_CLAIMED_INPUT) {
170 		struct input_dev *input = field->hidinput->input;
171 
172 		switch (usage->hid) {
173 		case HID_DG_INRANGE:
174 			td->valid = value;
175 			break;
176 		case HID_DG_CONTACTID:
177 			td->id = value;
178 			break;
179 		case HID_GD_X:
180 			td->x = value;
181 			break;
182 		case HID_GD_Y:
183 			td->y = value;
184 			cando_filter_event(td, input);
185 			break;
186 		case HID_DG_TIPSWITCH:
187 			/* avoid interference from generic hidinput handling */
188 			break;
189 
190 		default:
191 			/* fallback to the generic hidinput handling */
192 			return 0;
193 		}
194 	}
195 
196 	/* we have handled the hidinput part, now remains hiddev */
197 	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
198 		hid->hiddev_hid_event(hid, field, usage, value);
199 
200 	return 1;
201 }
202 
cando_probe(struct hid_device * hdev,const struct hid_device_id * id)203 static int cando_probe(struct hid_device *hdev, const struct hid_device_id *id)
204 {
205 	int ret;
206 	struct cando_data *td;
207 
208 	td = kmalloc(sizeof(struct cando_data), GFP_KERNEL);
209 	if (!td) {
210 		hid_err(hdev, "cannot allocate Cando Touch data\n");
211 		return -ENOMEM;
212 	}
213 	hid_set_drvdata(hdev, td);
214 	td->first = false;
215 	td->oldest = -1;
216 	td->valid = false;
217 
218 	ret = hid_parse(hdev);
219 	if (!ret)
220 		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
221 
222 	if (ret)
223 		kfree(td);
224 
225 	return ret;
226 }
227 
cando_remove(struct hid_device * hdev)228 static void cando_remove(struct hid_device *hdev)
229 {
230 	hid_hw_stop(hdev);
231 	kfree(hid_get_drvdata(hdev));
232 	hid_set_drvdata(hdev, NULL);
233 }
234 
235 static const struct hid_device_id cando_devices[] = {
236 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
237 			USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
238 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
239 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
240 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
241 			USB_DEVICE_ID_CANDO_MULTI_TOUCH_11_6) },
242 	{ HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
243 		USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
244 	{ }
245 };
246 MODULE_DEVICE_TABLE(hid, cando_devices);
247 
248 static const struct hid_usage_id cando_grabbed_usages[] = {
249 	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
250 	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
251 };
252 
253 static struct hid_driver cando_driver = {
254 	.name = "cando-touch",
255 	.id_table = cando_devices,
256 	.probe = cando_probe,
257 	.remove = cando_remove,
258 	.input_mapping = cando_input_mapping,
259 	.input_mapped = cando_input_mapped,
260 	.usage_table = cando_grabbed_usages,
261 	.event = cando_event,
262 };
263 
cando_init(void)264 static int __init cando_init(void)
265 {
266 	return hid_register_driver(&cando_driver);
267 }
268 
cando_exit(void)269 static void __exit cando_exit(void)
270 {
271 	hid_unregister_driver(&cando_driver);
272 }
273 
274 module_init(cando_init);
275 module_exit(cando_exit);
276 
277