00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00050 #include <stdio.h>
00051 #include <stdlib.h>
00052 #include <string.h>
00053 #include <ctype.h>
00054 #include <unistd.h>
00055 #include <errno.h>
00056 #include <signal.h>
00057
00058 #include <sys/types.h>
00059
00060 #include <fcntl.h>
00061 #include <errno.h>
00062
00063
00064 #include <linux/input.h>
00065
00066 #ifndef EV_SYN
00067 #define EV_SYN 0
00068 #endif
00069 #include <linux/uinput.h>
00070
00071
00072 #include <sys/time.h>
00073 #include <gmp.h>
00074
00075
00076
00077
00078 #include <sys/select.h>
00079 #include <sys/stat.h>
00080
00081
00082 #include <tslib.h>
00083
00084
00085 #include "fbvncserver.h"
00086 #include "dev_uinput.h"
00087
00088
00089 #define DefaultTS "/dev/sharp_ts"
00093 #define DefaultTSCal "/etc/pointercal"
00097
00098 struct t_ts_event {
00099 long y;
00100 long x;
00101 long pressure;
00102 long long millisecs;
00103 };
00104
00105 static struct t_ts_event tsevent;
00106
00107 void write_to_input(int fd, struct t_ts_event *tsevent) {
00108 ptr_abs(fd,tsevent->x,tsevent->y);
00109 TRACE2(" [I] inputAPI - x=%d, y=%d \n",tsevent->x,tsevent->y);
00110 if ((tsevent->pressure) > 0) {
00111 button_click(fd,1);
00112 } else {
00113 button_click(fd,0);
00114 }
00115 dev_uinput_sync(fd);
00116 }
00117
00118 int write_to_fifo (char *buf, int size) {
00119 char *fname;
00120 static int fifo;
00121
00122 fname="/dev/tsvnc";
00123
00124 TRACE2(" [I] %d Bytes => fifo (fd: %d)...\n", size, fifo);
00125
00126 if(fifo<=0)
00127 if((fifo=open(fname,O_WRONLY | O_NONBLOCK))<=0) {
00128 TRACE1(" [W] unable to open fifo %s - no listeners? \n",fname);
00129 return(-1);
00130 }
00131
00132 if(size!=0 && write(fifo,buf,size)==-1 && errno==EPIPE) {
00133 close(fifo);
00134 fifo=-1;
00135 return(-1);
00136 }
00137
00138 TRACE1(" [I] sent to %s \n", fname);
00139 return(0);
00140 }
00141
00142 static char *devs[] = {
00143 "/dev/input/event0",
00144 "/dev/input/event1",
00145 "/dev/input/event2",
00146 "/dev/input/event3",
00147 NULL
00148 };
00149
00155 int node_is_sane (int fd) {
00156 int version;
00157 u_int32_t bit;
00158 u_int64_t absbit;
00159 char name[UINPUT_MAX_NAME_SIZE] = "unknown";
00160
00161 if (! ((ioctl(fd, EVIOCGVERSION, &version) >= 0) &&
00162 (version == EV_VERSION) &&
00163 (ioctl(fd, EVIOCGBIT(0, sizeof(bit) * 8), &bit) >= 0) &&
00164 (bit & (1 << EV_ABS)) &&
00165 (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit) * 8), &absbit) >= 0) &&
00166 (bit & (1 << EV_SYN)) &&
00167 (bit & (1 << EV_KEY)) &&
00168 (absbit & (1 << ABS_X)) &&
00169 (absbit & (1 << ABS_Y)) )) {
00170
00171 TRACE(" => event source did NOT pass sanity check. \n");
00172 return -1;
00173 }
00174
00175 ioctl(fd, EVIOCGNAME(sizeof(name)), name);
00176 if (strcmp(name,UINPUT_TS_NAME) != 0) {
00177 TRACE2(" [I] node name (%s) does not match (!= %s) \n", &name, UINPUT_TS_NAME);
00178 TRACE(" => event source did NOT pass sanity check. \n");
00179 return -1;
00180 }
00181
00182 TRACE (" => event source passed sanity check. \n");
00183 TRACE1(" - %s - will be used. \n",name);
00184 return 1;
00185 }
00186
00187 int vncts(int vnctsfd, struct ts_sample *samp) {
00188 struct buffer {
00189 int current_x;
00190 int current_y;
00191 int current_p;
00192
00193 struct timeval time;
00194 };
00195
00196 struct input_event ev;
00197 static struct buffer i;
00198 static int pressed = 0;
00199 int size = 0;
00200
00201 size = read(vnctsfd, &ev, sizeof(struct input_event));
00202 TRACE1(" [I] %d bytes read from uinput \n", size);
00203 if (size < (int)sizeof(struct input_event)) {
00204 if (pressed == 1) {
00205 samp->x = i.current_x;
00206 samp->y = i.current_y;
00207 samp->pressure = i.current_p;
00208 gettimeofday(&(i.time),NULL);
00209 samp->tv = i.time;
00210 return 1;
00211 } else {
00212 }
00213 }
00214
00215 switch (ev.type) {
00216 case EV_KEY:
00217 switch (ev.code) {
00218 case BTN_TOUCH:
00219 if (ev.value == 0) {
00220 samp->x = 0;
00221 samp->y = 0;
00222 samp->pressure = 0;
00223 samp->tv = ev.time;
00224 pressed = 0;
00225 return 1;
00226 } else {
00227 pressed = 1;
00228 }
00229 break;
00230 }
00231 break;
00232 case EV_SYN:
00233 samp->x = i.current_x;
00234 samp->y = i.current_y;
00235 samp->pressure = i.current_p;
00236 i.time = ev.time;
00237 samp->tv = ev.time;
00238 if (i.current_p > 0) {
00239 pressed = 1;
00240 } else {
00241 pressed = 0;
00242 }
00243 return 1;
00244 break;
00245 case EV_ABS:
00246 switch (ev.code) {
00247 case ABS_X:
00248 i.current_x = ev.value;
00249 break;
00250 case ABS_Y:
00251 i.current_y = ev.value;
00252 break;
00253 case ABS_PRESSURE:
00254 i.current_p = ev.value;
00255 break;
00256 }
00257 break;
00258 }
00259
00260 return -1;
00261 }
00262
00267 void display_help(char* arg0) {
00268 printf("%s: error !\n",arg0);
00269 #ifdef DEBUG
00270 printf("Usage: %s [-inputAPI] [-debug] ",arg0);
00271 #else
00272 printf("Usage: %s [-inputAPI] ",arg0);
00273 #endif
00274 printf("\n");
00275 printf(" -input: send TS events to input API \n");
00276 #ifdef DEBUG
00277 printf(" -debug \n\n");
00278 #endif
00279 };
00280
00281 int main(int argc, char **argv) {
00282 struct tsdev *ts;
00283
00284 struct linear {
00285 int swap_xy;
00286
00287
00288 int p_offset;
00289 int p_mult;
00290 int p_div;
00291
00292
00293 mpf_t a[7];
00294 };
00295
00296 char *tsdev;
00297 char *calfile=NULL;
00298 char *tokptr;
00299 char pcalbuf[200];
00300
00301 int hwtsfd = 0,
00302 vnctsfd = 0,
00303
00304 pcal_fd = 0,
00305
00306 inputAPIfd = 0;
00307
00308 fd_set fds;
00309
00310 struct linear lin;
00311 struct stat sbuf;
00312 struct timeval tv;
00313
00314 int vnctssane = 0,
00315 inputAPI = 0,
00316 index = 0, i = 0, retval = 0;
00317
00318
00319
00320
00321 if( (tsdev = getenv("TSLIB_TSDEVICE")) == NULL) tsdev = strdup (DefaultTS);
00322 if( (calfile = getenv("TSLIB_CALIBFILE")) == NULL) calfile = strdup (DefaultTSCal);
00323
00324 mpf_t b[9];
00325 mpf_t c[6];
00326 mpf_t mpf_helper1, mpf_helper2;
00327
00328 mpf_init(lin.a[0]);
00329 mpf_init(lin.a[1]);
00330 mpf_init(lin.a[2]);
00331 mpf_init(lin.a[3]);
00332 mpf_init(lin.a[4]);
00333 mpf_init(lin.a[5]);
00334 mpf_init(lin.a[6]);
00335
00336 printf("%s (%s %s) \n",PACKAGE_STRING,__DATE__, __TIME__ );
00337
00338
00339
00340 for(i=1;i<argc;i++) {
00341 if(!strcmp(argv[i],"-h") ||
00342 !strcmp(argv[i],"-?") ||
00343 !strcmp(argv[i],"/?") ||
00344 !strcmp(argv[i],"-help") ||
00345 !strcmp(argv[i],"--help")) { display_help(argv[0]); return(-1); }
00346 else if(!strcmp(argv[i],"-inputAPI")) { inputAPI = 1;}
00347 #ifdef DEBUG
00348 else if(!strcmp(argv[i],"-debug")) { debug = 1;}
00349 #endif
00350 }
00351
00352 TRACE1(" [I] %s will be used as HW TS event source \n",tsdev);
00353 TRACE1(" [I] %s will be used to calculate raw frames \n", calfile);
00354
00355
00356
00357
00358 ts = ts_open(tsdev,0);
00359 if (!ts) {
00360 perror("ts_open");
00361 exit(1);
00362 }
00363 TRACE(" [I] HW TS open ...\n");
00364 if (ts_config(ts)) {
00365 perror("ts_config");
00366 exit(1);
00367 }
00368 TRACE(" [I] HW TS configured ... \n");
00369 hwtsfd = ts_fd(ts);
00370 TRACE1(" [I] HW TS FD: %d\n", hwtsfd);
00371
00372
00373
00374
00375 i=0;
00376 while (devs[i] != NULL) {
00377 TRACE1(" [I] %s ... ",devs[i]);
00378 vnctsfd = open(devs[i++], O_RDONLY | O_NONBLOCK);
00379 if (vnctsfd > 0) {
00380 if ((node_is_sane(vnctsfd)) > 0) {
00381 vnctssane = 1;
00382 break;
00383 }
00384 } else {
00385 TRACE(" - not present. \n");
00386 }
00387 }
00388
00389
00390
00391 if (inputAPI) {
00392 inputAPIfd = dev_uinput_init_mouse(UINPUT_INPUTAPI_NAME);
00393 if (inputAPIfd < 1) {
00394 TRACE(" [F] unable to create a new uinput node for the merged TS \n");
00395 perror("dev_uinput_init_mouse");
00396 exit(1);
00397 }
00398 TRACE(" [I] we'll use inputAPI ... \n");
00399 }
00400
00401
00402
00403
00404
00405 mpf_set_si(lin.a[0],1);
00406 mpf_set_si(lin.a[1],0);
00407 mpf_set_si(lin.a[2],0);
00408 mpf_set_si(lin.a[3],0);
00409 mpf_set_si(lin.a[4],1);
00410 mpf_set_si(lin.a[5],0);
00411 mpf_set_si(lin.a[6],1);
00412
00413 lin.p_offset = 0;
00414 lin.p_mult = 1;
00415 lin.p_div = 1;
00416 lin.swap_xy = 0;
00417
00418 if(stat(calfile,&sbuf)==0) {
00419 pcal_fd = open(calfile,O_RDONLY);
00420 read(pcal_fd,pcalbuf,200);
00421 mpf_set_si(lin.a[0],atoi(strtok(pcalbuf," ")));
00422 index=1;
00423 while(index<7) {
00424 tokptr = strtok(NULL," ");
00425 if(*tokptr!='\0') {
00426 mpf_set_si(lin.a[index],atoi(tokptr));
00427 index++;
00428 }
00429 }
00430 }
00431
00432 signal(SIGPIPE,SIG_IGN);
00433
00434
00435
00436
00437
00438 mpf_init(mpf_helper1);
00439 mpf_init(mpf_helper2);
00440
00441 for(index=0;index<9;index++) mpf_init(b[index]);
00442 for(index=0;index<6;index++) mpf_init(c[index]);
00443
00444 mpf_neg(mpf_helper1,lin.a[1]);
00445 mpf_mul(b[0],mpf_helper1,lin.a[6]);
00446 mpf_mul(b[1],lin.a[4],lin.a[6]);
00447 mpf_mul(b[2],lin.a[1],lin.a[5]);
00448 mpf_mul(b[3],lin.a[2],lin.a[4]);
00449 mpf_mul(mpf_helper1,lin.a[1],lin.a[3]);
00450 mpf_mul(mpf_helper2,lin.a[0],lin.a[4]);
00451 mpf_sub(b[4],mpf_helper1,mpf_helper2);
00452 mpf_neg(mpf_helper1,lin.a[0]);
00453 mpf_mul(b[5],mpf_helper1,lin.a[6]);
00454 mpf_mul(b[6],lin.a[3],lin.a[6]);
00455 mpf_mul(b[7],lin.a[0],lin.a[6]);
00456 mpf_mul(b[8],lin.a[2],lin.a[3]);
00457
00458 mpf_div(c[0],b[0],b[4]);
00459 mpf_div(c[1],b[1],b[4]);
00460 mpf_sub(mpf_helper1,b[2],b[3]);
00461 mpf_div(c[2],mpf_helper1,b[4]);
00462 mpf_div(c[3],b[5],b[4]);
00463 mpf_div(c[4],b[6],b[4]);
00464 mpf_sub(mpf_helper1,b[7],b[8]);
00465 mpf_div(c[5],mpf_helper1,b[4]);
00466
00467 #ifdef DEBUG
00468 if (debug) {
00469
00470
00471
00472
00473
00474
00475
00476 TRACE(" [I] raw equations: \n")
00477 gmp_printf(" => rawx = %Ff * y + %Ff * x + %Ff \n", c[0],c[1], c[2]);
00478 gmp_printf(" => rawy = %Ff * y + %Ff * x + %Ff \n", c[3],c[4],c[5]);
00479 }
00480 #endif
00481
00482
00483 while (1) {
00484 struct ts_sample samp;
00485
00486 FD_ZERO(&fds);
00487 FD_SET(hwtsfd,&fds);
00488
00489 if (vnctssane == 1) {
00490 FD_SET(vnctsfd,&fds);
00491 } else {
00492 TRACE(" [W] vnc ts events will not be processed => transparent mode. \n");
00493 }
00494 tv.tv_sec = 5; tv.tv_usec = 0;
00495 retval = select(FD_SETSIZE,&fds,NULL,NULL,&tv);
00496 switch (retval) {
00497 case EBADF:
00498 TRACE(" [W] An invalid file descriptor was given in one of the sets. \n");
00499 break;
00500 case EINTR:
00501 TRACE(" [W] A non blocked signal was caught. \n");
00502 break;
00503 case EINVAL:
00504 TRACE(" [W] n is negative or the value contained within timeout is invalid. \n");
00505 break;
00506 case ENOMEM:
00507 TRACE(" [W] select() was unable to allocate memory for internal tables. \n");
00508 break;
00509 case 0:
00510
00511
00512 break;
00513 case 1:
00514 TRACE(" [I] event catched ... ");
00515 if (FD_ISSET(hwtsfd,&fds)) {
00516 TRACE(" [- HW -] \n");
00517 retval = ts_read_raw(ts,&samp,1);
00518 if (retval < 0) {
00519 perror("ts_read_raw");
00520 exit;
00521 }
00522
00523 tsevent.y = samp.y;
00524 tsevent.x = samp.x;
00525 tsevent.pressure = samp.pressure;
00526 tsevent.millisecs = ((samp.tv.tv_sec * 1000) + samp.tv.tv_usec);
00527
00528 write_to_fifo((char*) &tsevent,sizeof(tsevent));
00529 }
00530 if (vnctssane == 1) {
00531 if (FD_ISSET(vnctsfd,&fds)) {
00532 TRACE(" [- VNC -] \n");
00533 if (vncts(vnctsfd,&samp) == 1) {
00534 mpf_t tmpy, tmpx;
00535 mpf_init(tmpx);
00536 mpf_init(tmpy);
00537
00538
00539 mpf_set_si(mpf_helper1,samp.x);
00540 mpf_set_si(mpf_helper2,samp.y);
00541 mpf_mul(mpf_helper2,c[0],mpf_helper2);
00542 mpf_mul(mpf_helper1,c[1],mpf_helper1);
00543 mpf_add(tmpx,mpf_helper1,mpf_helper2);
00544 mpf_add(tmpx,tmpx,c[2]);
00545
00546
00547 mpf_set_si(mpf_helper1,samp.x);
00548 mpf_set_si(mpf_helper2,samp.y);
00549 mpf_mul(mpf_helper2,c[3],mpf_helper2);
00550 mpf_mul(mpf_helper1,c[4],mpf_helper1);
00551 mpf_add(tmpy,mpf_helper1,mpf_helper2);
00552 mpf_add(tmpy,tmpy,c[5]);
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 tsevent.y = mpf_get_si(tmpy);
00577 tsevent.x = -mpf_get_si(tmpx);
00579 #ifdef DEBUG
00580 if (debug) {
00581 gmp_printf(" [I] x: %d, y: %d \n", samp.x,samp.y);
00582 gmp_printf(" [I] rawx: %d, rawy: %d \n", tsevent.x, tsevent.y);
00583 }
00584 #endif
00585 tsevent.pressure = samp.pressure;
00586 tsevent.millisecs = ((samp.tv.tv_sec * 1000) + samp.tv.tv_usec);
00587
00588 if (!inputAPI) {
00589 write_to_fifo((char*) &tsevent,sizeof(tsevent));
00590 } else {
00591 write_to_input(inputAPIfd,&tsevent);
00592 }
00593 }
00594 }
00595 }
00596 break;
00597 }
00598 }
00599 }