summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-09-24 14:32:26 +0200
committerHenrik Rydberg <rydberg@euromail.se>2010-09-24 14:32:26 +0200
commit98613761026a3476b2de7081d75ea696aa761c8a (patch)
tree5b4519cc9d3d7295338561d1066f06d7c6f714fe /usr/src
parent073771586ebc397b3a262ae469c92932492678da (diff)
This driver works for the joojoo, but not the other dwav devices.
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/dkms_source_tree/hid-egalax.c200
1 files changed, 119 insertions, 81 deletions
diff --git a/usr/src/dkms_source_tree/hid-egalax.c b/usr/src/dkms_source_tree/hid-egalax.c
index 61e6a80..db4fbc9 100644
--- a/usr/src/dkms_source_tree/hid-egalax.c
+++ b/usr/src/dkms_source_tree/hid-egalax.c
@@ -27,38 +27,62 @@ MODULE_LICENSE("GPL");
27void usbhid_submit_report 27void usbhid_submit_report
28(struct hid_device *hid, struct hid_report *report, unsigned char dir); 28(struct hid_device *hid, struct hid_report *report, unsigned char dir);
29 29
30#define MAX_SLOTS 2
31#define MAX_TRKID USHRT_MAX
32#define MAX_EVENTS 360
33
34/* estimated signal-to-noise ratios */
35#define SN_MOVE 1024
36#define SN_PRESSURE 32
37
38struct egalax_contact {
39 int id;
40 int x, y, z;
41};
42
30struct egalax_data { 43struct egalax_data {
31 __u16 x, y, z; 44 struct egalax_contact contact[MAX_SLOTS];
32 __u8 id; 45 int valid;
33 bool first; /* is this the first finger in the frame? */ 46 int x, y, z;
34 bool valid; /* valid finger data, or just placeholder? */ 47 int slot, prev_slot;
35 bool activity; /* at least one active finger previously? */ 48 int mask;
36 __u16 lastx, lasty; /* latest valid (x, y) in the frame */ 49 int trkid;
50 int reported;
37}; 51};
38 52
39static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi, 53static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
40 struct hid_field *field, struct hid_usage *usage, 54 struct hid_field *field, struct hid_usage *usage,
41 unsigned long **bit, int *max) 55 unsigned long **bit, int *max)
42{ 56{
57 int f1 = field->logical_minimum;
58 int f2 = field->logical_maximum;
59 int df = f2 - f1;
60
43 switch (usage->hid & HID_USAGE_PAGE) { 61 switch (usage->hid & HID_USAGE_PAGE) {
44 62
45 case HID_UP_GENDESK: 63 case HID_UP_GENDESK:
46 switch (usage->hid) { 64 switch (usage->hid) {
47 case HID_GD_X: 65 case HID_GD_X:
66 f1 = 0;
67 f2 = 32768;
68 df = f2 - f1;
48 hid_map_usage(hi, usage, bit, max, 69 hid_map_usage(hi, usage, bit, max,
49 EV_ABS, ABS_MT_POSITION_X); 70 EV_ABS, ABS_MT_POSITION_X);
50 /* touchscreen emulation */ 71 input_set_abs_params(hi->input, ABS_MT_POSITION_X,
72 f1, f2, df / SN_MOVE, 0);
51 input_set_abs_params(hi->input, ABS_X, 73 input_set_abs_params(hi->input, ABS_X,
52 field->logical_minimum, 74 f1, f2, df / SN_MOVE, 0);
53 field->logical_maximum, 0, 0);
54 return 1; 75 return 1;
55 case HID_GD_Y: 76 case HID_GD_Y:
77 f1 = 0;
78 f2 = 32768;
79 df = f2 - f1;
56 hid_map_usage(hi, usage, bit, max, 80 hid_map_usage(hi, usage, bit, max,
57 EV_ABS, ABS_MT_POSITION_Y); 81 EV_ABS, ABS_MT_POSITION_Y);
58 /* touchscreen emulation */ 82 input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
83 f1, f2, df / SN_MOVE, 0);
59 input_set_abs_params(hi->input, ABS_Y, 84 input_set_abs_params(hi->input, ABS_Y,
60 field->logical_minimum, 85 f1, f2, df / SN_MOVE, 0);
61 field->logical_maximum, 0, 0);
62 return 1; 86 return 1;
63 } 87 }
64 return 0; 88 return 0;
@@ -68,6 +92,7 @@ static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
68 case HID_DG_TIPSWITCH: 92 case HID_DG_TIPSWITCH:
69 /* touchscreen emulation */ 93 /* touchscreen emulation */
70 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); 94 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
95 input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
71 return 1; 96 return 1;
72 case HID_DG_INRANGE: 97 case HID_DG_INRANGE:
73 case HID_DG_CONFIDENCE: 98 case HID_DG_CONFIDENCE:
@@ -75,12 +100,22 @@ static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
75 case HID_DG_CONTACTMAX: 100 case HID_DG_CONTACTMAX:
76 return -1; 101 return -1;
77 case HID_DG_CONTACTID: 102 case HID_DG_CONTACTID:
103 field->logical_maximum = MAX_TRKID;
78 hid_map_usage(hi, usage, bit, max, 104 hid_map_usage(hi, usage, bit, max,
79 EV_ABS, ABS_MT_TRACKING_ID); 105 EV_ABS, ABS_MT_TRACKING_ID);
106 input_set_abs_params(hi->input, ABS_MT_TRACKING_ID,
107 0, MAX_TRKID, 0, 0);
108 if (!hi->input->mt)
109 input_mt_create_slots(hi->input, MAX_SLOTS);
110 input_set_events_per_packet(hi->input, MAX_EVENTS);
80 return 1; 111 return 1;
81 case HID_DG_TIPPRESSURE: 112 case HID_DG_TIPPRESSURE:
82 hid_map_usage(hi, usage, bit, max, 113 hid_map_usage(hi, usage, bit, max,
83 EV_ABS, ABS_MT_PRESSURE); 114 EV_ABS, ABS_PRESSURE);
115 input_set_abs_params(hi->input, ABS_MT_PRESSURE,
116 f1, f2, df / SN_PRESSURE, 0);
117 input_set_abs_params(hi->input, ABS_PRESSURE,
118 f1, f2, df / SN_PRESSURE, 0);
84 return 1; 119 return 1;
85 } 120 }
86 return 0; 121 return 0;
@@ -94,67 +129,60 @@ static int egalax_input_mapped(struct hid_device *hdev, struct hid_input *hi,
94 struct hid_field *field, struct hid_usage *usage, 129 struct hid_field *field, struct hid_usage *usage,
95 unsigned long **bit, int *max) 130 unsigned long **bit, int *max)
96{ 131{
132 /* tell hid-input to skip setup of these event types */
97 if (usage->type == EV_KEY || usage->type == EV_ABS) 133 if (usage->type == EV_KEY || usage->type == EV_ABS)
98 clear_bit(usage->code, *bit); 134 set_bit(usage->type, hi->input->evbit);
99 135 return -1;
100 return 0;
101} 136}
102 137
103/* 138static void report_frame(struct egalax_data *td, struct input_dev *input)
104 * this function is called when a whole finger has been parsed,
105 * so that it can decide what to send to the input layer.
106 */
107static void egalax_filter_event(struct egalax_data *td, struct input_dev *input)
108{ 139{
109 td->first = !td->first; /* touchscreen emulation */ 140 struct egalax_contact *f = &td->contact[td->slot];
110 141 struct egalax_contact *oldest = 0;
111 if (td->valid) { 142 int i;
112 /* emit multitouch events */ 143
113 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id); 144 if (!td->valid)
114 input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x); 145 f->id = -1;
115 input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y); 146 else if (f->id < 0)
116 input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z); 147 f->id = td->trkid++ & MAX_TRKID;
117 148 f->x = td->x;
118 input_mt_sync(input); 149 f->y = td->y;
119 150 f->z = td->z;
120 /* 151
121 * touchscreen emulation: store (x, y) as 152 td->mask = 0;
122 * the last valid values in this frame 153 if (td->prev_slot != td->slot) {
123 */ 154 td->prev_slot = td->slot;
124 td->lastx = td->x; 155 if (td->reported) {
125 td->lasty = td->y; 156 td->reported = 0;
126 } 157 return;
127
128 /*
129 * touchscreen emulation: if this is the second finger and at least
130 * one in this frame is valid, the latest valid in the frame is
131 * the oldest on the panel, the one we want for single touch
132 */
133 if (!td->first && td->activity) {
134 input_event(input, EV_ABS, ABS_X, td->lastx);
135 input_event(input, EV_ABS, ABS_Y, td->lasty);
136 }
137
138 if (!td->valid) {
139 /*
140 * touchscreen emulation: if the first finger is invalid
141 * and there previously was finger activity, this is a release
142 */
143 if (td->first && td->activity) {
144 input_event(input, EV_KEY, BTN_TOUCH, 0);
145 td->activity = false;
146 } 158 }
147 return; 159 }
160 td->reported = 1;
161
162 for (i = 0; i < MAX_SLOTS; i++) {
163 f = &td->contact[i];
164 input_mt_slot(input, i);
165 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id);
166 if (f->id < 0)
167 continue;
168 input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
169 input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
170 input_event(input, EV_ABS, ABS_MT_PRESSURE, f->z);
171 if (!oldest)
172 oldest = f;
148 } 173 }
149 174
150 175 if (oldest) {
151 /* touchscreen emulation: if no previous activity, emit touch event */
152 if (!td->activity) {
153 input_event(input, EV_KEY, BTN_TOUCH, 1); 176 input_event(input, EV_KEY, BTN_TOUCH, 1);
154 td->activity = true; 177 input_event(input, EV_ABS, ABS_X, oldest->x);
178 input_event(input, EV_ABS, ABS_Y, oldest->y);
179 input_event(input, EV_ABS, ABS_PRESSURE, oldest->z);
180 } else {
181 input_event(input, EV_KEY, BTN_TOUCH, 0);
155 } 182 }
156}
157 183
184 input_sync(input);
185}
158 186
159static int egalax_event(struct hid_device *hid, struct hid_field *field, 187static int egalax_event(struct hid_device *hid, struct hid_field *field,
160 struct hid_usage *usage, __s32 value) 188 struct hid_usage *usage, __s32 value)
@@ -171,37 +199,44 @@ static int egalax_event(struct hid_device *hid, struct hid_field *field,
171 if (hid->claimed & HID_CLAIMED_INPUT) { 199 if (hid->claimed & HID_CLAIMED_INPUT) {
172 struct input_dev *input = field->hidinput->input; 200 struct input_dev *input = field->hidinput->input;
173 201
202 //printk(KERN_INFO "CHECK: %08x %d", usage->hid, value);
203 //return 1;
204
174 switch (usage->hid) { 205 switch (usage->hid) {
175 case HID_DG_INRANGE: 206 case HID_DG_INRANGE:
176 case HID_DG_CONFIDENCE: 207 case HID_DG_CONFIDENCE:
177 /* avoid interference from generic hidinput handling */ 208 case HID_DG_CONTACTCOUNT:
178 break; 209 break;
210
179 case HID_DG_TIPSWITCH: 211 case HID_DG_TIPSWITCH:
180 td->valid = value; 212 td->valid = value;
213 td->mask |= 0x01;
181 break; 214 break;
182 case HID_DG_TIPPRESSURE: 215
183 td->z = value;
184 break;
185 case HID_DG_CONTACTID: 216 case HID_DG_CONTACTID:
186 td->id = value; 217 td->slot = clamp_val(value, 0, MAX_SLOTS - 1);
218 td->mask |= 0x02;
187 break; 219 break;
188 case HID_GD_X: 220 case HID_GD_X:
189 td->x = value; 221 td->x = 32768 - value;
222 td->mask |= 0x04;
190 break; 223 break;
191 case HID_GD_Y: 224 case HID_GD_Y:
192 td->y = value; 225 td->y = 32768 - value;
193 /* this is the last field in a finger */ 226 td->mask |= 0x08;
194 egalax_filter_event(td, input);
195 break; 227 break;
196 case HID_DG_CONTACTCOUNT: 228 case HID_DG_TIPPRESSURE:
197 /* touch emulation: this is the last field in a frame */ 229 td->z = value;
198 td->first = false; 230 td->mask |= 0x10;
199 break; 231 break;
200 232
201 default: 233 default:
202 /* fallback to the generic hidinput handling */ 234 /* fallback to the generic hidinput handling */
203 return 0; 235 return 0;
204 } 236 }
237
238 if (td->mask == 0x1f)
239 report_frame(td, input);
205 } 240 }
206 241
207 /* we have handled the hidinput part, now remains hiddev */ 242 /* we have handled the hidinput part, now remains hiddev */
@@ -216,12 +251,17 @@ static int egalax_probe(struct hid_device *hdev, const struct hid_device_id *id)
216 int ret; 251 int ret;
217 struct egalax_data *td; 252 struct egalax_data *td;
218 struct hid_report *report; 253 struct hid_report *report;
254 int i;
219 255
220 td = kmalloc(sizeof(struct egalax_data), GFP_KERNEL); 256 hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
257
258 td = kzalloc(sizeof(struct egalax_data), GFP_KERNEL);
221 if (!td) { 259 if (!td) {
222 dev_err(&hdev->dev, "cannot allocate eGalax data\n"); 260 dev_err(&hdev->dev, "cannot allocate eGalax data\n");
223 return -ENOMEM; 261 return -ENOMEM;
224 } 262 }
263 for (i = 0; i < MAX_SLOTS; i++)
264 td->contact[i].id = -1;
225 hid_set_drvdata(hdev, td); 265 hid_set_drvdata(hdev, td);
226 266
227 ret = hid_parse(hdev); 267 ret = hid_parse(hdev);
@@ -232,7 +272,7 @@ static int egalax_probe(struct hid_device *hdev, const struct hid_device_id *id)
232 if (ret) 272 if (ret)
233 goto end; 273 goto end;
234 274
235 report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[5]; 275 report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[5];
236 if (report) { 276 if (report) {
237 report->field[0]->value[0] = 2; 277 report->field[0]->value[0] = 2;
238 usbhid_submit_report(hdev, report, USB_DIR_OUT); 278 usbhid_submit_report(hdev, report, USB_DIR_OUT);
@@ -254,8 +294,6 @@ static void egalax_remove(struct hid_device *hdev)
254 294
255static const struct hid_device_id egalax_devices[] = { 295static const struct hid_device_id egalax_devices[] = {
256 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, 296 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
257 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
258 { HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
259 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, 297 USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
260 { } 298 { }
261}; 299};
@@ -267,7 +305,7 @@ static const struct hid_usage_id egalax_grabbed_usages[] = {
267}; 305};
268 306
269static struct hid_driver egalax_driver = { 307static struct hid_driver egalax_driver = {
270 .name = "egalax-touch", 308 .name = "egalax-joojoo",
271 .id_table = egalax_devices, 309 .id_table = egalax_devices,
272 .probe = egalax_probe, 310 .probe = egalax_probe,
273 .remove = egalax_remove, 311 .remove = egalax_remove,