OSDN Git Service

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