Mercurial > sdl-ios-xcode
annotate src/video/fbcon/SDL_fbelo.c @ 4:4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
From: Alexander Pipelka <pipelka@bms-austria.com>
Subject: SDL ELO driver bugfix
Hi Sam!
We noticed that the ELO serial touchscreen controller is quite sensitive
in terms of correct protocol handling.
The current implementation cause some controllers to hangup after some
time (> 24h).
I think the attached patch should fix this (I ran my device more than 3
days without any hangups).
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Thu, 26 Apr 2001 16:54:56 +0000 |
parents | 74212992fb08 |
children | 2cf88672fc7f |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@devolution.com | |
21 */ | |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 #include <stdlib.h> | |
29 #include <unistd.h> | |
30 #include <sys/time.h> | |
31 #include <ctype.h> | |
32 | |
33 #include "SDL_fbvideo.h" | |
34 #include "SDL_fbelo.h" | |
35 | |
36 /* | |
37 calibration default values | |
38 values are read from the following environment variables: | |
39 | |
40 SDL_ELO_MIN_X | |
41 SDL_ELO_MAX_X | |
42 SDL_ELO_MIN_Y | |
43 SDL_ELO_MAX_Y | |
44 */ | |
45 | |
46 static int ELO_MIN_X = 400; | |
47 static int ELO_MAX_X = 3670; | |
48 static int ELO_MIN_Y = 500; | |
49 static int ELO_MAX_Y = 3540; | |
50 | |
51 #define ELO_SNAP_SIZE 6 | |
52 #define ELO_TOUCH_BYTE 'T' | |
53 #define ELO_ID 'I' | |
54 #define ELO_MODE 'M' | |
55 #define ELO_PARAMETER 'P' | |
56 #define ELO_REPORT 'B' | |
57 #define ELO_ACK 'A' | |
58 | |
59 #define ELO_INIT_CHECKSUM 0xAA | |
60 | |
61 #define ELO_BTN_PRESS 0x01 | |
62 #define ELO_STREAM 0x02 | |
63 #define ELO_BTN_RELEASE 0x04 | |
64 | |
65 #define ELO_TOUCH_MODE 0x01 | |
66 #define ELO_STREAM_MODE 0x02 | |
67 #define ELO_UNTOUCH_MODE 0x04 | |
68 #define ELO_RANGE_CHECK_MODE 0x40 | |
69 #define ELO_TRIM_MODE 0x02 | |
70 #define ELO_CALIB_MODE 0x04 | |
71 #define ELO_SCALING_MODE 0x08 | |
72 #define ELO_TRACKING_MODE 0x40 | |
73 | |
74 #define ELO_SERIAL_MASK 0xF8 | |
75 | |
76 #define ELO_SERIAL_IO '0' | |
77 | |
78 #define ELO_MAX_TRIALS 3 | |
79 #define ELO_MAX_WAIT 100000 | |
80 #define ELO_UNTOUCH_DELAY 5 | |
81 #define ELO_REPORT_DELAY 1 | |
82 | |
83 /* eloParsePacket | |
84 */ | |
85 int eloParsePacket(unsigned char* mousebuf, int* dx, int* dy, int* button_state) { | |
86 static int elo_button = 0; | |
87 static int last_x = 0; | |
88 static int last_y = 0; | |
89 int x,y; | |
90 | |
91 /* Check if we have a touch packet */ | |
92 if (mousebuf[1] != ELO_TOUCH_BYTE) { | |
93 return 0; | |
94 } | |
95 | |
96 x = ((mousebuf[4] << 8) | mousebuf[3]); | |
97 y = ((mousebuf[6] << 8) | mousebuf[5]); | |
98 | |
99 if((abs(x - last_x) > ELO_SNAP_SIZE) || (abs(y - last_y) > ELO_SNAP_SIZE)) { | |
100 *dx = ((mousebuf[4] << 8) | mousebuf[3]); | |
101 *dy = ((mousebuf[6] << 8) | mousebuf[5]); | |
102 } | |
103 else { | |
104 *dx = last_x; | |
105 *dy = last_y; | |
106 } | |
107 | |
108 last_x = *dx; | |
109 last_y = *dy; | |
110 | |
111 if ( (mousebuf[2] & 0x07) == ELO_BTN_PRESS ) { | |
112 elo_button = 1; | |
113 } | |
114 if ( (mousebuf[2] & 0x07) == ELO_BTN_RELEASE ) { | |
115 elo_button = 0; | |
116 } | |
117 | |
118 *button_state = elo_button; | |
119 return 1; | |
120 } | |
121 | |
122 /* Convert the raw coordinates from the ELO controller | |
123 to a screen position. | |
124 */ | |
125 void eloConvertXY(_THIS, int *dx, int *dy) { | |
126 int input_x = *dx; | |
127 int input_y = *dy; | |
128 int width = ELO_MAX_X - ELO_MIN_X; | |
129 int height = ELO_MAX_Y - ELO_MIN_Y; | |
130 | |
131 *dx = (cache_vinfo.xres - (cache_vinfo.xres * (input_x - ELO_MIN_X)) / width); | |
132 *dy = (cache_vinfo.yres * (input_y - ELO_MIN_Y)) / height; | |
133 } | |
134 | |
135 | |
136 /* eloGetPacket | |
137 */ | |
138 int eloGetPacket(unsigned char* buffer, int* buffer_p, int* checksum, int fd) { | |
139 int num_bytes; | |
140 int ok; | |
141 | |
142 if(fd == 0) { | |
143 num_bytes = ELO_PACKET_SIZE; | |
144 } | |
145 else { | |
146 num_bytes = read(fd, | |
147 (char *) (buffer + *buffer_p), | |
148 ELO_PACKET_SIZE - *buffer_p); | |
149 } | |
150 | |
151 if (num_bytes < 0) { | |
152 #ifdef DEBUG_MOUSE | |
153 fprintf(stderr, "System error while reading from Elographics touchscreen.\n"); | |
154 #endif | |
155 return 0; | |
156 } | |
157 | |
158 while (num_bytes) { | |
159 if ((*buffer_p == 0) && (buffer[0] != ELO_START_BYTE)) { | |
160 memcpy(&buffer[0], &buffer[1], num_bytes-1); | |
161 } | |
162 else { | |
163 if (*buffer_p < ELO_PACKET_SIZE-1) { | |
164 *checksum = *checksum + buffer[*buffer_p]; | |
165 *checksum = *checksum % 256; | |
166 } | |
167 (*buffer_p)++; | |
168 } | |
169 num_bytes--; | |
170 } | |
171 | |
172 if (*buffer_p == ELO_PACKET_SIZE) { | |
173 ok = (*checksum == buffer[ELO_PACKET_SIZE-1]); | |
174 *checksum = ELO_INIT_CHECKSUM; | |
175 *buffer_p = 0; | |
176 | |
177 if (!ok) { | |
178 return 0; | |
179 } | |
180 | |
181 return 1; | |
182 } | |
183 else { | |
184 return 0; | |
185 } | |
186 } | |
187 | |
188 /* eloSendPacket | |
189 */ | |
190 | |
191 int eloSendPacket(unsigned char* packet, int fd) | |
192 { | |
193 int i, result; | |
194 int sum = ELO_INIT_CHECKSUM; | |
195 | |
196 packet[0] = ELO_START_BYTE; | |
197 for (i = 0; i < ELO_PACKET_SIZE-1; i++) { | |
198 sum += packet[i]; | |
199 sum &= 0xFF; | |
200 } | |
201 packet[ELO_PACKET_SIZE-1] = sum; | |
202 | |
203 result = write(fd, packet, ELO_PACKET_SIZE); | |
204 | |
205 if (result != ELO_PACKET_SIZE) { | |
206 #ifdef DEBUG_MOUSE | |
207 printf("System error while sending to Elographics touchscreen.\n"); | |
208 #endif | |
209 return 0; | |
210 } | |
211 else { | |
212 return 1; | |
213 } | |
214 } | |
215 | |
216 | |
217 /* eloWaitForInput | |
218 */ | |
219 int eloWaitForInput(int fd, int timeout) | |
220 { | |
221 fd_set readfds; | |
222 struct timeval to; | |
223 int r; | |
224 | |
225 FD_ZERO(&readfds); | |
226 FD_SET(fd, &readfds); | |
227 to.tv_sec = 0; | |
228 to.tv_usec = timeout; | |
229 | |
230 r = select(FD_SETSIZE, &readfds, NULL, NULL, &to); | |
231 return r; | |
232 } | |
233 | |
234 /* eloWaitReply | |
235 */ | |
236 int eloWaitReply(unsigned char type, unsigned char *reply, int fd) { | |
237 int ok; | |
238 int i, result; | |
239 int reply_p = 0; | |
240 int sum = ELO_INIT_CHECKSUM; | |
241 | |
242 i = ELO_MAX_TRIALS; | |
243 do { | |
244 ok = 0; | |
245 | |
246 result = eloWaitForInput(fd, ELO_MAX_WAIT); | |
247 | |
248 if (result > 0) { | |
249 ok = eloGetPacket(reply, &reply_p, &sum, fd); | |
250 | |
251 if (ok && reply[1] != type && type != ELO_PARAMETER) { | |
252 #ifdef DEBUG_MOUSE | |
253 fprintf(stderr, "Wrong reply received\n"); | |
254 #endif | |
255 ok = 0; | |
256 } | |
257 } | |
258 else { | |
259 #ifdef DEBUG_MOUSE | |
260 fprintf(stderr, "No input!\n"); | |
261 #endif | |
262 } | |
263 | |
264 if (result == 0) { | |
265 i--; | |
266 } | |
267 } while(!ok && (i>0)); | |
268 | |
269 return ok; | |
270 } | |
271 | |
272 | |
273 /* eloWaitAck | |
274 */ | |
275 | |
276 int eloWaitAck(int fd) { | |
277 unsigned char packet[ELO_PACKET_SIZE]; | |
278 int i, nb_errors; | |
279 | |
280 if (eloWaitReply(ELO_ACK, packet, fd)) { | |
281 for (i = 0, nb_errors = 0; i < 4; i++) { | |
282 if (packet[2 + i] != '0') { | |
283 nb_errors++; | |
284 } | |
285 } | |
286 | |
287 if (nb_errors != 0) { | |
288 #ifdef DEBUG_MOUSE | |
289 fprintf(stderr, "Elographics acknowledge packet reports %d errors\n", nb_errors); | |
290 #endif | |
291 } | |
292 return 1; | |
293 } | |
294 else { | |
295 return 0; | |
296 } | |
297 } | |
298 | |
299 | |
300 /* eloSendQuery -- | |
301 */ | |
302 int eloSendQuery(unsigned char *request, unsigned char* reply, int fd) { | |
303 int ok; | |
304 | |
305 if (eloSendPacket(request, fd)) { | |
306 ok = eloWaitReply(toupper(request[1]), reply, fd); | |
307 if (ok) { | |
308 ok = eloWaitAck(fd); | |
309 } | |
310 return ok; | |
311 } | |
312 else { | |
313 return 0; | |
314 } | |
315 } | |
316 | |
317 | |
318 /* eloSendControl | |
319 */ | |
320 int eloSendControl(unsigned char* control, int fd) { | |
321 if (eloSendPacket(control, fd)) { | |
322 return eloWaitAck(fd); | |
323 } | |
324 else { | |
325 return 0; | |
326 } | |
327 } | |
328 | |
329 /* eloInitController | |
330 */ | |
331 int eloInitController(int fd) { | |
332 unsigned char req[ELO_PACKET_SIZE]; | |
333 unsigned char reply[ELO_PACKET_SIZE]; | |
334 const char *buffer = NULL; | |
335 int result = 0; | |
336 | |
337 struct termios mouse_termios; | |
338 | |
339 /* try to read the calibration values */ | |
340 buffer = getenv("SDL_ELO_MIN_X"); | |
341 if(buffer) { | |
342 ELO_MIN_X = atoi(buffer); | |
343 } | |
344 buffer = getenv("SDL_ELO_MAX_X"); | |
345 if(buffer) { | |
346 ELO_MAX_X = atoi(buffer); | |
347 } | |
348 buffer = getenv("SDL_ELO_MIN_Y"); | |
349 if(buffer) { | |
350 ELO_MIN_Y = atoi(buffer); | |
351 } | |
352 buffer = getenv("SDL_ELO_MAX_Y"); | |
353 if(buffer) { | |
354 ELO_MAX_Y = atoi(buffer); | |
355 } | |
356 | |
357 #ifdef DEBUG_MOUSE | |
358 fprintf( stderr, "ELO calibration values:\nmin_x: %i\nmax_x: %i\nmin_y: %i\nmax_y: %i\n", | |
359 ELO_MIN_X, | |
360 ELO_MAX_X, | |
361 ELO_MIN_Y, | |
362 ELO_MAX_Y); | |
363 #endif | |
364 | |
365 /* set comm params */ | |
366 memset(&mouse_termios, 0, sizeof(mouse_termios)); | |
367 mouse_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL; | |
368 mouse_termios.c_cc[VMIN] = 1; | |
369 result = tcsetattr(fd, TCSANOW, &mouse_termios); | |
370 | |
371 if (result < 0) { | |
372 #ifdef DEBUG_MOUSE | |
373 fprintf( stderr, "Unable to configure Elographics touchscreen port\n"); | |
374 #endif | |
375 return 0; | |
376 } | |
377 | |
378 memset(req, 0, ELO_PACKET_SIZE); | |
379 req[1] = tolower(ELO_PARAMETER); | |
380 if (!eloSendQuery(req, reply, fd)) { | |
381 #ifdef DEBUG_MOUSE | |
382 fprintf( stderr, "Not at the specified rate or model 2310, will continue\n"); | |
383 #endif | |
384 } | |
385 | |
386 memset(req, 0, ELO_PACKET_SIZE); | |
387 req[1] = tolower(ELO_ID); | |
388 if (eloSendQuery(req, reply, fd)) { | |
389 #ifdef DEBUG_MOUSE | |
390 fprintf(stderr, "Ok, controller configured!\n"); | |
391 #endif | |
392 } | |
393 else { | |
394 #ifdef DEBUG_MOUSE | |
395 fprintf( stderr, "Unable to ask Elographics touchscreen identification\n"); | |
396 #endif | |
397 return 0; | |
398 } | |
399 | |
400 memset(req, 0, ELO_PACKET_SIZE); | |
401 req[1] = ELO_MODE; | |
402 req[3] = ELO_TOUCH_MODE | ELO_STREAM_MODE | ELO_UNTOUCH_MODE; | |
403 req[4] = ELO_TRACKING_MODE; | |
404 if (!eloSendControl(req, fd)) { | |
405 #ifdef DEBUG_MOUSE | |
406 fprintf( stderr, "Unable to change Elographics touchscreen operating mode\n"); | |
407 #endif | |
408 return 0; | |
409 } | |
410 | |
411 memset(req, 0, ELO_PACKET_SIZE); | |
412 req[1] = ELO_REPORT; | |
413 req[2] = ELO_UNTOUCH_DELAY; | |
414 req[3] = ELO_REPORT_DELAY; | |
415 if (!eloSendControl(req, fd)) { | |
416 #ifdef DEBUG_MOUSE | |
417 fprintf( stderr, "Unable to change Elographics touchscreen reports timings\n"); | |
418 #endif | |
419 return 0; | |
420 } | |
421 | |
422 return 1; | |
423 } | |
4
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
424 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
425 int eloReadPosition(_THIS, int fd, int* x, int* y, int* button_state, int* realx, int* realy) { |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
426 unsigned char buffer[ELO_PACKET_SIZE]; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
427 int pointer = 0; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
428 int checksum = ELO_INIT_CHECKSUM; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
429 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
430 while(pointer < ELO_PACKET_SIZE) { |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
431 if(eloGetPacket(buffer, &pointer, &checksum, fd)) { |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
432 break; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
433 } |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
434 } |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
435 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
436 if(!eloParsePacket(buffer, realx, realy, button_state)) { |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
437 return 0; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
438 } |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
439 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
440 *x = *realx; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
441 *y = *realy; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
442 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
443 eloConvertXY(this, x, y); |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
444 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
445 return 1; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
446 } |