summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-08-28 17:43:22 +0200
committerHenrik Rydberg <rydberg@euromail.se>2010-08-28 17:43:22 +0200
commitb2dede96923654de8dfc41413e0f2fceda131efa (patch)
tree131dc36f6d30eed272f72a037d3cd71df7eed808 /usr
parent942c63024ca73a020bd7ae7a80f684c36ff6196c (diff)
New upstream version pending
Supports 60 fingers using MT slots Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'usr')
-rw-r--r--usr/src/dkms_source_tree/hid-3m-pct.c186
1 files changed, 100 insertions, 86 deletions
diff --git a/usr/src/dkms_source_tree/hid-3m-pct.c b/usr/src/dkms_source_tree/hid-3m-pct.c
index 1a6b02b..65441e0 100644
--- a/usr/src/dkms_source_tree/hid-3m-pct.c
+++ b/usr/src/dkms_source_tree/hid-3m-pct.c
@@ -24,29 +24,34 @@ MODULE_LICENSE("GPL");
24 24
25#include "hid-ids.h" 25#include "hid-ids.h"
26 26
27#define MAX_SLOTS 20 27#define MAX_SLOTS 60
28#define MAX_TRACKING_ID 0xfff 28#define MAX_TRKID USHRT_MAX
29#define SN_MOVE 2048 29#define MAX_EVENTS 360
30#define SN_WIDTH 512 30#define SN_MOVE 2048
31#define SN_WIDTH 128
31 32
32struct mmm_finger { 33struct mmm_finger {
33 __s32 x, y, w, h; 34 __s32 x, y, w, h;
34 int touch, valid; 35 __u16 id;
35 int last_touch, id; 36 bool prev_touch;
37 bool touch, valid;
36}; 38};
37 39
38struct mmm_data { 40struct mmm_data {
39 struct mmm_finger f[MAX_SLOTS]; 41 struct mmm_finger f[MAX_SLOTS];
40 int touch, valid; 42 __u16 id;
41 int slot; 43 __u8 curid;
44 __u8 nexp, nreal;
45 bool touch, valid;
42}; 46};
43 47
44static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi, 48static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
45 struct hid_field *field, struct hid_usage *usage, 49 struct hid_field *field, struct hid_usage *usage,
46 unsigned long **bit, int *max) 50 unsigned long **bit, int *max)
47{ 51{
48 struct input_dev *input = hi->input; 52 int f1 = field->logical_minimum;
49 int delta = field->logical_maximum - field->logical_minimum; 53 int f2 = field->logical_maximum;
54 int df = f2 - f1;
50 55
51 switch (usage->hid & HID_USAGE_PAGE) { 56 switch (usage->hid & HID_USAGE_PAGE) {
52 57
@@ -57,27 +62,21 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
57 switch (usage->hid) { 62 switch (usage->hid) {
58 case HID_GD_X: 63 case HID_GD_X:
59 hid_map_usage(hi, usage, bit, max, 64 hid_map_usage(hi, usage, bit, max,
60 EV_ABS, ABS_MT_POSITION_X); 65 EV_ABS, ABS_MT_POSITION_X);
61 input_set_abs_params(input, ABS_MT_POSITION_X, 66 input_set_abs_params(hi->input, ABS_MT_POSITION_X,
62 field->logical_minimum, 67 f1, f2, df / SN_MOVE, 0);
63 field->logical_maximum, 68 /* touchscreen emulation */
64 delta / SN_MOVE, 0); 69 input_set_abs_params(hi->input, ABS_X,
65 input_set_abs_params(input, ABS_X, 70 f1, f2, df / SN_MOVE, 0);
66 field->logical_minimum,
67 field->logical_maximum,
68 delta / SN_MOVE, 0);
69 return 1; 71 return 1;
70 case HID_GD_Y: 72 case HID_GD_Y:
71 hid_map_usage(hi, usage, bit, max, 73 hid_map_usage(hi, usage, bit, max,
72 EV_ABS, ABS_MT_POSITION_Y); 74 EV_ABS, ABS_MT_POSITION_Y);
73 input_set_abs_params(input, ABS_MT_POSITION_Y, 75 input_set_abs_params(hi->input, ABS_MT_POSITION_Y,
74 field->logical_minimum, 76 f1, f2, df / SN_MOVE, 0);
75 field->logical_maximum, 77 /* touchscreen emulation */
76 delta / SN_MOVE, 0); 78 input_set_abs_params(hi->input, ABS_Y,
77 input_set_abs_params(input, ABS_Y, 79 f1, f2, df / SN_MOVE, 0);
78 field->logical_minimum,
79 field->logical_maximum,
80 delta / SN_MOVE, 0);
81 return 1; 80 return 1;
82 } 81 }
83 return 0; 82 return 0;
@@ -95,37 +94,33 @@ static int mmm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
95 case HID_DG_CONFIDENCE: 94 case HID_DG_CONFIDENCE:
96 return -1; 95 return -1;
97 case HID_DG_TIPSWITCH: 96 case HID_DG_TIPSWITCH:
97 /* touchscreen emulation */
98 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); 98 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
99 input_set_capability(input, EV_KEY, BTN_TOUCH); 99 input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
100 return 1; 100 return 1;
101 case HID_DG_WIDTH: 101 case HID_DG_WIDTH:
102 hid_map_usage(hi, usage, bit, max, 102 hid_map_usage(hi, usage, bit, max,
103 EV_ABS, ABS_MT_TOUCH_MAJOR); 103 EV_ABS, ABS_MT_TOUCH_MAJOR);
104 input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 104 input_set_abs_params(hi->input, ABS_MT_TOUCH_MAJOR,
105 field->logical_minimum, 105 f1, f2, df / SN_WIDTH, 0);
106 field->logical_maximum,
107 delta / SN_WIDTH, 0);
108 return 1; 106 return 1;
109 case HID_DG_HEIGHT: 107 case HID_DG_HEIGHT:
110 hid_map_usage(hi, usage, bit, max, 108 hid_map_usage(hi, usage, bit, max,
111 EV_ABS, ABS_MT_TOUCH_MINOR); 109 EV_ABS, ABS_MT_TOUCH_MINOR);
112 input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 110 input_set_abs_params(hi->input, ABS_MT_TOUCH_MINOR,
113 field->logical_minimum, 111 f1, f2, df / SN_WIDTH, 0);
114 field->logical_maximum, 112 input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
115 delta / SN_WIDTH, 0); 113 1, 1, 0, 0);
116 input_set_abs_params(input, ABS_MT_ORIENTATION,
117 1, 1, 0, 0);
118 return 1; 114 return 1;
119 case HID_DG_CONTACTID: 115 case HID_DG_CONTACTID:
120 field->logical_maximum = MAX_TRACKING_ID; 116 field->logical_maximum = MAX_TRKID;
121 hid_map_usage(hi, usage, bit, max, 117 hid_map_usage(hi, usage, bit, max,
122 EV_ABS, ABS_MT_TRACKING_ID); 118 EV_ABS, ABS_MT_TRACKING_ID);
123 input_set_abs_params(input, ABS_MT_TRACKING_ID, 119 input_set_abs_params(hi->input, ABS_MT_TRACKING_ID,
124 0, MAX_TRACKING_ID, 0, 0); 120 0, MAX_TRKID, 0, 0);
125 if (!input->mt) { 121 if (!hi->input->mt)
126 input_mt_create_slots(input, MAX_SLOTS); 122 input_mt_create_slots(hi->input, MAX_SLOTS);
127 input_set_events_per_packet(input, 150); 123 input_set_events_per_packet(hi->input, MAX_EVENTS);
128 }
129 return 1; 124 return 1;
130 } 125 }
131 /* let hid-input decide for the others */ 126 /* let hid-input decide for the others */
@@ -143,6 +138,7 @@ static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi,
143 struct hid_field *field, struct hid_usage *usage, 138 struct hid_field *field, struct hid_usage *usage,
144 unsigned long **bit, int *max) 139 unsigned long **bit, int *max)
145{ 140{
141 /* tell hid-input to skip setup of these event types */
146 if (usage->type == EV_KEY || usage->type == EV_ABS) 142 if (usage->type == EV_KEY || usage->type == EV_ABS)
147 set_bit(usage->type, hi->input->evbit); 143 set_bit(usage->type, hi->input->evbit);
148 return -1; 144 return -1;
@@ -154,40 +150,46 @@ static int mmm_input_mapped(struct hid_device *hdev, struct hid_input *hi,
154 */ 150 */
155static void mmm_filter_event(struct mmm_data *md, struct input_dev *input) 151static void mmm_filter_event(struct mmm_data *md, struct input_dev *input)
156{ 152{
157 static int trkid; 153 struct mmm_finger *oldest = 0;
158 int i, sx = 0, sy = 0, count = 0; 154 int i;
159 for (i = 0; i < MAX_SLOTS; ++i) { 155 for (i = 0; i < MAX_SLOTS; ++i) {
160 struct mmm_finger *f = &md->f[i]; 156 struct mmm_finger *f = &md->f[i];
161 if (!f->valid) 157 if (!f->valid) {
158 /* this finger is just placeholder data, ignore */
162 continue; 159 continue;
160 }
163 input_mt_slot(input, i); 161 input_mt_slot(input, i);
164 if (f->touch) { 162 if (f->touch) {
165 int wide = f->w > f->h; 163 /* this finger is on the screen */
166 int major = wide ? f->w : f->h; 164 int wide = (f->w > f->h);
167 int minor = wide ? f->h : f->w; 165 if (!f->prev_touch)
166 f->id = md->id++;
167 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id);
168 input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); 168 input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x);
169 input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); 169 input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y);
170 input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); 170 input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
171 input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); 171 input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR,
172 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); 172 wide ? f->w : f->h);
173 if (!f->last_touch) 173 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR,
174 f->id = trkid++ & MAX_TRACKING_ID; 174 wide ? f->h : f->w);
175 if (!count++) 175 /* touchscreen emulation: pick the oldest contact */
176 sx = f->x, sy = f->y; 176 if (!oldest || ((f->id - oldest->id) & (SHRT_MAX + 1)))
177 oldest = f;
177 } else { 178 } else {
178 f->id = -1; 179 /* this finger took off the screen */
180 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, -1);
179 } 181 }
180 input_event(input, EV_ABS, ABS_MT_TRACKING_ID, f->id); 182 f->prev_touch = f->touch;
181 f->last_touch = f->touch; 183 f->valid = 0;
182 }
183 for (i = 0; i < MAX_SLOTS; ++i) {
184 struct mmm_finger *f = &md->f[i];
185 f->valid = f->touch = 0;
186 } 184 }
187 input_report_key(input, BTN_TOUCH, count > 0); 185
188 if (count > 0) { 186 /* touchscreen emulation */
189 input_report_abs(input, ABS_X, sx); 187 if (oldest) {
190 input_report_abs(input, ABS_Y, sy); 188 input_event(input, EV_KEY, BTN_TOUCH, 1);
189 input_event(input, EV_ABS, ABS_X, oldest->x);
190 input_event(input, EV_ABS, ABS_Y, oldest->y);
191 } else {
192 input_event(input, EV_KEY, BTN_TOUCH, 0);
191 } 193 }
192 input_sync(input); 194 input_sync(input);
193} 195}
@@ -208,32 +210,44 @@ static int mmm_event(struct hid_device *hid, struct hid_field *field,
208 if (hid->claimed & HID_CLAIMED_INPUT) { 210 if (hid->claimed & HID_CLAIMED_INPUT) {
209 struct input_dev *input = field->hidinput->input; 211 struct input_dev *input = field->hidinput->input;
210 switch (usage->hid) { 212 switch (usage->hid) {
211 case HID_DG_CONTACTCOUNT:
212 break;
213 case HID_DG_TIPSWITCH: 213 case HID_DG_TIPSWITCH:
214 md->touch = value; 214 md->touch = value;
215 break; 215 break;
216 case HID_DG_CONFIDENCE: 216 case HID_DG_CONFIDENCE:
217 if (md->valid && !value)
218 mmm_filter_event(md, input);
219 md->valid = value; 217 md->valid = value;
220 break; 218 break;
219 case HID_DG_WIDTH:
220 if (md->valid)
221 md->f[md->curid].w = value;
222 break;
223 case HID_DG_HEIGHT:
224 if (md->valid)
225 md->f[md->curid].h = value;
226 break;
221 case HID_DG_CONTACTID: 227 case HID_DG_CONTACTID:
222 md->slot = value < MAX_SLOTS ? value : 0; 228 value = clamp_val(value, 0, MAX_SLOTS - 1);
223 md->f[md->slot].touch = md->touch; 229 if (md->valid) {
224 md->f[md->slot].valid = md->valid; 230 md->curid = value;
231 md->f[value].touch = md->touch;
232 md->f[value].valid = 1;
233 md->nreal++;
234 }
225 break; 235 break;
226 case HID_GD_X: 236 case HID_GD_X:
227 md->f[md->slot].x = value; 237 if (md->valid)
238 md->f[md->curid].x = value;
228 break; 239 break;
229 case HID_GD_Y: 240 case HID_GD_Y:
230 md->f[md->slot].y = value; 241 if (md->valid)
231 break; 242 md->f[md->curid].y = value;
232 case HID_DG_WIDTH:
233 md->f[md->slot].w = value;
234 break; 243 break;
235 case HID_DG_HEIGHT: 244 case HID_DG_CONTACTCOUNT:
236 md->f[md->slot].h = value; 245 if (value)
246 md->nexp = value;
247 if (md->nreal >= md->nexp) {
248 mmm_filter_event(md, input);
249 md->nreal = 0;
250 }
237 break; 251 break;
238 } 252 }
239 } 253 }