summaryrefslogtreecommitdiff
path: root/connect.c
diff options
context:
space:
mode:
authorSam Spillaz <smspillaz@gmail.com>2008-04-26 20:49:42 +0800
committerSam Spillaz <smspillaz@gmail.com>2008-04-26 20:49:42 +0800
commite8d1840c19de93f081df99b13df0bd10781e636f (patch)
tree38a8c2d653c85d6a422a88445412d74ef3937d2e /connect.c
parentec06b2488acf4ce5cd9a88a52ee72cd61f9ada21 (diff)
downloadwiimote-e8d1840c19de93f081df99b13df0bd10781e636f.tar.gz
wiimote-e8d1840c19de93f081df99b13df0bd10781e636f.tar.bz2
* Part 1 of the big wiimote file split: Split connection into connect.c, some utility functions into util.c
Diffstat (limited to 'connect.c')
-rw-r--r--connect.c352
1 files changed, 352 insertions, 0 deletions
diff --git a/connect.c b/connect.c
index e69de29..c9b4036 100644
--- a/connect.c
+++ b/connect.c
@@ -0,0 +1,352 @@
+#include "compiz-wiimote.h"
+
+/* Wii Remote Connection / Handling --------------------------------------------------- */
+
+/* Allocate a callback function */
+
+static Bool
+allocateCallbackFunction (cwiid_wiimote_t *wiimote, int nWiimote)
+{
+ if (nWiimote > MAX_WIIMOTES)
+ return FALSE;
+
+ if (cwiid_set_mesg_callback (wiimote, cwiid_callback))
+ {
+ fprintf(stderr, "Could not set mesg callback\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Interface to find a Wii Remote
+ * so that cwiid_open won't crash
+ * when we can't find one */
+
+Bool find_wiimote(bdaddr_t *bdaddr, int timeout)
+{
+ struct cwiid_bdinfo *bdinfo;
+ int bdinfo_count;
+
+ if (timeout == -1) {
+ while ((bdinfo_count = cwiid_get_bdinfo_array(-1, 2, 1, &bdinfo, 0))
+ == 0);
+ if (bdinfo_count == -1) {
+ return FALSE;
+ }
+ }
+ else {
+ bdinfo_count = cwiid_get_bdinfo_array(-1, timeout, 1, &bdinfo, 0);
+ if (bdinfo_count == -1) {
+ return FALSE;
+ }
+ else if (bdinfo_count == 0) {
+ return FALSE;
+ }
+ }
+
+ free(bdinfo);
+ return TRUE;
+}
+
+/* Second thread.
+ * This is the actual bluetooth connection
+ * phase for the Wii Remote. Because
+ * control is not returned to compiz while
+ * connection is taking place, the desktop
+ * will appear to 'lock up' - which
+ * is certainly not what we want, especially
+ * if we want to do fancy stuff like display
+ * messages. When a wiimote is successfully
+ * connected to the host via bluetooth, a
+ * variable 'connected' is set to indicate that
+ * the CompWiimote can be used.
+ */
+
+void* connectWiimote (void *vd)
+{
+ bdaddr_t bdaddr; /* bluetooth device address */
+ CompDisplay *d = (CompDisplay *) vd;
+ bdaddr = *BDADDR_ANY;
+ CompScreen *s;
+ cwiid_wiimote_t *wiimote;
+
+ WIIMOTE_DISPLAY (d);
+
+ if (!find_wiimote(&bdaddr, 2))
+ {
+ compLogMessage (d, "wiimote", CompLogLevelError,
+ "Wii Remote not found");
+
+ for (s = d->screens; s; s = s->next)
+ {
+ // WIIMOTE_SCREEN (s);
+ CompOption arg[4];
+ int nArg = 0;
+
+ arg[nArg].name = "window";
+ arg[nArg].type = CompOptionTypeInt;
+ arg[nArg].value.i = d->activeWindow;
+ nArg++;
+
+ arg[nArg].name = "root";
+ arg[nArg].type = CompOptionTypeInt;
+ arg[nArg].value.i = s->root;
+ nArg++;
+
+ arg[nArg].name = "string";
+ arg[nArg].type = CompOptionTypeString;
+ arg[nArg].value.s = "Wii Remote not found";
+ nArg++;
+
+ arg[nArg].name = "timeout";
+ arg[nArg].type = CompOptionTypeInt;
+ arg[nArg].value.i = 500;
+
+ sendInfoToPlugin (d, arg, nArg,
+ "prompt",
+ "display_text");
+ }
+ compRemoveTimeout(ad->checkingTimeoutHandle);
+ }
+ else
+ {
+ for (s = d->screens; s; s = s->next)
+ {
+ CompOption arg[4];
+ int nArg = 0;
+
+ arg[nArg].name = "window";
+ arg[nArg].type = CompOptionTypeInt;
+ arg[nArg].value.i = d->activeWindow;
+ nArg++;
+
+ arg[nArg].name = "root";
+ arg[nArg].type = CompOptionTypeInt;
+ arg[nArg].value.i = s->root;
+ nArg++;
+
+ arg[nArg].name = "string";
+ arg[nArg].type = CompOptionTypeString;
+ arg[nArg].value.s = "Wii Remote(s) found. Continue to\n"\
+ " hold (1) and (2) to finalize connection sequence";
+ nArg++;
+
+ arg[nArg].name = "timeout";
+ arg[nArg].type = CompOptionTypeInt;
+ arg[nArg].value.i = 500;
+
+ sendInfoToPlugin (d, arg, nArg,
+ "prompt",
+ "display_text");
+ }
+ if (!(wiimote = cwiid_open(&bdaddr, 0))) {
+ compLogMessage (d, "wiimote", CompLogLevelError,
+ "Could not connect to Wii Remote");
+
+ return NULL;
+ }
+ ad->cWiimote[ad->nWiimote].wiimote = wiimote;
+ ad->cWiimote[ad->nWiimote].connected = TRUE;
+ for (s = d->screens; s; s = s->next)
+ {
+ CompOption arg[4];
+ int nArg = 0;
+
+ arg[nArg].name = "window";
+ arg[nArg].type = CompOptionTypeInt;
+ arg[nArg].value.i = d->activeWindow;
+ nArg++;
+
+ arg[nArg].name = "root";
+ arg[nArg].type = CompOptionTypeInt;
+ arg[nArg].value.i = s->root;
+ nArg++;
+
+ arg[nArg].name = "string";
+ arg[nArg].type = CompOptionTypeString;
+ arg[nArg].value.s = "Wii Remote successfully connected";
+ nArg++;
+
+ arg[nArg].name = "timeout";
+ arg[nArg].type = CompOptionTypeInt;
+ arg[nArg].value.i = 500;
+
+ sendInfoToPlugin (d, arg, nArg,
+ "prompt",
+ "display_text");
+ }
+ }
+ return NULL; // This is required for pthread
+}
+
+/* Second Thread Poller.
+ * This is a poller interface
+ * to ensure that the Wii Remote is connected
+ * before we do anything that requires initialisation.
+ * When the wii remote is connected it does things
+ * such as setup and then returns FALSE
+ * so that it is not called again.
+ */
+
+Bool checkConnected (void *vd)
+{
+ CompDisplay *d = vd;
+ WIIMOTE_DISPLAY (d);
+ struct cwiid_state state; /* wiimote state */
+ unsigned char mesg = 0; /* Mesg Flag */
+ unsigned char rpt_mode = 0; /* Reporting Flag */
+ unsigned char rumble = 0; /* Rumble Flag */
+ int led_state = 0; /* LED State Flag */
+
+ /* FIXME:
+ * Remove me as all I do
+ * is bring down host programs
+ * not good for compiz!
+ */
+
+ cwiid_set_err(err); /* Error Handling */
+
+
+
+ if (ad->cWiimote[ad->nWiimote].connected)
+ {
+ /* Connect to the wiimote */
+ compLogMessage (d, "wiimote", CompLogLevelInfo,
+ "Wii Remote Connection started");
+
+ if (allocateCallbackFunction
+ (ad->cWiimote[ad->nWiimote].wiimote, ad->nWiimote)) // Allocate a c
+ {
+ compLogMessage (d, "wiimote", CompLogLevelInfo,
+ "Wii Remote is now connected");
+
+
+ if (cwiid_set_rumble(ad->cWiimote[0].wiimote, rumble)) {
+ compLogMessage (d, "wiimote", CompLogLevelError,
+ "Couldn't set rumble");
+ }
+
+ /* Toggle Accellerometor Reporting */
+
+ toggle_bit(rpt_mode, CWIID_RPT_ACC);
+ set_rpt_mode(ad->cWiimote[ad->nWiimote].wiimote, rpt_mode);
+
+ /* Toggle Button Reporting */
+
+ toggle_bit(rpt_mode, CWIID_RPT_BTN);
+ set_rpt_mode(ad->cWiimote[ad->nWiimote].wiimote, rpt_mode);
+
+
+ /* CWIID_RPT_EXT is actually
+ * CWIID_RPT_NUNCHUK | CWIID_RPT_CLASSIC */
+
+ /* Toggle Extension Reporting */
+
+ toggle_bit(rpt_mode, CWIID_RPT_EXT);
+ set_rpt_mode(ad->cWiimote[ad->nWiimote].wiimote, rpt_mode);
+
+
+ /* libwiimote picks the highest quality IR mode available with the
+ * other options selected (not including as-yet-undeciphered
+ * interleaved mode */
+
+ /* Toggle IR reporting */
+
+ toggle_bit(rpt_mode, CWIID_RPT_IR);
+ set_rpt_mode(ad->cWiimote[ad->nWiimote].wiimote, rpt_mode);
+
+ /* Toggle Status (Battery etc) reporting */
+
+ toggle_bit(rpt_mode, CWIID_RPT_STATUS);
+ set_rpt_mode(ad->cWiimote[ad->nWiimote].wiimote, rpt_mode);
+
+ /* Check to see if there is a mesg reporting
+ handler (Should be cwiid_callbackx, where X is
+ the Wii Remote iter
+ */
+ /* FIXME !mesg is here unconditionally true */
+ if (!mesg) {
+ if (cwiid_enable(ad->cWiimote[ad->nWiimote].wiimote, CWIID_FLAG_MESG_IFC)) {
+ compLogMessage (d, "wiimote", CompLogLevelError,
+ "Couldn't set messages. Wii remote will connect, but reporting and other things won't work!");
+ }
+ else {
+ mesg = 1;
+ }
+ }
+ else {
+ if (cwiid_disable(ad->cWiimote[ad->nWiimote].wiimote, CWIID_FLAG_MESG_IFC)) {
+ compLogMessage (d, "wiimote", CompLogLevelError,
+ "Couldn't disable messages");
+ }
+ else {
+ mesg = 0;
+ }
+ }
+
+ /* Request Status */
+
+ if (cwiid_request_status(ad->cWiimote[ad->nWiimote].wiimote)) {
+ compLogMessage (d, "wiimote", CompLogLevelError,
+ "Error requesting status. Battery info will not work!");
+ }
+
+ /* Request State */
+
+ if (cwiid_get_state(ad->cWiimote[ad->nWiimote].wiimote, &state)) {
+ compLogMessage (d, "wiimote", CompLogLevelError,
+ "Error requesting state. Calibration will not work!");
+ }
+
+ /* TODO:
+ * Toggle certain LED's for certain
+ * Wii Remote 'Types'
+ */
+
+ toggle_bit(led_state, CWIID_LED1_ON);
+ set_led_state(ad->cWiimote[ad->nWiimote].wiimote, led_state);
+
+ /* Do a fancy thing with the LED's. Doesn't
+ * quite work right yet :(
+ */
+
+ ad->cWiimote[ad->nWiimote].lightsTimeoutHandle =
+ compAddTimeout (650, wiimoteChangeLights, ad->cWiimote[ad->nWiimote].wiimote);
+
+ /* Set some variables using the state interface
+ * FIXME: For some reason, over-querying the
+ * state interface can result in a Mesg Pipe
+ * overflow which in turn causes a cwiid_err.
+ * This is no good because it brings down compiz!
+ * Of course, we only poll the value once, but it
+ * _should_ be fixed in CWiiD
+ */
+
+ ad->cWiimote[ad->nWiimote].acc.initAccX = state.acc[CWIID_X];
+ ad->cWiimote[ad->nWiimote].acc.initAccY = state.acc[CWIID_Y];
+
+ /* Set the id */
+
+ ad->cWiimote[ad->nWiimote].id = cwiid_get_id (ad->cWiimote[ad->nWiimote].wiimote);
+
+
+ /* Increment the Wiimote iter to
+ * allow another CompWiimote to initialise
+ */
+
+ ad->nWiimote++;
+ }
+ else
+ {
+ compLogMessage (d, "wiimote", CompLogLevelError,
+ "Maximum number of Wii Remotes reached. If you want to enable more,"\
+ "change the macro MAX_WIIMOTES in wiimote.c. This will be fixed in "\
+ "the future with actual memory allocation");
+ }
+
+ /* No more checking */
+ return FALSE;
+ }
+
+ return TRUE;
+}