/* Howto compile: gcc -o voht voht.c * To use: * gpm -t ps2 -m /dev/psaux -M -t ps2 -m /dev/voht -R msc * repeats on /dev/gpmdata input from both ps2 port and this program * and set XF86Config: protocol type to "MouseSystems" and * set XF86Config: device to /dev/gpmdata */ #include #include #include #include #include #include #include #include /* usually the parameters fall in this range when estpchirp2m worked */ #define LOWER_THRESHOLD -1.5 #define UPPER_THRESHOLD 1.5 void usage() { fprintf(stderr,"Use: Reads 8 projective chirp parameters from stdin\n" " and moves the mouse accordingly by writing ps2\n" " protocol data on /dev/voht. Parameters are\n" " relative to last frame\n"); } void calc_motion( double *x, double *y, float *params, double *delta_x, double *delta_y); void motion_to_ps2( double delta_x, double delta_y, unsigned char *ps2_out); //static void ser_read (int fd, unsigned char *bytes, int count); int main( int argc, char *argv[] ) { int fifo; int voht_pin_fifo; unsigned char ps2_output_bytes[3]; int i=0; int exit_flag = 0; double x, y, delta_x, delta_y; /* x and y as orbits coords!!*/ fd_set rfds; float pchirp_parameters[8]; x=0.5, y=0,5; if( argc == 2 ) { usage(); exit(1); } /* open the fifo for writing */ fifo = open("/dev/voht", O_WRONLY); if( fifo == -1 ) { perror("open"); exit(1); } /* open the fifo for reading */ //voht_pin_fifo = open("/dev/voht_pin", O_RDONLY | O_SYNC); /* RDWR seems to keep it from looping too much */ voht_pin_fifo = open("/dev/voht_pin", O_RDWR | O_SYNC); if( voht_pin_fifo == -1 ) { perror("open");exit(1); } FD_ZERO(&rfds); FD_SET(voht_pin_fifo, &rfds); while(1) { char buffer[1024]; int j=0; /* scan and verify input parameters */ while( select( voht_pin_fifo+1, &rfds, NULL, NULL, NULL)==1) { read( voht_pin_fifo, &(buffer[j++]), 1); printf("got %c\n", buffer[j-1]); if( !isalnum(buffer[j-1] ) && buffer[j-1] != '1' ) break; } //if(scanf("%f", &(pchirp_parameters[i]))==0) continue; sscanf(buffer, "%f", &(pchirp_parameters[i])); printf("%f read\n", pchirp_parameters[i]); if( isnan(pchirp_parameters[i]) ) exit_flag = 1; if( pchirp_parameters[i] > UPPER_THRESHOLD || pchirp_parameters[i] < LOWER_THRESHOLD ) { exit_flag = 1; fprintf(stderr, "Crazy big parameters read, ignoring!!\n"); } // if( exit_flag == 1) exit(1); if( exit_flag == 1) continue; calc_motion(&x, &y, pchirp_parameters, &delta_x, &delta_y); motion_to_ps2(delta_x, delta_y,ps2_output_bytes); printf("sending chars!\n"); fflush(stdout); write(fifo, ps2_output_bytes, 3); } } /* if we knew the resolution of the monitor/screen and how * much fov the HMD takes up on it, then we could actually * do a calulation here, but for now, do something perty */ /* ps2 goes from -127:1:127 */ #define RANDOM_FUDGE_FACTOR 127 /* based on some motion, calculate some ps2 output */ void motion_to_ps2( double delta_x, double delta_y, unsigned char *ps2_out) { int dx, dy; dx = delta_x * RANDOM_FUDGE_FACTOR; dy = delta_y * RANDOM_FUDGE_FACTOR; //assert(dy >= -127 && dy < 127 && dx >= -127 && dx < 127 ); fprintf(stderr, "Motion dx = %d, dy = %d\n", dx, dy ); /* flip x/y orbits -> x/y ps2 motion convention */ ps2_out[0] = (char)0x00; ps2_out[1] = (char)dy; ps2_out[2] = (char)dx; } /* calculate the new position of the coordinates by applying the projective coordinate transformation with the parameters as determined by estpchirp2m locally, x is up/down, y is left/right */ void calc_motion( double *x, double *y, float *params, double *delta_x, double *delta_y) { double last_x, last_y; double A_11, A_12, A_21, A_22, b_1, b_2, c_1, c_2, denom; last_x = *x; last_y = *y; A_11 = params[0]; A_12 = params[1]; b_1 = params[2]; A_21 = params[3]; A_22 = params[4]; b_2 = params[5]; c_1 = params[6]; c_2 = params[7]; denom = (c_1*last_x + c_2*last_y + 1); /* update x and y as in screen coords!! */ *x = (A_11*last_x + A_12*last_y + b_1) / denom; *y = (A_21*last_x + A_22*last_y + b_2) / denom; *delta_x = *x - last_x; *delta_y = *y - last_y; /* inverse proj coord trans */ /* denom = (last.x*c_1-A_11)*(last.y*c_2-A_22)-A_21*A_12+A_21*c_2*last.x+ last.y*c_1*A_12-last.y*c_1*c_2*last.x; pos->y = A_21*b_1 - A_21*last.x - (last.y*c_1)*(b_1 - last.x) + (last.x*c_1-A_11)* (b_2-last.y); pos->y = pos->y/denom; pos->x = (A_12*pos->y + b_1 - c_2*pos->y*last.x - last.x)/ (last.x*c_1 - A_11); */ } /* static void ser_read (int fd, unsigned char *bytes, int count) { struct timeval tv; fd_set rfds; int num_read = 0; int read_count; FD_ZERO (&rfds); FD_SET (fd, &rfds); tv.tv_sec = 1; tv.tv_usec = 0; while ((select (fd+1, &rfds, NULL, NULL, &tv) == 1) && (num_read < count)) { read_count = read (fd, &bytes [num_read], count - num_read); num_read += read_count; FD_ZERO (&rfds); FD_SET (fd, &rfds); } for (; num_read < count; num_read++) { bytes [num_read] = '\0'; } } */