OSDN Git Service

cy8mrln-palmpre: print out just another value
[android-x86/external-tslib.git] / plugins / cy8mrln-palmpre.c
1 /*
2  *  tslib/plugins/cy8mrln-palmpre.c
3  *
4  *  Copyright (C) 2010 Frederik Sdun <frederik.sdun@googlemail.com>
5  *                     Thomas Zimmermann <ml@vdm-design.de>
6  *
7  *
8  * This file is placed under the LGPL.  Please see the file
9  * COPYING for more details.
10  *
11  *
12  * Pluging for the cy8mrln touchscreen with the Firmware used on the Palm Pre
13  */
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <limits.h>
17 #include <stdint.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stddef.h>
22 #include <sys/ioctl.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26
27 #include "config.h"
28 #include "tslib-private.h"
29 #include "tslib-filter.h"
30
31 #include "cy8mrln.h"
32
33 #define NOISE          12
34 #define SCREEN_WIDTH   319
35 #define SCREEN_HEIGHT  527
36 #define H_FIELDS       7
37 #define V_FIELDS       11
38
39 #define DEBUG
40
41 #define container_of(ptr, type, member) ({ \
42         const typeof( ((type*)0)->member ) *__mptr = (ptr); \
43         (type *)( (char *)__mptr - offsetof(type, member)); })
44
45 struct cy8mrln_palmpre_input
46 {  
47         uint16_t n_r;
48         uint16_t field[H_FIELDS * V_FIELDS];
49         uint16_t ffff;            //seperator? always ff
50         uint8_t seq_nr1;                //incremented if seq_nr0 = scanrate
51         uint16_t seq_nr2;              //incremeted if seq_nr1 = 255
52         uint8_t unknown[4]; 
53         uint8_t seq_nr0;                //incremented. 0- scanrate
54         uint8_t null;              //\0
55 }__attribute__((packed));
56
57 struct tslib_cy8mrln_palmpre 
58 {
59         struct tslib_module_info module;
60         uint16_t nulls[H_FIELDS * V_FIELDS];
61 };
62
63 static int scanrate = 60;
64 static int verbose = 0;
65 static int wot_threshold = 22;
66 static int sleepmode = CY8MRLN_ON_STATE;
67 static int wot_scanrate = WOT_SCANRATE_512HZ;
68 static int timestamp_mode = 1;
69
70 static int 
71 cy8mrln_palmpre_set_scanrate(struct tsdev* dev, int rate)
72 {
73         if (dev == NULL || ioctl(dev->fd,CY8MRLN_IOCTL_SET_SCANRATE,&rate) < 0)
74                 goto error;
75                 
76         scanrate = rate;
77         return 0;
78         
79 error:
80         printf("TSLIB: cy8mrln_palmpre: ERROR: could not set scanrate value\n");
81         return -1;
82 }
83
84 static int 
85 cy8mrln_palmpre_set_verbose(struct tsdev* dev, int v)
86 {
87         if (dev == NULL || ioctl(dev->fd,CY8MRLN_IOCTL_SET_VERBOSE_MODE,&v) < 0)
88                 goto error;
89         
90         verbose = v;
91         return 0;
92
93 error:
94         printf("TSLIB: cy8mrln_palmpre: ERROR: could not set verbose value\n");
95         return -1;
96 }
97
98 static int 
99 cy8mrln_palmpre_set_sleepmode(struct tsdev* dev, int mode)
100 {
101         if (dev == NULL || ioctl(dev->fd,CY8MRLN_IOCTL_SET_SLEEPMODE,&mode) < 0)
102                 goto error;
103
104         sleepmode = mode;
105         return 0;
106         
107 error:
108         printf("TSLIB: cy8mrln_palmpre: ERROR: could not set sleepmode value\n");
109         return -1;
110 }
111
112 static int 
113 cy8mrln_palmpre_set_wot_scanrate(struct tsdev* dev, int rate)
114 {
115         if (dev == NULL || ioctl(dev->fd,CY8MRLN_IOCTL_SET_WOT_SCANRATE,&rate) < 0)
116                 goto error;
117
118         wot_scanrate = rate;
119         return 0;
120
121 error:
122         printf("TSLIB: cy8mrln_palmpre: ERROR: could not set scanrate value\n");
123         return -1;
124 }
125
126 static int 
127 cy8mrln_palmpre_set_wot_threshold(struct tsdev* dev, int v)
128 {
129         if (dev == NULL) 
130                 goto error;
131         if(v < WOT_THRESHOLD_MIN || v > WOT_THRESHOLD_MAX)
132                 goto error;
133         if(ioctl(dev->fd,CY8MRLN_IOCTL_SET_WOT_THRESHOLD,&v) < 0)
134                 goto error;
135                 
136         wot_threshold = v;
137         return 0;
138         
139 error:
140         printf("TSLIB: cy8mrln_palmpre: ERROR: could not set wot treshhold value\n");
141         return -1;
142 }
143
144 static int 
145 cy8mrln_palmpre_set_timestamp_mode(struct tsdev* dev, int v)
146 {
147         v = v ? 1 : 0;
148         if(dev == NULL || ioctl(dev->fd,CY8MRLN_IOCTL_SET_TIMESTAMP_MODE,&v) < 0)
149              goto error;
150         timestamp_mode = v;
151         return 0;
152         
153 error:
154         printf("TSLIB: cy8mrln_palmpre: ERROR: could not set timestamp value\n");
155         return -1;
156 }
157
158 static int
159 parse_scanrate(struct tslib_module_info *info, char *str, void *data)
160 {
161         struct tslib_cy8mrln_palmpre *i = (struct tslib_cy8mrln_palmpre*) info;
162         unsigned long rate = strtoul(str, NULL, 0);
163
164         if(rate == ULONG_MAX && errno == ERANGE)
165                 return -1;
166
167         return cy8mrln_palmpre_set_scanrate(i->module.dev, scanrate);
168 }
169
170 static int
171 parse_verbose(struct tslib_module_info *info, char *str, void *data)
172 {
173         struct tslib_cy8mrln_palmpre *i = (struct tslib_cy8mrln_palmpre*) info;
174         unsigned long v = strtoul(str, NULL, 0);
175
176         if(v == ULONG_MAX && errno == ERANGE)
177                 return -1;
178
179         return cy8mrln_palmpre_set_verbose(i->module.dev, scanrate);
180 }
181
182 static int
183 parse_wot_scanrate(struct tslib_module_info *info, char *str, void *data)
184 {
185         struct tslib_cy8mrln_palmpre *i = (struct tslib_cy8mrln_palmpre*) info;
186         unsigned long rate = strtoul(str, NULL, 0);
187
188         return cy8mrln_palmpre_set_wot_scanrate(i->module.dev, rate);
189 }
190
191 static int
192 parse_wot_threshold(struct tslib_module_info *info, char *str, void *data)
193 {
194         struct tslib_cy8mrln_palmpre *i = (struct tslib_cy8mrln_palmpre*) info;
195         unsigned long threshold = strtoul(str, NULL, 0);
196
197         return cy8mrln_palmpre_set_wot_threshold(i->module.dev, threshold);
198 }
199
200 static int
201 parse_sleepmode(struct tslib_module_info *info, char *str, void *data)
202 {
203         struct tslib_cy8mrln_palmpre *i = (struct tslib_cy8mrln_palmpre*) info;
204         unsigned long sleep = strtoul(str, NULL, 0);
205
206         return cy8mrln_palmpre_set_sleepmode(i->module.dev, sleep);
207 }
208
209 static int
210 parse_timestamp_mode(struct tslib_module_info *info, char *str, void *data)
211 {
212         struct tslib_cy8mrln_palmpre *i = (struct tslib_cy8mrln_palmpre*) info;
213         unsigned long sleep = strtoul(str, NULL, 0);
214
215         return cy8mrln_palmpre_set_sleepmode(i->module.dev, sleep);
216 }
217
218 static const struct tslib_vars raw_vars[] =
219 {
220         { "scanrate", NULL, parse_scanrate},
221         { "verbose", NULL, parse_verbose},
222         { "wot_scanrate", NULL, parse_wot_scanrate},
223         { "wot_threshold", NULL, parse_wot_threshold},
224         { "sleepmode", NULL, parse_sleepmode},
225         { "timestamp_mode", NULL, parse_timestamp_mode}
226 };
227
228 #define NR_VARS (sizeof(raw_vars) / sizeof(raw_vars[0]))
229
230 void
231 interpolate(uint16_t field[H_FIELDS * V_FIELDS], int i, struct ts_sample *out) {
232         float f11, f12, f13, f21, f22, f23, f31, f32, f33;
233         int x = SCREEN_WIDTH / H_FIELDS * (H_FIELDS - (i % H_FIELDS));
234         int y = SCREEN_HEIGHT / (V_FIELDS - 1) * (i / H_FIELDS);
235         static int dx = SCREEN_WIDTH / H_FIELDS;
236         static int dy = SCREEN_HEIGHT / V_FIELDS;
237         
238         /* caluculate corrections for top, bottom, left and right fields */
239         f12 = (i < (H_FIELDS + 1)) ? 0.0 : 0.5 * field[i - H_FIELDS] / field[i];
240         f32 = (i > (H_FIELDS * (V_FIELDS - 2)))
241               ? 0.0 : 0.5 * field[i + H_FIELDS] / field[i];
242         f21 = (i % H_FIELDS == (H_FIELDS - 1))
243               ? 0.0 : 0.5 * field[i + 1] / field[i];
244         f23 = (i % H_FIELDS == 0) ? 0.0 : 0.5 * field[i - 1] / field[i];
245
246         /*
247            correct values for the edges, shift the mesuarment point by half a 
248            field diminsion to the outside
249         */
250         if (i == 0) {
251                 x = x + dx / 2;
252                 f21 = f21 * 2.0;
253                 y = y - dy / 2;
254                 f32 = f32 * 2.0;
255         } else if (i == (H_FIELDS - 1)) {
256                 x = x - dx / 2;
257                 f23 = f23 * 2.0;
258                 y = y - dy / 2;
259                 f32 = f32 * 2.0;
260         } else if (i % H_FIELDS == (H_FIELDS - 1)) {
261                 x = x - dx / 2;
262                 f23 = f23 * 2.0;
263         } else if (i % H_FIELDS == 0) {
264                 x = x + dx / 2;
265                 f21 = f21 * 2.0;
266         } else if (i < H_FIELDS) {
267                 y = y - dy / 2;
268                 f32 = f32 * 2.0;
269         } else if (i == (H_FIELDS * (V_FIELDS - 2))) {
270                 x = x + dx / 2;
271                 f21 = f21 * 2.0;
272                 y = y + dy / 2;
273                 f12 = f12 * 2.0;
274         } else if (i == (H_FIELDS * (V_FIELDS - 1) - 1)) {
275                 x = x - dx / 2;
276                 f23 = f23 * 2.0;
277                 y = y + dy / 2;
278                 f12 = f12 * 2.0;
279         } else if (i > (H_FIELDS * (V_FIELDS - 2))) {
280                 y = y + dy / 2;
281                 f12 = f12 * 2.0;
282         }
283
284         /* caluclate corrections for the corners */
285 /*
286         f11 = (i % H_FIELDS == (H_FIELDS - 1) || i < (H_FIELDS + 1))
287               ? 0.0 : 0.4 * field[i - H_FIELDS + 1] / field[i];
288         f13 = (i % H_FIELDS == 0 || i < (H_FIELDS + 1))
289               ? 0.0 : 0.4 * field[i - H_FIELDS - 1] / field[i];
290         f31 = (i % H_FIELDS == (H_FIELDS - 1)
291                || i > (H_FIELDS * (V_FIELDS - 1) - 1))
292               ? 0.0 : 0.4 * field[i + H_FIELDS + 1] / field[i];
293         f33 = (i % H_FIELDS == 0 || i > (H_FIELDS * (V_FIELDS - 1) - 1))
294               ? 0.0 : 0.4 * field[i + H_FIELDS - 1] / field[i];
295 */
296
297         out->x = x // + (f13 + f33 - f11 - f31) * dx /* use corners too?*/
298                  + (f23 - f21) * dx
299 //               + (f21 == 0.0) ? ((f23 * 2 + (dx / 2)) * dx) : (f23 * dx)
300 //               - (f23 == 0.0) ? ((f21 * 2 + (dx / 2)) * dx) : (f21 * dx)
301                  - (dx / 2);
302         out->y = y // + (f31 + f33 - f11 - f13) * dy /* use corners too?*/
303                  + (f32 - f12) * dy + (dy / 2);
304
305         out->pressure = field[i];
306 #ifdef DEBUG
307         printf("RAW---------------------------> f22: %f (%d) f21: %f (%d), f23: %f (%d), f12: %f (%d), f32: %f (%d), \n", 
308                f22, fields[i],
309                f21, field[i - 1], f23, field[i + 1], f12,
310                field[i - H_FIELDS], f32, field[i + H_FIELDS]);
311 #endif /*DEBUG*/
312 }
313
314 static int
315 cy8mrln_palmpre_read(struct tslib_module_info *info, struct ts_sample *samp, int nr)
316 {
317         struct tsdev *ts = info->dev;
318         struct cy8mrln_palmpre_input *cy8mrln_evt;
319         struct tslib_cy8mrln_palmpre *cy8mrln_info;
320         int max_index = 0, max_value = 0, i = 0;
321         uint16_t tmp_value;
322         int ret;
323         
324         cy8mrln_info = container_of(info, struct tslib_cy8mrln_palmpre, module);
325         
326         cy8mrln_evt = alloca(sizeof(*cy8mrln_evt) * nr);
327         ret = read(ts->fd, cy8mrln_evt, sizeof(*cy8mrln_evt) * nr);
328         if (ret > 0) {
329                 max_index = 0;
330                 max_value = 0;
331                 while(ret >= (int)sizeof(*cy8mrln_evt)) {
332                         for (i = 0; i < (H_FIELDS * V_FIELDS); i++) {
333                                 /* auto calibrate zero values */
334                                 if (cy8mrln_evt->field[i] > cy8mrln_info->nulls[i])
335                                         cy8mrln_info->nulls[i] = cy8mrln_evt->field[i];
336
337                                 tmp_value = abs(cy8mrln_info->nulls[i] - cy8mrln_evt->field[i]);
338
339                                 /* check for the maximum value */
340                                 if (tmp_value > max_value) {
341                                         max_value = tmp_value;
342                                         max_index = i;
343                                 }
344
345                                 cy8mrln_evt->field[i] = tmp_value;
346                         }
347                         /* only caluclate events that are not noise */
348                         if (max_value > NOISE) {
349                                 interpolate(cy8mrln_evt->field, max_index, samp);
350 #ifdef DEBUG
351                                 fprintf(stderr,"RAW---------------------------> %d %d %d\n",
352                                         samp->x, samp->y, samp->pressure);
353 #endif /*DEBUG*/
354                                 gettimeofday(&samp->tv,NULL);
355                                 samp++;
356                         }
357
358                         cy8mrln_evt++;
359                         ret -= sizeof(*cy8mrln_evt);
360                 }
361         } else {
362                 return -1;
363         }
364
365         ret = nr;
366         return ret;
367 }
368
369 static int 
370 cy8mrln_palmpre_fini(struct tslib_module_info *inf)
371 {
372         return 0;
373 }
374
375
376 static const struct tslib_ops cy8mrln_palmpre_ops = 
377 {
378         .read = cy8mrln_palmpre_read,
379         .fini = cy8mrln_palmpre_fini,
380 };
381
382 TSAPI struct tslib_module_info *cy8mrln_palmpre_mod_init(struct tsdev *dev, const char *params)
383 {
384         struct tslib_cy8mrln_palmpre *info;
385         struct cy8mrln_palmpre_input input;
386         
387         info = malloc(sizeof(struct tslib_cy8mrln_palmpre));
388         if(info == NULL)
389              return NULL;
390         info->module.ops = &cy8mrln_palmpre_ops;
391
392         cy8mrln_palmpre_set_verbose(dev,verbose);
393         cy8mrln_palmpre_set_scanrate(dev,scanrate);
394         cy8mrln_palmpre_set_timestamp_mode(dev,timestamp_mode);
395         cy8mrln_palmpre_set_sleepmode(dev,sleepmode);
396         cy8mrln_palmpre_set_wot_scanrate(dev,wot_scanrate);
397         cy8mrln_palmpre_set_wot_threshold(dev,wot_threshold);
398
399         if (tslib_parse_vars(&info->module, raw_vars, NR_VARS, params)) {
400                 free(info);
401                 return NULL;
402         }
403
404         // FIXME why do we read here one packet from fd?
405         read(dev->fd, &input, sizeof(input));
406
407         memcpy(info->nulls, input.field, H_FIELDS * V_FIELDS * sizeof(uint16_t));
408
409         return &(info->module);
410 }
411 #ifndef TSLIB_STATIC_CY8MRLN_MODULE
412         TSLIB_MODULE_INIT(cy8mrln_palmpre_mod_init);
413 #endif