/* * Beryl/Compiz WiiMote Interface *--------------------------------------- * Copyright (C) 2007, Bruno "PhoenixBF" * * Version 0.1 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ // Indirizzo del Wii-Mote !! #define MY_WIIMOTE_ADDR "00:19:1D:95:XX:XX" // Debug messages //#define PRINT_STATS #define ON 1 #define OFF 0 #define X_AXIS 0 #define Y_AXIS 1 #define Z_AXIS 2 #include #include #include #include #include #include #include #include #include "wiimote.h" #include "wiimote_api.h" // Functions static int uinput_init(const char *); static void insertEvent(int, unsigned short, unsigned short, int); static void inputEvent(int, unsigned short, int); void eventPress(unsigned short); void eventRelease(unsigned short); void initSounds(); // Globals int uifd = -1; float wiiTiltOffsets[3] = { 0.0f, 0.0f, 0.0f }; // tilt offsets float PitchSens = 40.0f; #define MAX_SOUNDS 16 enum { SOUND_EXIT = 0, SOUND_SHOWDESKTOP, SOUND_SCALE, SOUND_ROTATECUBELEFT, SOUND_ROTATECUBERIGHT, SOUND_SWITCH }; unsigned char PlayingSound[MAX_SOUNDS]; // MAIN PROGRAM int main(int argc, char **argv) { wiimote_t wiimote = WIIMOTE_INIT; wiimote_report_t report = WIIMOTE_REPORT_INIT; initSounds(); unsigned char modifier = OFF; unsigned char face = 1; unsigned char calibrated = OFF; unsigned char playingsound = OFF; unsigned char onPitch = OFF; uifd = uinput_init("/dev/input/uinput"); if (uifd<0) { perror("uinput"); return -1; } printf("Press buttons 1 and 2 on the wiimote now to connect.\n"); /* Connect the wiimote specified on the command line. */ if (wiimote_connect(&wiimote, MY_WIIMOTE_ADDR) < 0) { fprintf(stderr, "unable to open wiimote: %s\n", wiimote_get_error()); exit(1); } printf("WiiMote Connected!! ADDRESS: %s\n",MY_WIIMOTE_ADDR); /* Activate the first led on the wiimote. It will take effect on the next call to wiimote_update. */ //wiimote.led.one = ON; wiimote.led.bits = 1; wiimote.mode.acc = ON; while (wiimote_is_open(&wiimote)) { //system("clear"); wiimote.led.bits = face; /* The wiimote_update function is used to synchronize the wiimote object with the real wiimote. It should be called as often as possible in order to minimize latency. */ if (wiimote_update(&wiimote) < 0) { wiimote_disconnect(&wiimote); break; } /* The wiimote object has member 'keys' which keep track of the current key state. */ if (wiimote.keys.home) { wiimote_disconnect(&wiimote); if (!PlayingSound[SOUND_EXIT]){ system("playsound ok.wav"); PlayingSound[SOUND_EXIT]=ON; } } #if 0 if (!calibrated){ if (!isnan(wiimote.tilt.x)) wiiTiltOffsets[0] = - wiimote.tilt.x; if (!isnan(wiimote.tilt.y)) wiiTiltOffsets[1] = - wiimote.tilt.y; if (!isnan(wiimote.tilt.z)) wiiTiltOffsets[2] = - wiimote.tilt.z; printf("INIT Calibration Completed.\nOffsets = (X: %.3f, Y: %.3f, Z: %.3f)\n",wiiTiltOffsets[0],wiiTiltOffsets[1],wiiTiltOffsets[2]); calibrated = ON; } #endif /* Prepare and send a status report request. */ #if 0 if (wiimote.keys.one) { /* report.channel = WIIMOTE_RID_STATUS; if (wiimote_report(&wiimote, &report, sizeof (report.status)) < 0) { wiimote_perror("unable to get status report"); } */ if (modifier){ //eventPress(KEY_TAB); //if (!PlayingSound[SOUND_SWITCH]){ system("playsound switch.mp3 &"); PlayingSound[SOUND_SWITCH]=ON; } } else eventPress(KEY_LEFTSHIFT); } else if (!wiimote.keys.one){ if (modifier){ //eventRelease(KEY_TAB); //PlayingSound[SOUND_SWITCH] = OFF; } else eventRelease(KEY_LEFTSHIFT); } #endif if (wiimote.keys.two){ //if (SystemStatus){ SystemStatus = OFF; eventPress(KEY_SLEEP); } //else { SystemStatus = ON; eventPress(KEY_WAKEUP); } if (modifier){ if (!isnan(wiimote.tilt.x)) wiiTiltOffsets[0] = - wiimote.tilt.x; if (!isnan(wiimote.tilt.y)) wiiTiltOffsets[1] = - wiimote.tilt.y; if (!isnan(wiimote.tilt.z)) wiiTiltOffsets[2] = - wiimote.tilt.z; printf("Calibration Completed. Offsets = (%.3f,%.3f,%.3f)\n",wiiTiltOffsets[0],wiiTiltOffsets[1],wiiTiltOffsets[2]); } // App Switcher if (wiimote.keys.one){ eventPress(KEY_TAB); if (!PlayingSound[SOUND_SWITCH]){ system("playsound switch.mp3 &"); PlayingSound[SOUND_SWITCH]=ON; } } else if (!wiimote.keys.one){ eventRelease(KEY_TAB); PlayingSound[SOUND_SWITCH] = OFF; } } /* Activate modifier */ if (wiimote.keys.b) { modifier = ON; //eventPress(KEY_LEFTSHIFT); //wiimote.mode.ir = 1; } else if (!wiimote.keys.b){ modifier = OFF; //eventRelease(KEY_LEFTSHIFT); //wiimote.mode.ir = 0; } if (wiimote.keys.a) { // Show Desktop if (modifier){ eventPress(KEY_F6); if (!PlayingSound[SOUND_SHOWDESKTOP]){ system("playsound taaught.wav &"); PlayingSound[SOUND_SHOWDESKTOP] = ON; } } // Scale windows else { eventPress(KEY_F8); if (!PlayingSound[SOUND_SCALE]){ system("playsound scale.mp3 &"); PlayingSound[SOUND_SCALE] = ON; } } } else if (!wiimote.keys.a){ if (modifier){ eventRelease(KEY_F6); PlayingSound[SOUND_SHOWDESKTOP] = OFF; } else { eventRelease(KEY_F8); PlayingSound[SOUND_SCALE] = OFF; } } /* Adjust master Volume on + and - wiimote keys */ if (wiimote.keys.plus) eventPress(KEY_VOLUMEUP); else if (!wiimote.keys.plus) eventRelease(KEY_VOLUMEUP); if (wiimote.keys.minus) eventPress(KEY_VOLUMEDOWN); else if (!wiimote.keys.minus) eventRelease(KEY_VOLUMEDOWN); // CUBE ROTATE !! if (wiimote.keys.up) { eventPress(KEY_LEFTCTRL); eventPress(KEY_LEFTALT); eventPress(KEY_UP); } else if (!wiimote.keys.up){ eventRelease(KEY_LEFTCTRL); eventRelease(KEY_LEFTALT); eventRelease(KEY_UP); } if (wiimote.keys.down) { eventPress(KEY_LEFTCTRL); eventPress(KEY_LEFTALT); eventPress(KEY_DOWN); } else if (!wiimote.keys.down){ eventRelease(KEY_LEFTCTRL); eventRelease(KEY_LEFTALT); eventRelease(KEY_DOWN); } if (wiimote.keys.left){ if (!PlayingSound[SOUND_ROTATECUBELEFT]){ PlayingSound[SOUND_ROTATECUBELEFT] = ON; system("playsound left.mp3 &"); } eventPress(KEY_LEFTCTRL); eventPress(KEY_LEFTALT); eventPress(KEY_LEFT); //wiimote.rumble = ON; face = face>>1; if (face == 0) face = 32; } else if (!wiimote.keys.left){ PlayingSound[SOUND_ROTATECUBELEFT] = OFF; eventRelease(KEY_LEFTCTRL); eventRelease(KEY_LEFTALT); eventRelease(KEY_LEFT); //wiimote.rumble = OFF; } if (wiimote.keys.right){ if (!PlayingSound[SOUND_ROTATECUBERIGHT]){ PlayingSound[SOUND_ROTATECUBERIGHT] = ON; system("playsound right.mp3 &"); } eventPress(KEY_LEFTCTRL); eventPress(KEY_LEFTALT); eventPress(KEY_RIGHT); //wiimote.rumble = ON; face = face<<1; if (face > 32) face = 1; } else if (!wiimote.keys.right){ PlayingSound[SOUND_ROTATECUBERIGHT] = OFF; eventRelease(KEY_LEFTCTRL); eventRelease(KEY_LEFTALT); eventRelease(KEY_RIGHT); //wiimote.rumble = OFF; } // Pitch if ((wiimote.tilt.y + wiiTiltOffsets[Y_AXIS]) < -PitchSens){ if (!modifier){ wiimote.rumble = ON; //eventPress(KEY_LEFTALT); //eventPress(KEY_F10); } else { eventPress(KEY_LEFTALT); eventPress(KEY_LEFTSHIFT); //eventRelease(KEY_LEFTALT); //eventRelease(KEY_LEFTSHIFT); eventPress(KEY_UP); //eventRelease(KEY_UP); } } else if ((wiimote.tilt.y + wiiTiltOffsets[Y_AXIS]) > PitchSens){ if (!modifier){ wiimote.rumble = ON; //eventRelease(KEY_LEFTALT); //eventRelease(KEY_F10); } else { eventPress(KEY_LEFTALT); eventPress(KEY_LEFTSHIFT); //eventRelease(KEY_LEFTALT); //eventRelease(KEY_LEFTSHIFT); eventPress(KEY_DOWN); //eventRelease(KEY_DOWN); } } else if ( ((wiimote.tilt.y + wiiTiltOffsets[Y_AXIS]) > -PitchSens) && ((wiimote.tilt.y + wiiTiltOffsets[Y_AXIS]) < PitchSens) ){ if (!modifier){ wiimote.rumble = OFF; //eventRelease(KEY_LEFTALT); //eventRelease(KEY_F10); } else { eventRelease(KEY_LEFTALT); eventRelease(KEY_LEFTSHIFT); eventRelease(KEY_UP); eventRelease(KEY_DOWN); } } //else wiimote.rumble = OFF; #ifdef PRINT_STATS /* Print the current state of the wiimote. */ fprintf(stderr, "MODE %02x\n", wiimote.mode.bits); fprintf(stderr, "BAT %02x\n", wiimote.battery); fprintf(stderr, "KEYS %04x one=%d two=%d a=%d b=%d <=%d >=%d ^=%d v=%d h=%d +=%d -=%d\n", wiimote.keys.bits, wiimote.keys.one, wiimote.keys.two, wiimote.keys.a, wiimote.keys.b, wiimote.keys.left, wiimote.keys.right, wiimote.keys.up, wiimote.keys.down, wiimote.keys.home, wiimote.keys.plus, wiimote.keys.minus); fprintf(stderr, "JOY joyx=%03d joyy=%03d x=%03d y=%03d z=%03d keys.z=%d keys.c=%d\n", wiimote.ext.nunchuk.joyx, wiimote.ext.nunchuk.joyy, wiimote.ext.nunchuk.axis.x, wiimote.ext.nunchuk.axis.y, wiimote.ext.nunchuk.axis.z, wiimote.ext.nunchuk.keys.z, wiimote.ext.nunchuk.keys.c); fprintf(stderr, "AXIS x=%03d y=%03d z=%03d\n", wiimote.axis.x, wiimote.axis.y, wiimote.axis.z); #ifdef _ENABLE_TILT fprintf(stderr, "TILT x=%.3f y=%.3f z=%.3f\n", wiimote.tilt.x, wiimote.tilt.y, wiimote.tilt.z); #endif #ifdef _ENABLE_FORCE fprintf(stderr, "FORCE x=%.3f y=%.3f z=%.3f (sum=%.3f)\n", wiimote.force.x, wiimote.force.y, wiimote.force.z, sqrt(wiimote.force.x*wiimote.force.x+wiimote.force.y*wiimote.force.y+wiimote.force.z*wiimote.force.z)); #endif fprintf(stderr, "IR1 x=%04d y=%04d ss=%d\n", wiimote.ir1.x, wiimote.ir1.y, wiimote.ir1.size); fprintf(stderr, "IR2 x=%04d y=%04d ss=%d\n", wiimote.ir2.x, wiimote.ir2.y, wiimote.ir2.size); fprintf(stderr, "IR3 x=%04d y=%04d ss=%d\n", wiimote.ir3.x, wiimote.ir3.y, wiimote.ir3.size); fprintf(stderr, "IR4 x=%04d y=%04d ss=%d\n", wiimote.ir4.x, wiimote.ir4.y, wiimote.ir4.size); fprintf(stderr, "\n"); #endif } return 0; } static int uinput_init(const char *devname){ struct uinput_user_dev udev; int fd = open(devname, O_RDWR); if (fd<0) return -1; ioctl(fd, UI_SET_EVBIT, EV_KEY); ioctl(fd, UI_SET_KEYBIT, KEY_LEFTSHIFT); ioctl(fd, UI_SET_KEYBIT, KEY_LEFTCTRL); ioctl(fd, UI_SET_KEYBIT, KEY_LEFTALT); ioctl(fd, UI_SET_KEYBIT, KEY_TAB); ioctl(fd, UI_SET_KEYBIT, KEY_UP); ioctl(fd, UI_SET_KEYBIT, KEY_LEFT); ioctl(fd, UI_SET_KEYBIT, KEY_RIGHT); ioctl(fd, UI_SET_KEYBIT, KEY_DOWN); ioctl(fd, UI_SET_KEYBIT, KEY_F6); ioctl(fd, UI_SET_KEYBIT, KEY_F8); ioctl(fd, UI_SET_KEYBIT, KEY_F10); ioctl(fd, UI_SET_KEYBIT, KEY_F12); ioctl(fd, UI_SET_KEYBIT, KEY_VOLUMEDOWN); ioctl(fd, UI_SET_KEYBIT, KEY_VOLUMEUP); ioctl(fd, UI_SET_KEYBIT, KEY_PAGEUP); ioctl(fd, UI_SET_KEYBIT, KEY_PAGEDOWN); ioctl(fd, UI_SET_KEYBIT, KEY_SLEEP); ioctl(fd, UI_SET_KEYBIT, KEY_WAKEUP); ioctl(fd, UI_SET_KEYBIT, KEY_POWER); ioctl(fd, UI_SET_KEYBIT, KEY_MINUS); memset(&udev, 0, sizeof(udev)); strncpy(udev.name, "keybd", sizeof(udev.name)); write(fd, &udev, sizeof(udev)); if (ioctl(fd, UI_DEV_CREATE)==0) return fd; // Error close(fd); return -1; } static void insertEvent(int fd, unsigned short type, unsigned short code, int value) { struct input_event e; memset(&e, 0, sizeof(e)); e.type = type; e.code = code; e.value = value; write(fd, &e, sizeof(e)); } static void inputEvent(int fd, unsigned short key, int value) { insertEvent(fd, EV_KEY, key, value); insertEvent(fd, EV_SYN, SYN_REPORT, 0); } // Handy function for press/release events void eventPress(unsigned short key){ inputEvent(uifd, key, 1); } void eventRelease(unsigned short key){ inputEvent(uifd, key, 0); } void initSounds(){ int i; for (i=0;i