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