//see http://nexno.blogspot.com/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <getopt.h>
#include <sys/types.h>
#include <ctype.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XTest.h>
#define BUFSIZE 256
#define DATASIZE 6
int serialport_init(const char* serialport, int baud);
int main(int argc, char *argv[]){
Display *display;
Window root;
Window fromroot, tmpwin;
if((display = XOpenDisplay(NULL)) == NULL) {
fprintf(stderr, "Cannot open local X-display.\n");
exit(1);
}
root = DefaultRootWindow(display);
const char *sep = ";";
char line[BUFSIZE];
int data[DATASIZE];
char *token;
char *ptr;
int i=0;
int x, y, tmp;
unsigned int tmp2;
long altmodecnt=0;
int last_lbtn=0;
int last_rbtn=0;
int fd = 0;
if((fd = serialport_init("/dev/ttyUSB0", 19200)) == -1) {
exit(1);
}
FILE *sp;
sp = fdopen(fd, "r");
while(1){
while(fgets(line, BUFSIZE, sp) != NULL ){
i = 0;
if(*line != '\0') line[strlen(line)-1] = '\0';
//printf("%s\n",line); //DEBUG
if((token = strtok_r(line, sep, &ptr)) != NULL) {
data[i++] = atoi(token);
while(( token = strtok_r(NULL, sep, &ptr)) != NULL && i < DATASIZE)
data[i++] = atoi(token);
}
if(i == DATASIZE){
//printf("%i,%i,%i,%i,%i,%i\n",data[0],data[1],data[2],data[3],data[4],(90-data[5])); //DEBUG
if(data[4]>140 || data[4]<-140){
altmodecnt++;
//printf("alternative mode\n"); //DEBUG
if(data[1]>20 && altmodecnt%8==0){ //ZOOM (Compiz Super&Plus)
XTestFakeKeyEvent(display, 133, True, 0);
XTestFakeKeyEvent(display, 35, True, 0);
XTestFakeKeyEvent(display, 35, False, 0);
XTestFakeKeyEvent(display, 133, False, 0);
XFlush(display);
}else if(data[1]<-20 && altmodecnt%8==0){ //ZOOM (Compiz Super&Minus)
XTestFakeKeyEvent(display, 133, True, 0);
XTestFakeKeyEvent(display, 61, True, 0);
XTestFakeKeyEvent(display, 61, False, 0);
XTestFakeKeyEvent(display, 133, False, 0);
XFlush(display);
}
if(data[0]>20 && altmodecnt%10==0){ //Volume controll
system("amixer -c 0 set Master 1%-");
}else if(data[0]<-20 && altmodecnt%10==0){
system("amixer -c 0 set Master 1%+");
}
continue;
}
XQueryPointer(display, root, &fromroot, &tmpwin, &x, &y, &tmp, &tmp, &tmp2);
XWarpPointer(display, None, root, 0, 0, 0, 0, x+(data[0]/2), y+((-1)*data[1]/2));
// NORMAL MOUSE BUTTON USAGE
if( data[2] != last_lbtn ){
last_lbtn = !last_lbtn;
XTestFakeButtonEvent(display, 1, last_lbtn==1?True:False, 0);
}
if( data[3] != last_rbtn ){
last_rbtn = !last_rbtn;
XTestFakeButtonEvent(display, 3, last_rbtn==1?True:False, 0);
}
XFlush(display);
}
//else printf("bad data %i\n",i);
}
usleep(1000*50);
}
return 0;
}
// takes the string name of the serial port (e.g. "/dev/tty.usbserial","COM1")
// and a baud rate (bps) and connects to that port at that speed and 8N1.
// opens the port in fully raw mode so you can send binary data.
// returns valid fd, or -1 on error
int serialport_init(const char* serialport, int baud){
struct termios toptions;
int fd;
fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1){
perror("init_serialport: Unable to open port ");
return -1;
}
if (tcgetattr(fd, &toptions) < 0) {
perror("init_serialport: Couldn't get term attributes");
return -1;
}
speed_t brate = baud; // let you override switch below if needed
switch(baud) {
case 4800: brate=B4800; break;
case 9600: brate=B9600; break;
case 19200: brate=B19200; break;
case 38400: brate=B38400; break;
case 57600: brate=B57600; break;
case 115200: brate=B115200; break;
default: brate=B9600;
}
cfsetispeed(&toptions, brate);
cfsetospeed(&toptions, brate);
toptions.c_cflag &= ~PARENB; // 8N1
toptions.c_cflag &= ~CSTOPB; // 8N1
toptions.c_cflag &= ~CSIZE; // 8N1
toptions.c_cflag |= CS8; // 8N1
toptions.c_cflag &= ~CRTSCTS; // no flow control
toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
toptions.c_oflag &= ~OPOST; // make raw
// see: http://unixwiz.net/techtips/termios-vmin-vtime.html
toptions.c_cc[VMIN] = 0;
toptions.c_cc[VTIME] = 20;
if( tcsetattr(fd, TCSANOW, &toptions) < 0) {
perror("init_serialport: Couldn't set term attributes");
return -1;
}
return fd;
}
/*
//And here is the Arduino-Code
#include <math.h>
#include <Wire.h>
#include <WiiChuck.h>
#define MAXANGLE 90
#define MINANGLE -90
WiiChuck chuck = WiiChuck();
int angleStart, currentAngle;
int tillerStart = 0;
double angle;
void setup() {
Serial.begin(19200);
chuck.begin();
chuck.update();
chuck.calibrateJoy();
}
void loop() {
delay(20);
chuck.update();
Serial.print((int)chuck.readJoyX());
Serial.print(";");
Serial.print((int)chuck.readJoyY());
Serial.print(";");
Serial.print((int)chuck.zPressed());
Serial.print(";");
Serial.print((int)chuck.cPressed());
Serial.print(";");
Serial.print((int)chuck.readRoll());
Serial.print(";");
Serial.print((int)chuck.readPitch());
Serial.print("\n");
}
// Plus this little modification in the WiiChuck.h
boolean zPressed() {
//return (buttonZ && ! lastZ);
return buttonZ;
}
boolean cPressed() {
//return (buttonC && ! lastC);
return buttonC;
}
*/