/* * touchscreen.c * * Copyright 2015 Michel GRIMALDI * * allow to control X mouse events from an eleduino 7" touch screen * * release 1.01 - 19-02-2016 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // The payload structure sent each time the touchscreen is touched, moved or released // header1=aa, x, y, header2=bb, multitouch flag, x2, y2, x3, y3, x4, y4, x5, y5, terminator=cc // an hex dump bellow // aa 01 01 c2 01 1f bb 01 01 e0 03 20 01 e0 03 20 01 e0 03 20 01 e0 03 20 cc typedef struct { unsigned char header1; // aa unsigned char touch; uint8_t xh; // first touch position uint8_t xl; uint8_t yh; uint8_t yl; unsigned char header2; // bb unsigned char multitouch; uint8_t xh2; // second touch position uint8_t xl2; uint8_t yh2; uint8_t yl2; uint8_t xh3; // third touch position uint8_t xl3; uint8_t yh3; uint8_t yl3; uint8_t xh4; // fourth touch position uint8_t xl4; uint8_t yh4; uint8_t yl4; uint8_t xh5; // fifth touch position uint8_t xl5; uint8_t yh5; uint8_t yl5; unsigned char terminator; // cc } HidEleduinoPayload; #define SIMPLE_CLICK (0.1*CLOCKS_PER_SEC) // global variables Display *display ; // the X terminal display Window root_window; // the root system Window // mouse move pointer function int mouseMove(int x, int y){ if(display == NULL)return -1; XWarpPointer(display, None, root_window, 0, 0, 0, 0, x, y); XFlush(display); return 0; } // mouse click function int mouseClick(int button){ if(display == NULL)return -1; // Create and setting up the event XEvent event; memset (&event, 0, sizeof (event)); event.xbutton.button = button; event.xbutton.same_screen = False; event.xbutton.subwindow = DefaultRootWindow (display); while (event.xbutton.subwindow) { event.xbutton.window = event.xbutton.subwindow; XQueryPointer (display, event.xbutton.window, &event.xbutton.root, &event.xbutton.subwindow, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state); } // Press event.type = ButtonPress; if (XSendEvent (display, PointerWindow, True, ButtonPressMask, &event) == 0)return -2; XFlush (display); //printf("mouse down\n"); return 0; } // mouse release function int mouseRelease(int button){ XEvent event; if(display == NULL)return -1; memset(&event, 0x00, sizeof(event)); event.type = ButtonRelease; event.xbutton.button = button; event.xbutton.same_screen = False; event.xbutton.state = 1<<(7+button); // get the root window pointer if (!XQueryPointer(display, RootWindow(display, DefaultScreen(display)), &event.xbutton.root, &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state)) return -2; event.xbutton.subwindow = event.xbutton.window; while(event.xbutton.subwindow) { event.xbutton.window = event.xbutton.subwindow; XQueryPointer(display, event.xbutton.window, &event.xbutton.root, &event.xbutton.subwindow, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state); } if(XSendEvent(display, PointerWindow, True, 0xfff, &event) == 0) return -3; XFlush(display); //printf("mouse up\n"); return 0; } // get time in milliseconds uint32_t millis(){ struct timeval tv; gettimeofday(&tv, NULL); return (uint32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000) ; // convert tv_sec & tv_usec to millisecond } //______________________________________________________________________ // MAIN PROG int main(int argc, char **argv) { HidEleduinoPayload data; // a hid driver payload int xloc, yloc; // touch position int xloc2, yloc2; // second touch position (multitouch) int multitouch; // used for right click int thresholdTimeClick=200; // the duration between a touch and release sequence // to consider it as a click in milliseconds uint32_t now; // the current time stamp in millis uint32_t clTouch1, clRelease1; // first touch/release time stamp uint32_t holdTime; // the time on which the screen is touched //uint32_t clTouch2, clRelease2; // second touch/release time stamp char ch; // a char // verify the name of the driver hidraw0 or hidraw1 or ... char hidDriverName[50] = "/dev/"; if (argc!=2){ printf("Usage:\n"); printf("touchscreen driver\n"); printf("avec driver= hidraw0 | hidraw1 | hidrawx ... | touchscreen\n"); return 0; } strcat(hidDriverName, argv[1]); // the touchscreen hid driver int state; // init th state machine display = XOpenDisplay(NULL); // connect to X server if(display == NULL) { fprintf(stderr, "cannot find X Display\n"); exit(EXIT_FAILURE); } // get the system display root_window = XRootWindow(display, 0); XSelectInput(display, root_window, NoEventMask); // open hidraw eleduino touchscreen device FILE *fraw = fopen(hidDriverName,"r"); if (fraw==NULL) { fprintf(stderr, "Unable to open %s (perhaps you don't have the good rights!)\n", hidDriverName); return -1; } printf("driver installed on %s\n", hidDriverName); state=0; holdTime=0; for ( ; ; ){ // super loop // a touchscreen event append fread(&data, sizeof(HidEleduinoPayload), 1, fraw); // read the touch payload //printf("%x %x %x %x %x\n", data.header1, data.xl, data.xh, data.yl, data.yh); if (data.header1!=0xaa || data.header2!=0xbb ) { printf("HID touchscreen driver frame error!\n"); for (ch=0 ; ch!=0xcc ; )fread(&ch, 1, 1, fraw); // look for the terminator continue; } // swap the endian xloc = data.xl+256*data.xh; yloc = data.yl+256*data.yh; xloc2 = data.xl2+256*data.xh2; yloc2 = data.yl2+256*data.yh2; //printf("s=%d (%d, %d,%c), (%x, %d, %d)\n", state, xloc, yloc, (data.touch ? 'T':'F'), // data.multitouch, xloc2, yloc2); now = millis(); // now time stamp if (data.touch){ // every time screen is thouched, move the pointer multitouch = data.multitouch>1; // ? multitouch mouseMove(xloc, yloc); // move it } switch (state) { case 0 :if (data.touch){ // screen is touched clTouch1 = now; // time stamp state=1; // wait for release } break; case 1 : if (!data.touch){ // screen is released clRelease1 = now; // time stamp //printf("time stamps : %d %d %d\n",clTouch1, clRelease1, (clRelease1-clTouch1)); if (clRelease1-clTouch11000){ // maintain click mouseClick((multitouch ? Button2 : Button1)); // right or left button state=2; } } break; case 2 : if (!data.touch){ // screen is released mouseRelease((multitouch ? Button2 : Button1)); state=0; } } } // close X server XFlush(display); XCloseDisplay(display); fclose(fraw); return 0; }