Mercurial > sdl-ios-xcode
annotate src/video/fbcon/SDL_fbelo.c @ 937:1e6366bde299
Date: Tue, 27 Jul 2004 17:14:00 +0200
From: "Eckhard Stolberg"
Subject: Controller names in SDL for Windows
I'm working on an Atari 2600 emulator for different systems that uses
the SDL. Some time ago someone created an adaptor that lets you use
your old Atari controllers with your computer through the USB port.
Some of the Atari controllers require special handling by the emulator,
so it would be nice, if it would be possible to detect if any of the
controllers connected to the computer is this adaptor.
SDL would allow that with the SDL_JoystickName function, but unfortunately
it doesn't work properly on Windows. On Linux and MacOSX this function
returns the name of the controller, but on Windows you'll only get the
name of the joystick driver. Most joysticks nowadays use the generic
Microsoft driver, so they all return the same name.
In an old MSDN article
(http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnarinput/html/msdn_extdirect.asp)
Microsoft describes how to read out the OEM controller names from the registry.
I have implemented this for the SDL controller handler on Windows,
and now reading the joystick name works properly there too.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 21 Aug 2004 03:45:58 +0000 |
parents | b8d311d90021 |
children | 36f24cdfcda7 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 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 | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
152
diff
changeset
|
20 slouken@libsdl.org |
0 | 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> | |
152 | 32 #include <string.h> |
0 | 33 |
34 #include "SDL_fbvideo.h" | |
35 #include "SDL_fbelo.h" | |
36 | |
37 /* | |
38 calibration default values | |
39 values are read from the following environment variables: | |
40 | |
41 SDL_ELO_MIN_X | |
42 SDL_ELO_MAX_X | |
43 SDL_ELO_MIN_Y | |
44 SDL_ELO_MAX_Y | |
45 */ | |
46 | |
47 static int ELO_MIN_X = 400; | |
48 static int ELO_MAX_X = 3670; | |
49 static int ELO_MIN_Y = 500; | |
50 static int ELO_MAX_Y = 3540; | |
51 | |
52 #define ELO_SNAP_SIZE 6 | |
53 #define ELO_TOUCH_BYTE 'T' | |
54 #define ELO_ID 'I' | |
55 #define ELO_MODE 'M' | |
56 #define ELO_PARAMETER 'P' | |
57 #define ELO_REPORT 'B' | |
58 #define ELO_ACK 'A' | |
59 | |
60 #define ELO_INIT_CHECKSUM 0xAA | |
61 | |
62 #define ELO_BTN_PRESS 0x01 | |
63 #define ELO_STREAM 0x02 | |
64 #define ELO_BTN_RELEASE 0x04 | |
65 | |
66 #define ELO_TOUCH_MODE 0x01 | |
67 #define ELO_STREAM_MODE 0x02 | |
68 #define ELO_UNTOUCH_MODE 0x04 | |
69 #define ELO_RANGE_CHECK_MODE 0x40 | |
70 #define ELO_TRIM_MODE 0x02 | |
71 #define ELO_CALIB_MODE 0x04 | |
72 #define ELO_SCALING_MODE 0x08 | |
73 #define ELO_TRACKING_MODE 0x40 | |
74 | |
75 #define ELO_SERIAL_MASK 0xF8 | |
76 | |
77 #define ELO_SERIAL_IO '0' | |
78 | |
79 #define ELO_MAX_TRIALS 3 | |
80 #define ELO_MAX_WAIT 100000 | |
81 #define ELO_UNTOUCH_DELAY 5 | |
82 #define ELO_REPORT_DELAY 1 | |
83 | |
84 /* eloParsePacket | |
85 */ | |
86 int eloParsePacket(unsigned char* mousebuf, int* dx, int* dy, int* button_state) { | |
87 static int elo_button = 0; | |
88 static int last_x = 0; | |
89 static int last_y = 0; | |
90 int x,y; | |
91 | |
92 /* Check if we have a touch packet */ | |
93 if (mousebuf[1] != ELO_TOUCH_BYTE) { | |
94 return 0; | |
95 } | |
96 | |
97 x = ((mousebuf[4] << 8) | mousebuf[3]); | |
98 y = ((mousebuf[6] << 8) | mousebuf[5]); | |
99 | |
100 if((abs(x - last_x) > ELO_SNAP_SIZE) || (abs(y - last_y) > ELO_SNAP_SIZE)) { | |
101 *dx = ((mousebuf[4] << 8) | mousebuf[3]); | |
102 *dy = ((mousebuf[6] << 8) | mousebuf[5]); | |
103 } | |
104 else { | |
105 *dx = last_x; | |
106 *dy = last_y; | |
107 } | |
108 | |
109 last_x = *dx; | |
110 last_y = *dy; | |
111 | |
112 if ( (mousebuf[2] & 0x07) == ELO_BTN_PRESS ) { | |
113 elo_button = 1; | |
114 } | |
115 if ( (mousebuf[2] & 0x07) == ELO_BTN_RELEASE ) { | |
116 elo_button = 0; | |
117 } | |
118 | |
119 *button_state = elo_button; | |
120 return 1; | |
121 } | |
122 | |
123 /* Convert the raw coordinates from the ELO controller | |
124 to a screen position. | |
125 */ | |
126 void eloConvertXY(_THIS, int *dx, int *dy) { | |
127 int input_x = *dx; | |
128 int input_y = *dy; | |
129 int width = ELO_MAX_X - ELO_MIN_X; | |
130 int height = ELO_MAX_Y - ELO_MIN_Y; | |
131 | |
132 *dx = (cache_vinfo.xres - (cache_vinfo.xres * (input_x - ELO_MIN_X)) / width); | |
133 *dy = (cache_vinfo.yres * (input_y - ELO_MIN_Y)) / height; | |
134 } | |
135 | |
136 | |
137 /* eloGetPacket | |
138 */ | |
139 int eloGetPacket(unsigned char* buffer, int* buffer_p, int* checksum, int fd) { | |
140 int num_bytes; | |
141 int ok; | |
142 | |
143 if(fd == 0) { | |
144 num_bytes = ELO_PACKET_SIZE; | |
145 } | |
146 else { | |
147 num_bytes = read(fd, | |
148 (char *) (buffer + *buffer_p), | |
149 ELO_PACKET_SIZE - *buffer_p); | |
150 } | |
151 | |
152 if (num_bytes < 0) { | |
153 #ifdef DEBUG_MOUSE | |
154 fprintf(stderr, "System error while reading from Elographics touchscreen.\n"); | |
155 #endif | |
156 return 0; | |
157 } | |
158 | |
159 while (num_bytes) { | |
160 if ((*buffer_p == 0) && (buffer[0] != ELO_START_BYTE)) { | |
161 memcpy(&buffer[0], &buffer[1], num_bytes-1); | |
162 } | |
163 else { | |
164 if (*buffer_p < ELO_PACKET_SIZE-1) { | |
165 *checksum = *checksum + buffer[*buffer_p]; | |
166 *checksum = *checksum % 256; | |
167 } | |
168 (*buffer_p)++; | |
169 } | |
170 num_bytes--; | |
171 } | |
172 | |
173 if (*buffer_p == ELO_PACKET_SIZE) { | |
174 ok = (*checksum == buffer[ELO_PACKET_SIZE-1]); | |
175 *checksum = ELO_INIT_CHECKSUM; | |
176 *buffer_p = 0; | |
177 | |
178 if (!ok) { | |
179 return 0; | |
180 } | |
181 | |
182 return 1; | |
183 } | |
184 else { | |
185 return 0; | |
186 } | |
187 } | |
188 | |
189 /* eloSendPacket | |
190 */ | |
191 | |
192 int eloSendPacket(unsigned char* packet, int fd) | |
193 { | |
194 int i, result; | |
195 int sum = ELO_INIT_CHECKSUM; | |
196 | |
197 packet[0] = ELO_START_BYTE; | |
198 for (i = 0; i < ELO_PACKET_SIZE-1; i++) { | |
199 sum += packet[i]; | |
200 sum &= 0xFF; | |
201 } | |
202 packet[ELO_PACKET_SIZE-1] = sum; | |
203 | |
204 result = write(fd, packet, ELO_PACKET_SIZE); | |
205 | |
206 if (result != ELO_PACKET_SIZE) { | |
207 #ifdef DEBUG_MOUSE | |
208 printf("System error while sending to Elographics touchscreen.\n"); | |
209 #endif | |
210 return 0; | |
211 } | |
212 else { | |
213 return 1; | |
214 } | |
215 } | |
216 | |
217 | |
218 /* eloWaitForInput | |
219 */ | |
220 int eloWaitForInput(int fd, int timeout) | |
221 { | |
222 fd_set readfds; | |
223 struct timeval to; | |
224 int r; | |
225 | |
226 FD_ZERO(&readfds); | |
227 FD_SET(fd, &readfds); | |
228 to.tv_sec = 0; | |
229 to.tv_usec = timeout; | |
230 | |
231 r = select(FD_SETSIZE, &readfds, NULL, NULL, &to); | |
232 return r; | |
233 } | |
234 | |
235 /* eloWaitReply | |
236 */ | |
237 int eloWaitReply(unsigned char type, unsigned char *reply, int fd) { | |
238 int ok; | |
239 int i, result; | |
240 int reply_p = 0; | |
241 int sum = ELO_INIT_CHECKSUM; | |
242 | |
243 i = ELO_MAX_TRIALS; | |
244 do { | |
245 ok = 0; | |
246 | |
247 result = eloWaitForInput(fd, ELO_MAX_WAIT); | |
248 | |
249 if (result > 0) { | |
250 ok = eloGetPacket(reply, &reply_p, &sum, fd); | |
251 | |
252 if (ok && reply[1] != type && type != ELO_PARAMETER) { | |
253 #ifdef DEBUG_MOUSE | |
254 fprintf(stderr, "Wrong reply received\n"); | |
255 #endif | |
256 ok = 0; | |
257 } | |
258 } | |
259 else { | |
260 #ifdef DEBUG_MOUSE | |
261 fprintf(stderr, "No input!\n"); | |
262 #endif | |
263 } | |
264 | |
265 if (result == 0) { | |
266 i--; | |
267 } | |
268 } while(!ok && (i>0)); | |
269 | |
270 return ok; | |
271 } | |
272 | |
273 | |
274 /* eloWaitAck | |
275 */ | |
276 | |
277 int eloWaitAck(int fd) { | |
278 unsigned char packet[ELO_PACKET_SIZE]; | |
279 int i, nb_errors; | |
280 | |
281 if (eloWaitReply(ELO_ACK, packet, fd)) { | |
282 for (i = 0, nb_errors = 0; i < 4; i++) { | |
283 if (packet[2 + i] != '0') { | |
284 nb_errors++; | |
285 } | |
286 } | |
287 | |
288 if (nb_errors != 0) { | |
289 #ifdef DEBUG_MOUSE | |
290 fprintf(stderr, "Elographics acknowledge packet reports %d errors\n", nb_errors); | |
291 #endif | |
292 } | |
293 return 1; | |
294 } | |
295 else { | |
296 return 0; | |
297 } | |
298 } | |
299 | |
300 | |
301 /* eloSendQuery -- | |
302 */ | |
303 int eloSendQuery(unsigned char *request, unsigned char* reply, int fd) { | |
304 int ok; | |
305 | |
306 if (eloSendPacket(request, fd)) { | |
307 ok = eloWaitReply(toupper(request[1]), reply, fd); | |
308 if (ok) { | |
309 ok = eloWaitAck(fd); | |
310 } | |
311 return ok; | |
312 } | |
313 else { | |
314 return 0; | |
315 } | |
316 } | |
317 | |
318 | |
319 /* eloSendControl | |
320 */ | |
321 int eloSendControl(unsigned char* control, int fd) { | |
322 if (eloSendPacket(control, fd)) { | |
323 return eloWaitAck(fd); | |
324 } | |
325 else { | |
326 return 0; | |
327 } | |
328 } | |
329 | |
330 /* eloInitController | |
331 */ | |
332 int eloInitController(int fd) { | |
333 unsigned char req[ELO_PACKET_SIZE]; | |
334 unsigned char reply[ELO_PACKET_SIZE]; | |
335 const char *buffer = NULL; | |
336 int result = 0; | |
337 | |
338 struct termios mouse_termios; | |
339 | |
340 /* try to read the calibration values */ | |
341 buffer = getenv("SDL_ELO_MIN_X"); | |
342 if(buffer) { | |
343 ELO_MIN_X = atoi(buffer); | |
344 } | |
345 buffer = getenv("SDL_ELO_MAX_X"); | |
346 if(buffer) { | |
347 ELO_MAX_X = atoi(buffer); | |
348 } | |
349 buffer = getenv("SDL_ELO_MIN_Y"); | |
350 if(buffer) { | |
351 ELO_MIN_Y = atoi(buffer); | |
352 } | |
353 buffer = getenv("SDL_ELO_MAX_Y"); | |
354 if(buffer) { | |
355 ELO_MAX_Y = atoi(buffer); | |
356 } | |
357 | |
358 #ifdef DEBUG_MOUSE | |
359 fprintf( stderr, "ELO calibration values:\nmin_x: %i\nmax_x: %i\nmin_y: %i\nmax_y: %i\n", | |
360 ELO_MIN_X, | |
361 ELO_MAX_X, | |
362 ELO_MIN_Y, | |
363 ELO_MAX_Y); | |
364 #endif | |
365 | |
366 /* set comm params */ | |
367 memset(&mouse_termios, 0, sizeof(mouse_termios)); | |
368 mouse_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL; | |
369 mouse_termios.c_cc[VMIN] = 1; | |
370 result = tcsetattr(fd, TCSANOW, &mouse_termios); | |
371 | |
372 if (result < 0) { | |
373 #ifdef DEBUG_MOUSE | |
374 fprintf( stderr, "Unable to configure Elographics touchscreen port\n"); | |
375 #endif | |
376 return 0; | |
377 } | |
378 | |
379 memset(req, 0, ELO_PACKET_SIZE); | |
380 req[1] = tolower(ELO_PARAMETER); | |
381 if (!eloSendQuery(req, reply, fd)) { | |
382 #ifdef DEBUG_MOUSE | |
383 fprintf( stderr, "Not at the specified rate or model 2310, will continue\n"); | |
384 #endif | |
385 } | |
386 | |
387 memset(req, 0, ELO_PACKET_SIZE); | |
388 req[1] = tolower(ELO_ID); | |
389 if (eloSendQuery(req, reply, fd)) { | |
390 #ifdef DEBUG_MOUSE | |
391 fprintf(stderr, "Ok, controller configured!\n"); | |
392 #endif | |
393 } | |
394 else { | |
395 #ifdef DEBUG_MOUSE | |
396 fprintf( stderr, "Unable to ask Elographics touchscreen identification\n"); | |
397 #endif | |
398 return 0; | |
399 } | |
400 | |
401 memset(req, 0, ELO_PACKET_SIZE); | |
402 req[1] = ELO_MODE; | |
403 req[3] = ELO_TOUCH_MODE | ELO_STREAM_MODE | ELO_UNTOUCH_MODE; | |
404 req[4] = ELO_TRACKING_MODE; | |
405 if (!eloSendControl(req, fd)) { | |
406 #ifdef DEBUG_MOUSE | |
407 fprintf( stderr, "Unable to change Elographics touchscreen operating mode\n"); | |
408 #endif | |
409 return 0; | |
410 } | |
411 | |
412 memset(req, 0, ELO_PACKET_SIZE); | |
413 req[1] = ELO_REPORT; | |
414 req[2] = ELO_UNTOUCH_DELAY; | |
415 req[3] = ELO_REPORT_DELAY; | |
416 if (!eloSendControl(req, fd)) { | |
417 #ifdef DEBUG_MOUSE | |
418 fprintf( stderr, "Unable to change Elographics touchscreen reports timings\n"); | |
419 #endif | |
420 return 0; | |
421 } | |
422 | |
423 return 1; | |
424 } | |
4
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
425 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
426 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
|
427 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
|
428 int pointer = 0; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
429 int checksum = ELO_INIT_CHECKSUM; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
430 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
431 while(pointer < ELO_PACKET_SIZE) { |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
432 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
|
433 break; |
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 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
437 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
|
438 return 0; |
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 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
441 *x = *realx; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
442 *y = *realy; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
443 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
444 eloConvertXY(this, x, y); |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
445 |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
446 return 1; |
4f6c5f021323
Date: Thu, 26 Apr 2001 10:46:23 +0200
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
447 } |