From: <fu...@us...> - 2013-01-24 22:53:47
|
Revision: 12415 http://supertuxkart.svn.sourceforge.net/supertuxkart/?rev=12415&view=rev Author: funto66 Date: 2013-01-24 22:53:34 +0000 (Thu, 24 Jan 2013) Log Message: ----------- Updated to wiiuse fork from https://github.com/rpavlik/wiiuse Modified Paths: -------------- main/trunk/lib/wiiuse/CMakeLists.txt main/trunk/lib/wiiuse/classic.c main/trunk/lib/wiiuse/classic.h main/trunk/lib/wiiuse/definitions.h main/trunk/lib/wiiuse/dynamics.c main/trunk/lib/wiiuse/dynamics.h main/trunk/lib/wiiuse/events.c main/trunk/lib/wiiuse/events.h main/trunk/lib/wiiuse/guitar_hero_3.c main/trunk/lib/wiiuse/guitar_hero_3.h main/trunk/lib/wiiuse/io.c main/trunk/lib/wiiuse/io.h main/trunk/lib/wiiuse/ir.c main/trunk/lib/wiiuse/ir.h main/trunk/lib/wiiuse/nunchuk.c main/trunk/lib/wiiuse/nunchuk.h main/trunk/lib/wiiuse/os.h main/trunk/lib/wiiuse/wiiuse.c main/trunk/lib/wiiuse/wiiuse.h main/trunk/lib/wiiuse/wiiuse_internal.h Added Paths: ----------- main/trunk/lib/wiiuse/definitions_os.h main/trunk/lib/wiiuse/motion_plus.c main/trunk/lib/wiiuse/motion_plus.h main/trunk/lib/wiiuse/os_mac/ main/trunk/lib/wiiuse/os_mac/os_mac.h main/trunk/lib/wiiuse/os_mac/os_mac.m main/trunk/lib/wiiuse/os_mac/os_mac_find.m main/trunk/lib/wiiuse/os_mac/os_mac_interface.m main/trunk/lib/wiiuse/os_nix.c main/trunk/lib/wiiuse/os_win.c main/trunk/lib/wiiuse/util.c main/trunk/lib/wiiuse/wiiboard.c main/trunk/lib/wiiuse/wiiboard.h main/trunk/lib/wiiuse/wiiuse_msvcstdint.h Modified: main/trunk/lib/wiiuse/CMakeLists.txt =================================================================== --- main/trunk/lib/wiiuse/CMakeLists.txt 2013-01-24 21:44:06 UTC (rev 12414) +++ main/trunk/lib/wiiuse/CMakeLists.txt 2013-01-24 22:53:34 UTC (rev 12415) @@ -11,4 +11,7 @@ ir.c nunchuk.c wiiuse.c + wiiboard.c + motion_plus.c + util.c ) Modified: main/trunk/lib/wiiuse/classic.c =================================================================== --- main/trunk/lib/wiiuse/classic.c 2013-01-24 21:44:06 UTC (rev 12414) +++ main/trunk/lib/wiiuse/classic.c 2013-01-24 22:53:34 UTC (rev 12415) @@ -31,20 +31,13 @@ * @brief Classic controller expansion device. */ -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - -#ifdef WIN32 - #include <Winsock2.h> -#endif - -#include "definitions.h" -#include "wiiuse_internal.h" -#include "dynamics.h" -#include "events.h" #include "classic.h" +#include "dynamics.h" /* for calc_joystick_state */ +#include "events.h" /* for handshake_expansion */ +#include <stdlib.h> /* for malloc */ +#include <string.h> /* for memset */ + static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now); /** @@ -56,9 +49,8 @@ * * @return Returns 1 if handshake was successful, 0 if not. */ +#define HANDSHAKE_BYTES_USED 12 int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len) { - int i; - int offset = 0; cc->btns = 0; cc->btns_held = 0; @@ -66,11 +58,7 @@ cc->r_shoulder = 0; cc->l_shoulder = 0; - /* decrypt data */ - for (i = 0; i < len; ++i) - data[i] = (data[i] ^ 0x17) + 0x17; - - if (data[offset] == 0xFF) { + if (data[0] == 0xFF || len < HANDSHAKE_BYTES_USED) { /* * Sometimes the data returned here is not correct. * This might happen because the wiimote is lagging @@ -81,40 +69,41 @@ * but since the next 16 bytes are the same, just use * those. */ - if (data[offset + 16] == 0xFF) { + if (len < 17 || len < HANDSHAKE_BYTES_USED + 16 || data[16] == 0xFF) { /* get the calibration data */ - byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte)); + byte* handshake_buf = (byte *)malloc(EXP_HANDSHAKE_LEN * sizeof(byte)); WIIUSE_DEBUG("Classic controller handshake appears invalid, trying again."); wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN); return 0; - } else - offset += 16; + } else { + data += 16; + } } /* joystick stuff */ - cc->ljs.max.x = data[0 + offset] / 4; - cc->ljs.min.x = data[1 + offset] / 4; - cc->ljs.center.x = data[2 + offset] / 4; - cc->ljs.max.y = data[3 + offset] / 4; - cc->ljs.min.y = data[4 + offset] / 4; - cc->ljs.center.y = data[5 + offset] / 4; + cc->ljs.max.x = data[0] / 4; + cc->ljs.min.x = data[1] / 4; + cc->ljs.center.x = data[2] / 4; + cc->ljs.max.y = data[3] / 4; + cc->ljs.min.y = data[4] / 4; + cc->ljs.center.y = data[5] / 4; - cc->rjs.max.x = data[6 + offset] / 8; - cc->rjs.min.x = data[7 + offset] / 8; - cc->rjs.center.x = data[8 + offset] / 8; - cc->rjs.max.y = data[9 + offset] / 8; - cc->rjs.min.y = data[10 + offset] / 8; - cc->rjs.center.y = data[11 + offset] / 8; + cc->rjs.max.x = data[6] / 8; + cc->rjs.min.x = data[7] / 8; + cc->rjs.center.x = data[8] / 8; + cc->rjs.max.y = data[9] / 8; + cc->rjs.min.y = data[10] / 8; + cc->rjs.center.y = data[11] / 8; /* handshake done */ wm->exp.type = EXP_CLASSIC; - #ifdef WIN32 +#ifdef WIIUSE_WIN32 wm->timeout = WIIMOTE_DEFAULT_TIMEOUT; - #endif +#endif return 1; } @@ -138,15 +127,11 @@ * @param msg The message specified in the event packet. */ void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg) { - int i, lx, ly, rx, ry; + int lx, ly, rx, ry; byte l, r; - /* decrypt data */ - for (i = 0; i < 6; ++i) - msg[i] = (msg[i] ^ 0x17) + 0x17; + classic_ctrl_pressed_buttons(cc, from_big_endian_uint16_t(msg + 4)); - classic_ctrl_pressed_buttons(cc, BIG_ENDIAN_SHORT(*(short*)(msg + 4))); - /* left/right buttons */ l = (((msg[2] & 0x60) >> 2) | ((msg[3] & 0xE0) >> 5)); r = (msg[3] & 0x1F); @@ -164,8 +149,8 @@ rx = ((msg[0] & 0xC0) >> 3) | ((msg[1] & 0xC0) >> 5) | ((msg[2] & 0x80) >> 7); ry = (msg[2] & 0x1F); - calc_joystick_state(&cc->ljs, lx, ly); - calc_joystick_state(&cc->rjs, rx, ry); + calc_joystick_state(&cc->ljs, (float)lx, (float)ly); + calc_joystick_state(&cc->rjs, (float)rx, (float)ry); } Modified: main/trunk/lib/wiiuse/classic.h =================================================================== --- main/trunk/lib/wiiuse/classic.h 2013-01-24 21:44:06 UTC (rev 12414) +++ main/trunk/lib/wiiuse/classic.h 2013-01-24 22:53:34 UTC (rev 12415) @@ -40,14 +40,17 @@ extern "C" { #endif -int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len); + /** @defgroup internal_classic Internal: Classic Controller */ + /** @{ */ + int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len); -void classic_ctrl_disconnected(struct classic_ctrl_t* cc); + void classic_ctrl_disconnected(struct classic_ctrl_t* cc); -void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg); + void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg); + /** @} */ #ifdef __cplusplus } #endif -#endif // CLASSIC_H_INCLUDED +#endif /* CLASSIC_H_INCLUDED */ Modified: main/trunk/lib/wiiuse/definitions.h =================================================================== --- main/trunk/lib/wiiuse/definitions.h 2013-01-24 21:44:06 UTC (rev 12414) +++ main/trunk/lib/wiiuse/definitions.h 2013-01-24 22:53:34 UTC (rev 12415) @@ -35,31 +35,43 @@ #define DEFINITIONS_H_INCLUDED /* this is wiiuse - used to distinguish from third party programs using wiiuse.h */ -#include "os.h" +#include <stdio.h> +#include "definitions_os.h" +/** @addtogroup internal_general */ +/** @{ */ #define WIIMOTE_PI 3.14159265f -//#define WITH_WIIUSE_DEBUG +/* #define WITH_WIIUSE_DEBUG */ +extern FILE* logtarget[]; + +#define OUTF_ERROR logtarget[0] +#define OUTF_WARNING logtarget[1] +#define OUTF_INFO logtarget[2] +#define OUTF_DEBUG logtarget[3] + /* Error output macros */ -#define WIIUSE_ERROR(fmt, ...) fprintf(stderr, "[ERROR] " fmt "\n", ##__VA_ARGS__) +#define WIIUSE_ERROR(fmt, ...) do { if (OUTF_ERROR) fprintf(OUTF_ERROR, "[ERROR] " fmt "\n", ##__VA_ARGS__); } while(0) /* Warning output macros */ -#define WIIUSE_WARNING(fmt, ...) fprintf(stderr, "[WARNING] " fmt "\n", ##__VA_ARGS__) +#define WIIUSE_WARNING(fmt, ...) do { if (OUTF_WARNING) fprintf(OUTF_WARNING, "[WARNING] " fmt "\n", ##__VA_ARGS__); } while(0) /* Information output macros */ -#define WIIUSE_INFO(fmt, ...) fprintf(stderr, "[INFO] " fmt "\n", ##__VA_ARGS__) +#define WIIUSE_INFO(fmt, ...) do { if (OUTF_INFO) fprintf(OUTF_INFO, "[INFO] " fmt "\n", ##__VA_ARGS__); } while(0) #ifdef WITH_WIIUSE_DEBUG - #ifdef WIN32 - #define WIIUSE_DEBUG(fmt, ...) do { \ - char* file = __FILE__; \ - int i = strlen(file) - 1; \ - for (; i && (file[i] != '\\'); --i); \ - fprintf(stderr, "[DEBUG] %s:%i: " fmt "\n", file+i+1, __LINE__, ##__VA_ARGS__); \ + #ifdef WIIUSE_WIN32 + #define WIIUSE_DEBUG(fmt, ...) do { \ + if (OUTF_DEBUG) { \ + char* file = __FILE__; \ + int i = strlen(file) - 1; \ + for (; i && (file[i] != '\\'); --i); \ + fprintf(OUTF_DEBUG, "[DEBUG] %s:%i: " fmt "\n", file+i+1, __LINE__, ##__VA_ARGS__); \ + } \ } while (0) #else - #define WIIUSE_DEBUG(fmt, ...) fprintf(stderr, "[DEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__) + #define WIIUSE_DEBUG(fmt, ...) do { if (OUTF_DEBUG) fprintf(OUTF_DEBUG, "[DEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__); } while (0) #endif #else #define WIIUSE_DEBUG(fmt, ...) @@ -69,11 +81,12 @@ #define RAD_TO_DEGREE(r) ((r * 180.0f) / WIIMOTE_PI) #define DEGREE_TO_RAD(d) (d * (WIIMOTE_PI / 180.0f)) -/* Convert to big endian */ -#define BIG_ENDIAN_LONG(i) (htonl(i)) -#define BIG_ENDIAN_SHORT(i) (htons(i)) - #define absf(x) ((x >= 0) ? (x) : (x * -1.0f)) #define diff_f(x, y) ((x >= y) ? (absf(x - y)) : (absf(y - x))) -#endif // DEFINITIONS_H_INCLUDED +#define WCONST + + +/** @} */ + +#endif /* DEFINITIONS_H_INCLUDED */ Added: main/trunk/lib/wiiuse/definitions_os.h =================================================================== --- main/trunk/lib/wiiuse/definitions_os.h (rev 0) +++ main/trunk/lib/wiiuse/definitions_os.h 2013-01-24 22:53:34 UTC (rev 12415) @@ -0,0 +1,51 @@ +/* + * wiiuse + * + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > + * + * Copyright 2006-2007 + * + * This file is part of wiiuse. + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * $Header$ + * + */ + + +/** + * @file + * @brief Operating system related definitions. + * + * This file is an attempt to separate operating system + * dependent functions and choose what should be used + * at compile time. + */ + +#ifndef DEFINITIONS_OS_H_INCLUDED +#define DEFINITIONS_OS_H_INCLUDED + +#ifdef _MSC_VER + #include <float.h> + /* windows with visual c */ + #define isnan(x) (_isnan(x)) + #define isinf(x) (!_finite(x)) + /* disable warnings I don't care about */ + /*#pragma warning(disable:4273) */ /* inconsistent dll linkage */ +#endif + +#endif /* DEFINITIONS_OS_H_INCLUDED */ Modified: main/trunk/lib/wiiuse/dynamics.c =================================================================== --- main/trunk/lib/wiiuse/dynamics.c 2013-01-24 21:44:06 UTC (rev 12414) +++ main/trunk/lib/wiiuse/dynamics.c 2013-01-24 22:53:34 UTC (rev 12415) @@ -35,18 +35,11 @@ * motion sensing. */ -#include <stdio.h> -#include <stdlib.h> -#include <math.h> +#include "dynamics.h" -#ifdef WIN32 - #include <float.h> -#endif +#include <math.h> /* for atan2f, atanf, sqrt */ +#include <stdlib.h> /* for abs */ -#include "definitions.h" -#include "wiiuse_internal.h" -#include "ir.h" -#include "dynamics.h" /** * @brief Calculate the roll, pitch, yaw. @@ -84,12 +77,21 @@ z = ((float)accel->z - (float)ac->cal_zero.z) / zg; /* make sure x,y,z are between -1 and 1 for the tan functions */ - if (x < -1.0f) x = -1.0f; - else if (x > 1.0f) x = 1.0f; - if (y < -1.0f) y = -1.0f; - else if (y > 1.0f) y = 1.0f; - if (z < -1.0f) z = -1.0f; - else if (z > 1.0f) z = 1.0f; + if (x < -1.0f) { + x = -1.0f; + } else if (x > 1.0f) { + x = 1.0f; + } + if (y < -1.0f) { + y = -1.0f; + } else if (y > 1.0f) { + y = 1.0f; + } + if (z < -1.0f) { + z = -1.0f; + } else if (z > 1.0f) { + z = 1.0f; + } /* if it is over 1g then it is probably accelerating and not reliable */ if (abs(accel->x - ac->cal_zero.x) <= ac->cal_g.x) { @@ -137,6 +139,18 @@ gforce->z = ((float)accel->z - (float)ac->cal_zero.z) / zg; } +static float applyCalibration(float inval, float minval, float maxval, float centerval) { + float ret; + /* We don't use the exact ranges but the ranges + 1 in case we get bad calibration data - avoid div0 */ + if (inval == centerval) { + ret = 0; + } else if (inval < centerval) { + ret = (inval - centerval) / (centerval - minval + 1); + } else { + ret = (inval - centerval) / (maxval - centerval + 1); + } + return ret; +} /** * @brief Calculate the angle and magnitude of a joystick. @@ -154,7 +168,7 @@ * Then the range from the min to the center and the center to the max * may be different. * Because of this, depending on if the current x or y value is greater - * or less than the assoicated axis center value, it needs to be interpolated + * or less than the associated axis center value, it needs to be interpolated * between the center and the minimum or maxmimum rather than between * the minimum and maximum. * @@ -164,65 +178,50 @@ * The range is therefore -1 to 1, 0 being the exact center rather than * the middle of min and max. */ - if (x == js->center.x) - rx = 0; - else if (x >= js->center.x) - rx = ((float)(x - js->center.x) / (float)(js->max.x - js->center.x)); - else - rx = ((float)(x - js->min.x) / (float)(js->center.x - js->min.x)) - 1.0f; - - if (y == js->center.y) - ry = 0; - else if (y >= js->center.y) - ry = ((float)(y - js->center.y) / (float)(js->max.y - js->center.y)); - else - ry = ((float)(y - js->min.y) / (float)(js->center.y - js->min.y)) - 1.0f; - + rx = applyCalibration(x, js->min.x, js->max.x, js->center.x); + ry = applyCalibration(y, js->min.y, js->max.y, js->center.y); /* calculate the joystick angle and magnitude */ - ang = RAD_TO_DEGREE(atanf(ry / rx)); - ang -= 90.0f; - if (rx < 0.0f) - ang -= 180.0f; - js->ang = absf(ang); - js->mag = (float) sqrt((rx * rx) + (ry * ry)); + ang = RAD_TO_DEGREE(atan2f(ry, rx)); + js->ang = ang + 180.0f; + js->mag = sqrtf((rx * rx) + (ry * ry)); } void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type) { switch (type) { - case SMOOTH_ROLL: - { - /* it's possible last iteration was nan or inf, so set it to 0 if that happened */ - if (isnan(ac->st_roll) || isinf(ac->st_roll)) - ac->st_roll = 0.0f; + case SMOOTH_ROLL: { + /* it's possible last iteration was nan or inf, so set it to 0 if that happened */ + if (isnan(ac->st_roll) || isinf(ac->st_roll)) { + ac->st_roll = 0.0f; + } - /* - * If the sign changes (which will happen if going from -180 to 180) - * or from (-1 to 1) then don't smooth, just use the new angle. - */ - if (((ac->st_roll < 0) && (orient->roll > 0)) || ((ac->st_roll > 0) && (orient->roll < 0))) { - ac->st_roll = orient->roll; - } else { - orient->roll = ac->st_roll + (ac->st_alpha * (orient->a_roll - ac->st_roll)); - ac->st_roll = orient->roll; + /* + * If the sign changes (which will happen if going from -180 to 180) + * or from (-1 to 1) then don't smooth, just use the new angle. + */ + if (((ac->st_roll < 0) && (orient->roll > 0)) || ((ac->st_roll > 0) && (orient->roll < 0))) { + ac->st_roll = orient->roll; + } else { + orient->roll = ac->st_roll + (ac->st_alpha * (orient->a_roll - ac->st_roll)); + ac->st_roll = orient->roll; + } + + return; } - return; - } + case SMOOTH_PITCH: { + if (isnan(ac->st_pitch) || isinf(ac->st_pitch)) { + ac->st_pitch = 0.0f; + } - case SMOOTH_PITCH: - { - if (isnan(ac->st_pitch) || isinf(ac->st_pitch)) - ac->st_pitch = 0.0f; + if (((ac->st_pitch < 0) && (orient->pitch > 0)) || ((ac->st_pitch > 0) && (orient->pitch < 0))) { + ac->st_pitch = orient->pitch; + } else { + orient->pitch = ac->st_pitch + (ac->st_alpha * (orient->a_pitch - ac->st_pitch)); + ac->st_pitch = orient->pitch; + } - if (((ac->st_pitch < 0) && (orient->pitch > 0)) || ((ac->st_pitch > 0) && (orient->pitch < 0))) { - ac->st_pitch = orient->pitch; - } else { - orient->pitch = ac->st_pitch + (ac->st_alpha * (orient->a_pitch - ac->st_pitch)); - ac->st_pitch = orient->pitch; + return; } - - return; - } } } Modified: main/trunk/lib/wiiuse/dynamics.h =================================================================== --- main/trunk/lib/wiiuse/dynamics.h 2013-01-24 21:44:06 UTC (rev 12414) +++ main/trunk/lib/wiiuse/dynamics.h 2013-01-24 22:53:34 UTC (rev 12415) @@ -44,13 +44,17 @@ extern "C" { #endif -void calculate_orientation(struct accel_t* ac, struct vec3b_t* accel, struct orient_t* orient, int smooth); -void calculate_gforce(struct accel_t* ac, struct vec3b_t* accel, struct gforce_t* gforce); -void calc_joystick_state(struct joystick_t* js, float x, float y); -void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type); + /** @defgroup internal_dynamics Internal: Dynamics Functions */ + /** @{ */ + void calculate_orientation(struct accel_t* ac, struct vec3b_t* accel, struct orient_t* orient, int smooth); + void calculate_gforce(struct accel_t* ac, struct vec3b_t* accel, struct gforce_t* gforce); + void calc_joystick_state(struct joystick_t* js, float x, float y); + void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type); + /** @} */ + #ifdef __cplusplus } #endif -#endif // DYNAMICS_H_INCLUDED +#endif /* DYNAMICS_H_INCLUDED */ Modified: main/trunk/lib/wiiuse/events.c =================================================================== --- main/trunk/lib/wiiuse/events.c 2013-01-24 21:44:06 UTC (rev 12414) +++ main/trunk/lib/wiiuse/events.c 2013-01-24 22:53:34 UTC (rev 12415) @@ -34,34 +34,25 @@ * that are sent from the wiimote to us. */ -#include <stdio.h> +#include "wiiuse_internal.h" +#include "events.h" -#ifndef WIN32 - #include <sys/time.h> - #include <unistd.h> - #include <errno.h> -#else - #include <winsock2.h> -#endif +#include "classic.h" /* for classic_ctrl_disconnected, etc */ +#include "dynamics.h" /* for calculate_gforce, etc */ +#include "guitar_hero_3.h" /* for guitar_hero_3_disconnected, etc */ +#include "ir.h" /* for calculate_basic_ir, etc */ +#include "nunchuk.h" /* for nunchuk_disconnected, etc */ +#include "wiiboard.h" /* for wii_board_disconnected, etc */ +#include "motion_plus.h" /* for motion_plus_disconnected, etc */ -#include <sys/types.h> -#include <stdlib.h> -#include <math.h> +#include "os.h" /* for wiiuse_os_poll */ -#include "definitions.h" -#include "io.h" -#include "wiiuse_internal.h" -#include "dynamics.h" -#include "ir.h" -#include "nunchuk.h" -#include "classic.h" -#include "guitar_hero_3.h" -#include "events.h" +#include <stdio.h> /* for printf, perror */ +#include <stdlib.h> /* for free, malloc */ +#include <string.h> /* for memcpy, memset */ -static void idle_cycle(struct wiimote_t* wm); -static void clear_dirty_reads(struct wiimote_t* wm); -static void propagate_event(struct wiimote_t* wm, byte event, byte* msg); static void event_data_read(struct wiimote_t* wm, byte* msg); +static void event_data_write(struct wiimote_t *wm, byte *msg); static void event_status(struct wiimote_t* wm, byte* msg); static void handle_expansion(struct wiimote_t* wm, byte* msg); @@ -74,133 +65,55 @@ * @param wm An array of pointers to wiimote_t structures. * @param wiimotes The number of wiimote_t structures in the \a wm array. * - * @return Returns number of wiimotes that an event has occured on. + * @return Returns number of wiimotes that an event has occurred on. * * It is necessary to poll the wiimote devices for events * that occur. If an event occurs on a particular wiimote, * the event variable will be set. */ int wiiuse_poll(struct wiimote_t** wm, int wiimotes) { + return wiiuse_os_poll(wm, wiimotes); +} + +int wiiuse_update(struct wiimote_t** wiimotes, int nwiimotes, wiiuse_update_cb callback) { int evnt = 0; - - #ifndef WIN32 - /* - * *nix - */ - struct timeval tv; - fd_set fds; - int r; - int i; - int highest_fd = -1; - - if (!wm) return 0; - - /* block select() for 1/2000th of a second */ - tv.tv_sec = 0; - tv.tv_usec = 500; - - FD_ZERO(&fds); - - for (i = 0; i < wiimotes; ++i) { - /* only poll it if it is connected */ - if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED)) { - FD_SET(wm[i]->in_sock, &fds); - - /* find the highest fd of the connected wiimotes */ - if (wm[i]->in_sock > highest_fd) - highest_fd = wm[i]->in_sock; + if (wiiuse_poll(wiimotes, nwiimotes)) { + static struct wiimote_callback_data_t s; + int i = 0; + for (; i < nwiimotes; ++i) { + switch (wiimotes[i]->event) { + case WIIUSE_NONE: + break; + default: + /* this could be: WIIUSE_EVENT, WIIUSE_STATUS, WIIUSE_CONNECT, etc.. */ + s.uid = wiimotes[i]->unid; + s.leds = wiimotes[i]->leds; + s.battery_level = wiimotes[i]->battery_level; + s.accel = wiimotes[i]->accel; + s.orient = wiimotes[i]->orient; + s.gforce = wiimotes[i]->gforce; + s.ir = wiimotes[i]->ir; + s.buttons = wiimotes[i]->btns; + s.buttons_held = wiimotes[i]->btns_held; + s.buttons_released = wiimotes[i]->btns_released; + s.event = wiimotes[i]->event; + s.state = wiimotes[i]->state; + s.expansion = wiimotes[i]->exp; + callback(&s); + evnt++; + break; } - - wm[i]->event = WIIUSE_NONE; } - - if (highest_fd == -1) - /* nothing to poll */ - return 0; - - if (select(highest_fd + 1, &fds, NULL, NULL, &tv) == -1) { - WIIUSE_ERROR("Unable to select() the wiimote interrupt socket(s)."); - perror("Error Details"); - return 0; - } - - /* check each socket for an event */ - for (i = 0; i < wiimotes; ++i) { - /* if this wiimote is not connected, skip it */ - if (!WIIMOTE_IS_CONNECTED(wm[i])) - continue; - - if (FD_ISSET(wm[i]->in_sock, &fds)) { - /* clear out the event buffer */ - memset(wm[i]->event_buf, 0, sizeof(wm[i]->event_buf)); - - /* clear out any old read requests */ - clear_dirty_reads(wm[i]); - - /* read the pending message into the buffer */ - r = read(wm[i]->in_sock, wm[i]->event_buf, sizeof(wm[i]->event_buf)); - if (r == -1) { - /* error reading data */ - WIIUSE_ERROR("Receiving wiimote data (id %i).", wm[i]->unid); - perror("Error Details"); - - if (errno == ENOTCONN) { - /* this can happen if the bluetooth dongle is disconnected */ - WIIUSE_ERROR("Bluetooth appears to be disconnected. Wiimote unid %i will be disconnected.", wm[i]->unid); - wiiuse_disconnect(wm[i]); - wm[i]->event = WIIUSE_UNEXPECTED_DISCONNECT; - } - - continue; - } - if (!r) { - /* remote disconnect */ - wiiuse_disconnected(wm[i]); - evnt = 1; - continue; - } - - /* propagate the event */ - propagate_event(wm[i], wm[i]->event_buf[1], wm[i]->event_buf+2); - evnt += (wm[i]->event != WIIUSE_NONE); - } else { - idle_cycle(wm[i]); - } - } - #else - /* - * Windows - */ - int i; - - if (!wm) return 0; - - for (i = 0; i < wiimotes; ++i) { - wm[i]->event = WIIUSE_NONE; - - if (wiiuse_io_read(wm[i])) { - /* propagate the event */ - propagate_event(wm[i], wm[i]->event_buf[0], wm[i]->event_buf+1); - evnt += (wm[i]->event != WIIUSE_NONE); - - /* clear out the event buffer */ - memset(wm[i]->event_buf, 0, sizeof(wm[i]->event_buf)); - } else { - idle_cycle(wm[i]); - } - } - #endif - + } return evnt; } - /** * @brief Called on a cycle where no significant change occurs. * * @param wm Pointer to a wiimote_t structure. */ -static void idle_cycle(struct wiimote_t* wm) { +void idle_cycle(struct wiimote_t* wm) { /* * Smooth the angles. * @@ -227,7 +140,7 @@ * * @param wm Pointer to a wiimote_t structure. */ -static void clear_dirty_reads(struct wiimote_t* wm) { +void clear_dirty_reads(struct wiimote_t* wm) { struct read_req_t* req = wm->read_req; while (req && req->dirty) { @@ -239,145 +152,130 @@ } } +/** + * @brief Handle accel data in a wiimote message. + * + * @param wm Pointer to a wiimote_t structure. + * @param msg The message specified in the event packet. + */ +static void handle_wm_accel(struct wiimote_t* wm, byte* msg) { + wm->accel.x = msg[2]; + wm->accel.y = msg[3]; + wm->accel.z = msg[4]; + /* calculate the remote orientation */ + calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING)); + + /* calculate the gforces on each axis */ + calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce); +} + + /** - * @brief Analyze the event that occured on a wiimote. + * @brief Analyze the event that occurred on a wiimote. * - * @param wm An array of pointers to wiimote_t structures. - * @param event The event that occured. + * @param wm Pointer to a wiimote_t structure. + * @param event The event that occurred. * @param msg The message specified in the event packet. * * Pass the event to the registered event callback. */ -static void propagate_event(struct wiimote_t* wm, byte event, byte* msg) { +void propagate_event(struct wiimote_t* wm, byte event, byte* msg) { save_state(wm); switch (event) { - case WM_RPT_BTN: - { - /* button */ - wiiuse_pressed_buttons(wm, msg); - break; - } - case WM_RPT_BTN_ACC: - { - /* button - motion */ - wiiuse_pressed_buttons(wm, msg); + case WM_RPT_BTN: { + /* button */ + wiiuse_pressed_buttons(wm, msg); + break; + } + case WM_RPT_BTN_ACC: { + /* button - motion */ + wiiuse_pressed_buttons(wm, msg); - wm->accel.x = msg[2]; - wm->accel.y = msg[3]; - wm->accel.z = msg[4]; + handle_wm_accel(wm, msg); - /* calculate the remote orientation */ - calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING)); + break; + } + case WM_RPT_READ: { + /* data read */ + event_data_read(wm, msg); - /* calculate the gforces on each axis */ - calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce); + /* yeah buttons may be pressed, but this wasn't an "event" */ + return; + } + case WM_RPT_CTRL_STATUS: { + /* controller status */ + event_status(wm, msg); - break; - } - case WM_RPT_READ: - { - /* data read */ - event_data_read(wm, msg); + /* don't execute the event callback */ + return; + } + case WM_RPT_BTN_EXP: { + /* button - expansion */ + wiiuse_pressed_buttons(wm, msg); + handle_expansion(wm, msg + 2); - /* yeah buttons may be pressed, but this wasn't an "event" */ - return; - } - case WM_RPT_CTRL_STATUS: - { - /* controller status */ - event_status(wm, msg); + break; + } + case WM_RPT_BTN_ACC_EXP: { + /* button - motion - expansion */ + wiiuse_pressed_buttons(wm, msg); - /* don't execute the event callback */ - return; - } - case WM_RPT_BTN_EXP: - { - /* button - expansion */ - wiiuse_pressed_buttons(wm, msg); - handle_expansion(wm, msg+2); + handle_wm_accel(wm, msg); - break; - } - case WM_RPT_BTN_ACC_EXP: - { - /* button - motion - expansion */ - wiiuse_pressed_buttons(wm, msg); + handle_expansion(wm, msg + 5); - wm->accel.x = msg[2]; - wm->accel.y = msg[3]; - wm->accel.z = msg[4]; + break; + } + case WM_RPT_BTN_ACC_IR: { + /* button - motion - ir */ + wiiuse_pressed_buttons(wm, msg); - calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING)); - calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce); + handle_wm_accel(wm, msg); - handle_expansion(wm, msg+5); + /* ir */ + calculate_extended_ir(wm, msg + 5); - break; - } - case WM_RPT_BTN_ACC_IR: - { - /* button - motion - ir */ - wiiuse_pressed_buttons(wm, msg); + break; + } + case WM_RPT_BTN_IR_EXP: { + /* button - ir - expansion */ + wiiuse_pressed_buttons(wm, msg); + handle_expansion(wm, msg + 12); - wm->accel.x = msg[2]; - wm->accel.y = msg[3]; - wm->accel.z = msg[4]; + /* ir */ + calculate_basic_ir(wm, msg + 2); - calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING)); - calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce); + break; + } + case WM_RPT_BTN_ACC_IR_EXP: { + /* button - motion - ir - expansion */ + wiiuse_pressed_buttons(wm, msg); - /* ir */ - calculate_extended_ir(wm, msg+5); + handle_wm_accel(wm, msg); - break; - } - case WM_RPT_BTN_IR_EXP: - { - /* button - ir - expansion */ - wiiuse_pressed_buttons(wm, msg); - handle_expansion(wm, msg+12); + handle_expansion(wm, msg + 15); - /* ir */ - calculate_basic_ir(wm, msg+2); + /* ir */ + calculate_basic_ir(wm, msg + 5); - break; - } - case WM_RPT_BTN_ACC_IR_EXP: - { - /* button - motion - ir - expansion */ - wiiuse_pressed_buttons(wm, msg); - - wm->accel.x = msg[2]; - wm->accel.y = msg[3]; - wm->accel.z = msg[4]; - - calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING)); - calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce); - - handle_expansion(wm, msg+15); - - /* ir */ - calculate_basic_ir(wm, msg+5); - - break; - } - case WM_RPT_WRITE: - { - /* write feedback - safe to skip */ - break; - } - default: - { - WIIUSE_WARNING("Unknown event, can not handle it [Code 0x%x].", event); - return; - } + break; + } + case WM_RPT_WRITE: { + event_data_write(wm, msg); + break; + } + default: { + WIIUSE_WARNING("Unknown event, can not handle it [Code 0x%x].", event); + return; + } } /* was there an event? */ - if (state_changed(wm)) + if (state_changed(wm)) { wm->event = WIIUSE_EVENT; + } } @@ -388,10 +286,10 @@ * @param msg The message specified in the event packet. */ void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg) { - short now; + int16_t now; - /* convert to big endian */ - now = BIG_ENDIAN_SHORT(*(short*)msg) & WIIMOTE_BUTTON_ALL; + /* convert from big endian */ + now = from_big_endian_uint16_t(msg) & WIIMOTE_BUTTON_ALL; /* pressed now & were pressed, then held */ wm->btns_held = (now & wm->btns); @@ -420,14 +318,15 @@ /* we must always assume the packet received is from the most recent request */ byte err; byte len; - unsigned short offset; + uint16_t offset; struct read_req_t* req = wm->read_req; wiiuse_pressed_buttons(wm, msg); /* find the next non-dirty request */ - while (req && req->dirty) + while (req && req->dirty) { req = req->next; + } /* if we don't have a request out then we didn't ask for this packet */ if (!req) { @@ -437,12 +336,13 @@ err = msg[2] & 0x0F; - if (err == 0x08) + if (err == 0x08) { WIIUSE_WARNING("Unable to read data - address does not exist."); - else if (err == 0x07) + } else if (err == 0x07) { WIIUSE_WARNING("Unable to read data - address is for write-only registers."); - else if (err) + } else if (err) { WIIUSE_WARNING("Unable to read data - unknown error code %x.", err); + } if (err) { /* this request errored out, so skip it and go to the next one */ @@ -452,20 +352,23 @@ free(req); /* if another request exists send it to the wiimote */ - if (wm->read_req) + if (wm->read_req) { wiiuse_send_next_pending_read_request(wm); + } return; } len = ((msg[2] & 0xF0) >> 4) + 1; - offset = BIG_ENDIAN_SHORT(*(unsigned short*)(msg + 3)); + offset = from_big_endian_uint16_t(msg + 3); req->addr = (req->addr & 0xFFFF); req->wait -= len; if (req->wait >= req->size) /* this should never happen */ + { req->wait = 0; + } WIIUSE_DEBUG("Received read packet:"); WIIUSE_DEBUG(" Packet read offset: %i bytes", offset); @@ -477,15 +380,16 @@ /* reconstruct this part of the data */ memcpy((req->buf + offset - req->addr), (msg + 5), len); - #ifdef WITH_WIIUSE_DEBUG +#ifdef WITH_WIIUSE_DEBUG { int i = 0; printf("Read: "); - for (; i < req->size - req->wait; ++i) + for (; i < req->size - req->wait; ++i) { printf("%x ", req->buf[i]); + } printf("\n"); } - #endif +#endif /* if all data has been received, execute the read event callback or generate event */ if (!req->wait) { @@ -509,12 +413,58 @@ } /* if another request exists send it to the wiimote */ - if (wm->read_req) + if (wm->read_req) { wiiuse_send_next_pending_read_request(wm); + } } } +static void event_data_write(struct wiimote_t *wm, byte *msg) { + + struct data_req_t* req = wm->data_req; + + wiiuse_pressed_buttons(wm, msg); + + /* if we don't have a request out then we didn't ask for this packet */ + if (!req) { + WIIUSE_WARNING("Transmitting data packet when no request was made."); + return; + } + if (!(req->state == REQ_SENT)) { + WIIUSE_WARNING("Transmission is not necessary"); + /* delete this request */ + wm->data_req = req->next; + free(req); + return; + } + + + req->state = REQ_DONE; + + if (req->cb) { + /* this was a callback, so invoke it now */ + req->cb(wm, NULL, 0); + /* delete this request */ + wm->data_req = req->next; + free(req); + } else { + /* + * This should generate an event. + * We need to leave the event in the array so the client + * can access it still. We'll flag is as being 'REQ_DONE' + * and give the client one cycle to use it. Next event + * we will remove it from the list. + */ + wm->event = WIIUSE_WRITE_DATA; + + } + /* if another request exists send it to the wiimote */ + if (wm->data_req) { + wiiuse_send_next_pending_write_request(wm); + } +} + /** * @brief Read the controller status. * @@ -524,13 +474,19 @@ * Read the controller status and execute the registered status callback. */ static void event_status(struct wiimote_t* wm, byte* msg) { - int led[4] = {0}; + int led[4] = {0, 0, 0, 0}; int attachment = 0; int ir = 0; int exp_changed = 0; + struct data_req_t* req = wm->data_req; + /* initial handshake is not finished yet, ignore this */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_HANDSHAKE)) { + return; + } + /* - * An event occured. + * An event occurred. * This event can be overwritten by a more specific * event type during a handshake or expansion removal. */ @@ -539,28 +495,45 @@ wiiuse_pressed_buttons(wm, msg); /* find what LEDs are lit */ - if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_1) led[0] = 1; - if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_2) led[1] = 1; - if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_3) led[2] = 1; - if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_4) led[3] = 1; + if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_1) { + led[0] = 1; + } + if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_2) { + led[1] = 1; + } + if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_3) { + led[2] = 1; + } + if (msg[2] & WM_CTRL_STATUS_BYTE1_LED_4) { + led[3] = 1; + } + /* probe for Motion+ */ + if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_MPLUS_PRESENT)) { + wiiuse_probe_motion_plus(wm); + } + /* is an attachment connected to the expansion port? */ - if ((msg[2] & WM_CTRL_STATUS_BYTE1_ATTACHMENT) == WM_CTRL_STATUS_BYTE1_ATTACHMENT) + if ((msg[2] & WM_CTRL_STATUS_BYTE1_ATTACHMENT) == WM_CTRL_STATUS_BYTE1_ATTACHMENT) { + WIIUSE_DEBUG("Attachment detected!"); attachment = 1; + } /* is the speaker enabled? */ - if ((msg[2] & WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED) == WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED) + if ((msg[2] & WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED) == WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED) { WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_SPEAKER); + } /* is IR sensing enabled? */ - if ((msg[2] & WM_CTRL_STATUS_BYTE1_IR_ENABLED) == WM_CTRL_STATUS_BYTE1_IR_ENABLED) + if ((msg[2] & WM_CTRL_STATUS_BYTE1_IR_ENABLED) == WM_CTRL_STATUS_BYTE1_IR_ENABLED) { ir = 1; + } /* find the battery level and normalize between 0 and 1 */ wm->battery_level = (msg[5] / (float)WM_MAX_BATTERY_CODE); /* expansion port */ - if (attachment && !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) { + if (attachment && !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP) && !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP_HANDSHAKE)) { /* send the initialization code for the attachment */ handshake_expansion(wm, NULL, 0); exp_changed = 1; @@ -570,12 +543,12 @@ exp_changed = 1; } - #ifdef WIN32 +#ifdef WIIUSE_WIN32 if (!attachment) { WIIUSE_DEBUG("Setting timeout to normal %i ms.", wm->normal_timeout); wm->timeout = wm->normal_timeout; } - #endif +#endif /* * From now on the remote will only send status packets. @@ -584,13 +557,27 @@ */ if (exp_changed && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) { /* - * Since the expansion status changed IR needs to - * be reset for the new IR report mode. + * Since the expansion status changed IR needs to + * be reset for the new IR report mode. */ WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR); wiiuse_set_ir(wm, 1); - } else + } else { wiiuse_set_report_type(wm); + return; + } + + /* handling new Tx for changed exp */ + if (!req) { + return; + } + if (!(req->state == REQ_SENT)) { + return; + } + wm->data_req = req->next; + req->state = REQ_DONE; + /* if(req->cb!=NULL) req->cb(wm,msg,6); */ + free(req); } @@ -611,6 +598,14 @@ case EXP_GUITAR_HERO_3: guitar_hero_3_event(&wm->exp.gh3, msg); break; + case EXP_WII_BOARD: + wii_board_event(&wm->exp.wb, msg); + break; + case EXP_MOTION_PLUS: + case EXP_MOTION_PLUS_CLASSIC: + case EXP_MOTION_PLUS_NUNCHUK: + motion_plus_event(&wm->exp.mp, wm->exp.type, msg); + break; default: break; } @@ -630,64 +625,107 @@ * If the data is NULL then this function will try to start * a handshake with the expansion. */ -void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len) { +void handshake_expansion(struct wiimote_t* wm, byte* data, uint16_t len) { int id; + byte val = 0; + byte buf = 0x00; + byte* handshake_buf; + int gotIt = 0; + WIIUSE_DEBUG("handshake_expansion with state %d", wm->expansion_state); - if (!data) { - byte* handshake_buf; - byte buf = 0x00; + switch (wm->expansion_state) { + /* These two initialization writes disable the encryption */ + case 0: + wm->expansion_state = 1; + /* increase the timeout until the handshake completes */ +#ifdef WIIUSE_WIN32 + WIIUSE_DEBUG("write 0x55 - Setting timeout to expansion %i ms.", wm->exp_timeout); + wm->timeout = wm->exp_timeout; +#endif + buf = 0x55; + wiiuse_write_data_cb(wm, WM_EXP_MEM_ENABLE1, &buf, 1, handshake_expansion); + break; + case 1: + wm->expansion_state = 2; + /* increase the timeout until the handshake completes */ +#ifdef WIIUSE_WIN32 + WIIUSE_DEBUG("write 0x00 - Setting timeout to expansion %i ms.", wm->exp_timeout); + wm->timeout = wm->exp_timeout; +#endif + val = 0x00; + wiiuse_write_data_cb(wm, WM_EXP_MEM_ENABLE2, &buf, 1, handshake_expansion); + break; + case 2: + wm->expansion_state = 3; + /* get the calibration data */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) { + disable_expansion(wm); + } + handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte)); + /* tell the wiimote to send expansion data */ + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP); + wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN); + break; + case 3: + if (!data || !len) { + WIIUSE_DEBUG("no handshake data received from expansion"); + disable_expansion(wm); + return; + } + wm->expansion_state = 0; + id = from_big_endian_uint32_t(data + 220); + switch (id) { + case EXP_ID_CODE_NUNCHUK: + if (nunchuk_handshake(wm, &wm->exp.nunchuk, data, len)) { + wm->event = WIIUSE_NUNCHUK_INSERTED; + gotIt = 1; + } + break; - if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) - disable_expansion(wm); + case EXP_ID_CODE_CLASSIC_CONTROLLER: + if (classic_ctrl_handshake(wm, &wm->exp.classic, data, len)) { + wm->event = WIIUSE_CLASSIC_CTRL_INSERTED; + gotIt = 1; + } + break; - /* increase the timeout until the handshake completes */ - #ifdef WIN32 - WIIUSE_DEBUG("Setting timeout to expansion %i ms.", wm->exp_timeout); - wm->timeout = wm->exp_timeout; - #endif + case EXP_ID_CODE_GUITAR: + if (guitar_hero_3_handshake(wm, &wm->exp.gh3, data, len)) { + wm->event = WIIUSE_GUITAR_HERO_3_CTRL_INSERTED; + gotIt = 1; + } + break; - wiiuse_write_data(wm, WM_EXP_MEM_ENABLE, &buf, 1); + case EXP_ID_CODE_MOTION_PLUS: + case EXP_ID_CODE_MOTION_PLUS_CLASSIC: + case EXP_ID_CODE_MOTION_PLUS_NUNCHUK: + /* wiiuse_motion_plus_handshake(wm, data, len); */ + wm->event = WIIUSE_MOTION_PLUS_ACTIVATED; + gotIt = 1; + break; - /* get the calibration data */ - handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte)); - wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN); + case EXP_ID_CODE_WII_BOARD: + if (wii_board_handshake(wm, &wm->exp.wb, data, len)) { + wm->event = WIIUSE_WII_BOARD_CTRL_INSERTED; + gotIt = 1; + } + break; - /* tell the wiimote to send expansion data */ - WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP); - - return; - } - - id = BIG_ENDIAN_LONG(*(int*)(data + 220)); - - /* call the corresponding handshake function for this expansion */ - switch (id) { - case EXP_ID_CODE_NUNCHUK: - { - if (nunchuk_handshake(wm, &wm->exp.nunchuk, data, len)) - wm->event = WIIUSE_NUNCHUK_INSERTED; + default: + WIIUSE_WARNING("Unknown expansion type. Code: 0x%x", id); + break; + } + free(data); + if (gotIt) { + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE); + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP); + } else { + WIIUSE_WARNING("Could not handshake with expansion id: 0x%x", id); + } + wiiuse_set_ir_mode(wm); + wiiuse_status(wm); break; - } - case EXP_ID_CODE_CLASSIC_CONTROLLER: - { - if (classic_ctrl_handshake(wm, &wm->exp.classic, data, len)) - wm->event = WIIUSE_CLASSIC_CTRL_INSERTED; - break; - } - case EXP_ID_CODE_GUITAR: - { - if (guitar_hero_3_handshake(wm, &wm->exp.gh3, data, len)) - wm->event = WIIUSE_GUITAR_HERO_3_CTRL_INSERTED; - break; - } - default: - { - WIIUSE_WARNING("Unknown expansion type. Code: 0x%x", id); - break; - } } - - free(data); } @@ -703,10 +741,12 @@ * a handshake with the expansion. */ void disable_expansion(struct wiimote_t* wm) { - if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) + WIIUSE_DEBUG("Disabling expansion"); + if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) { return; + } - /* tell the assoicated module the expansion was removed */ + /* tell the associated module the expansion was removed */ switch (wm->exp.type) { case EXP_NUNCHUK: nunchuk_disconnected(&wm->exp.nunchuk); @@ -720,12 +760,23 @@ guitar_hero_3_disconnected(&wm->exp.gh3); wm->event = WIIUSE_GUITAR_HERO_3_CTRL_REMOVED; break; + case EXP_WII_BOARD: + wii_board_disconnected(&wm->exp.wb); + wm->event = WIIUSE_WII_BOARD_CTRL_REMOVED; + break; + case EXP_MOTION_PLUS: + case EXP_MOTION_PLUS_CLASSIC: + case EXP_MOTION_PLUS_NUNCHUK: + motion_plus_disconnected(&wm->exp.mp); + wm->event = WIIUSE_MOTION_PLUS_REMOVED; + break; default: break; } WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP); wm->exp.type = EXP_NONE; + wm->expansion_state = 0; } @@ -771,6 +822,38 @@ wm->lstate.exp_btns = wm->exp.gh3.btns; break; + case EXP_WII_BOARD: + wm->lstate.exp_wb_rtr = wm->exp.wb.rtr; + wm->lstate.exp_wb_rtl = wm->exp.wb.rtl; + wm->lstate.exp_wb_rbr = wm->exp.wb.rbr; + wm->lstate.exp_wb_rbl = wm->exp.wb.rbl; + break; + + case EXP_MOTION_PLUS: + case EXP_MOTION_PLUS_CLASSIC: + case EXP_MOTION_PLUS_NUNCHUK: { + wm->lstate.drx = wm->exp.mp.raw_gyro.pitch; + wm->lstate.dry = wm->exp.mp.raw_gyro.roll; + wm->lstate.drz = wm->exp.mp.raw_gyro.yaw; + + if (wm->exp.type == EXP_MOTION_PLUS_CLASSIC) { + wm->lstate.exp_ljs_ang = wm->exp.classic.ljs.ang; + wm->lstate.exp_ljs_mag = wm->exp.classic.ljs.mag; + wm->lstate.exp_rjs_ang = wm->exp.classic.rjs.ang; + wm->lstate.exp_rjs_mag = wm->exp.classic.rjs.mag; + wm->lstate.exp_r_shoulder = wm->exp.classic.r_shoulder; + wm->lstate.exp_l_shoulder = wm->exp.classic.l_shoulder; + wm->lstate.exp_btns = wm->exp.classic.btns; + } else { + wm->lstate.exp_ljs_ang = wm->exp.nunchuk.js.ang; + wm->lstate.exp_ljs_mag = wm->exp.nunchuk.js.mag; + wm->lstate.exp_btns = wm->exp.nunchuk.btns; + wm->lstate.exp_accel = wm->exp.nunchuk.accel; + } + + break; + } + case EXP_NONE: break; } @@ -780,12 +863,12 @@ /** * @brief Determine if the current state differs significantly from the previous. * @param wm A pointer to a wiimote_t structure. - * @return 1 if a significant change occured, 0 if not. + * @return 1 if a significant change occurred, 0 if not. */ static int state_changed(struct wiimote_t* wm) { - #define STATE_CHANGED(a, b) if (a != b) return 1 +#define STATE_CHANGED(a, b) if (a != b) return 1 - #define CROSS_THRESH(last, now, thresh) \ +#define CROSS_THRESH(last, now, thresh) \ do { \ if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) { \ if ((diff_f(last.roll, now.roll) >= thresh) || \ @@ -802,7 +885,7 @@ } \ } while (0) - #define CROSS_THRESH_XYZ(last, now, thresh) \ +#define CROSS_THRESH_XYZ(last, now, thresh) \ do { \ if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) { \ if ((diff_f(last.x, now.x) >= thresh) || \ @@ -832,44 +915,74 @@ CROSS_THRESH_XYZ(wm->lstate.accel, wm->accel, wm->accel_threshold); /* orientation */ - CROSS_THRESH(wm->lstate.orient, wm->orient, wm->orient_threshold); + CROSS_THRESH(wm->lstate.orient, wm->orient, wm->orient_threshold); } /* expansion */ switch (wm->exp.type) { - case EXP_NUNCHUK: - { - STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.nunchuk.js.ang); - STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.nunchuk.js.mag); - STATE_CHANGED(wm->lstate.exp_btns, wm->exp.nunchuk.btns); + case EXP_NUNCHUK: { + STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.nunchuk.js.ang); + STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.nunchuk.js.mag); + STATE_CHANGED(wm->lstate.exp_btns, wm->exp.nunchuk.btns); - CROSS_THRESH(wm->lstate.exp_orient, wm->exp.nunchuk.orient, wm->exp.nunchuk.orient_threshold); - CROSS_THRESH_XYZ(wm->lstate.exp_accel, wm->exp.nunchuk.accel, wm->exp.nunchuk.accel_threshold); - break; - } - case EXP_CLASSIC: - { - STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.classic.ljs.ang); - STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.classic.ljs.mag); - STATE_CHANGED(wm->lstate.exp_rjs_ang, wm->exp.classic.rjs.ang); - STATE_CHANGED(wm->lstate.exp_rjs_mag, wm->exp.classic.rjs.mag); - STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.classic.r_shoulder); - STATE_CHANGED(wm->lstate.exp_l_shoulder, wm->exp.classic.l_shoulder); - STATE_CHANGED(wm->lstate.exp_btns, wm->exp.classic.btns); - break; - } - case EXP_GUITAR_HERO_3: - { - STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.gh3.js.ang); - STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.gh3.js.mag); - STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.gh3.whammy_bar); - STATE_CHANGED(wm->lstate.exp_btns, wm->exp.gh3.btns); - break; - } - case EXP_NONE: - { - break; - } + CROSS_THRESH(wm->lstate.exp_orient, wm->exp.nunchuk.orient, wm->exp.nunchuk.orient_threshold); + CROSS_THRESH_XYZ(wm->lstate.exp_accel, wm->exp.nunchuk.accel, wm->exp.nunchuk.accel_threshold); + break; + } + case EXP_CLASSIC: { + STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.classic.ljs.ang); + STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.classic.ljs.mag); + STATE_CHANGED(wm->lstate.exp_rjs_ang, wm->exp.classic.rjs.ang); + STATE_CHANGED(wm->lstate.exp_rjs_mag, wm->exp.classic.rjs.mag); + STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.classic.r_shoulder); + STATE_CHANGED(wm->lstate.exp_l_shoulder, wm->exp.classic.l_shoulder); + STATE_CHANGED(wm->lstate.exp_btns, wm->exp.classic.btns); + break; + } + case EXP_GUITAR_HERO_3: { + STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.gh3.js.ang); + STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.gh3.js.mag); + STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.gh3.whammy_bar); + STATE_CHANGED(wm->lstate.exp_btns, wm->exp.gh3.btns); + break; + } + case EXP_WII_BOARD: { + STATE_CHANGED(wm->lstate.exp_wb_rtr, wm->exp.wb.tr); + STATE_CHANGED(wm->lstate.exp_wb_rtl, wm->exp.wb.tl); + STATE_CHANGED(wm->lstate.exp_wb_rbr, wm->exp.wb.br); + STATE_CHANGED(wm->lstate.exp_wb_rbl, wm->exp.wb.bl); + break; + } + + case EXP_MOTION_PLUS: + case EXP_MOTION_PLUS_CLASSIC: + case EXP_MOTION_PLUS_NUNCHUK: { + STATE_CHANGED(wm->lstate.drx, wm->exp.mp.raw_gyro.pitch); + STATE_CHANGED(wm->lstate.dry, wm->exp.mp.raw_gyro.roll); + STATE_CHANGED(wm->lstate.drz, wm->exp.mp.raw_gyro.yaw); + + if (wm->exp.type == EXP_MOTION_PLUS_CLASSIC) { + STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.classic.ljs.ang); + STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.classic.ljs.mag); + STATE_CHANGED(wm->lstate.exp_rjs_ang, wm->exp.classic.rjs.ang); + STATE_CHANGED(wm->lstate.exp_rjs_mag, wm->exp.classic.rjs.mag); + STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->exp.classic.r_shoulder); + STATE_CHANGED(wm->lstate.exp_l_shoulder, wm->exp.classic.l_shoulder); + STATE_CHANGED(wm->lstate.exp_btns, wm->exp.classic.btns); + } else { + STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->exp.nunchuk.js.ang); + STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->exp.nunchuk.js.mag); + STATE_CHANGED(wm->lstate.exp_btns, wm->exp.nunchuk.btns); + + CROSS_THRESH(wm->lstate.exp_orient, wm->exp.nunchuk.orient, wm->exp.nunchuk.orient_threshold); + CROSS_THRESH_XYZ(wm->lstate.exp_accel, wm->exp.nunchuk.accel, wm->exp.nunchuk.accel_threshold); + } + + break; + } + case EXP_NONE: { + break; + } } STATE_CHANGED(wm->lstate.btns, wm->btns); Modified: main/trunk/lib/wiiuse/events.h =================================================================== --- main/trunk/lib/wiiuse/events.h 2013-01-24 21:44:06 UTC (rev 12414) +++ main/trunk/lib/wiiuse/events.h 2013-01-24 22:53:34 UTC (rev 12415) @@ -37,18 +37,28 @@ #ifndef EVENTS_H_INCLUDED #define EVENTS_H_INCLUDED -#ifdef __cplusplus -extern "C" { +#if defined(_MSC_VER) +/* MS compilers of pre-VC2010 versions don't have stdint.h + * and I can't get VC2010's stdint.h to compile nicely in + * WiiUse + */ + #include "wiiuse_msvcstdint.h" +#else + #include <stdint.h> #endif + +/** @defgroup internal_events Internal: Event Utilities */ +/** @{ */ void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg); -void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len); +void handshake_expansion(struct wiimote_t* wm, byte* data, uint16_t len); void disable_expansion(struct wiimote_t* wm); -#ifdef __cplusplus -} -#endif +void propagate_event(struct wiimote_t* wm, byte event, byte* msg); +void idle_cycle(struct wiimote_t* wm); +void clear_dirty_reads(struct wiimote_t* wm); +/** @} */ -#endif // EVENTS_H_INCLUDED +#endif /* EVENTS_H_INCLUDED */ Modified: main/trunk/lib/wiiuse/guitar_hero_3.c =================================================================== --- main/trunk/lib/wiiuse/guitar_hero_3.c 2013-01-24 21:44:06 UTC (rev 12414) +++ main/trunk/lib/wiiuse/guitar_hero_3.c 2013-01-24 22:53:34 UTC (rev 12415) @@ -31,19 +31,13 @@ * @brief Guitar Hero 3 expansion device. */ -#include <stdio.h> -#include <stdlib.h> -#include <math.h> +#include "guitar_hero_3.h" -#ifdef WIN32 - #include <Winsock2.h> -#endif +#include "dynamics.h" /* for calc_joystick_state */ +#include "events.h" /* for handshake_expansion */ -#include "definitions.h" -#include "wiiuse_internal.h" -#include "dynamics.h" -#include "events.h" -#include "guitar_hero_3.h" +#include <stdlib.h> /* for malloc */ +#include <string.h> /* for memset */ static void guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now); @@ -57,8 +51,6 @@ * @return Returns 1 if handshake was successful, 0 if not. */ int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len) { - int i; - int offset = 0; /* * The good fellows that made the Guitar Hero 3 controller @@ -71,11 +63,11 @@ gh3->btns_released = 0; gh3->whammy_bar = 0.0f; - /* decrypt data */ - for (i = 0; i < len; ++i) - data[i] = (data[i] ^ 0x17) + 0x17; - - if (data[offset] == 0xFF) { + /* + TODO: If we're not using anything from calibration data, why are we + even bothering here? + */ + if (data[0] == 0xFF) { /* * Sometimes the data returned here is not correct. * This might happen because the wiimote is lagging @@ -86,7 +78,7 @@ * but since the next 16 bytes are the same, just use * those. */ - if (data[offset + 16] == 0xFF) { + if (data[16] == 0xFF) { /* get the calibration data */ byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte)); @@ -94,8 +86,9 @@ wiiuse_read_data_cb(wm, handshake_expansion, handshake_buf, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN); return 0; - } else - offset += 16; + } else { + data += 16; + } } /* joystick stuff */ @@ -109,9 +102,9 @@ /* handshake done */ wm->exp.type = EXP_GUITAR_HERO_3; - #ifdef WIN32 +#ifdef WIIUSE_WIN32 wm->timeout = WIIMOTE_DEFAULT_TIMEOUT; - #endif +#endif return 1; } @@ -135,14 +128,9 @@ * @param msg The message specified in the event packet. */ void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg) { - int i; - /* decrypt data */ - for (i = 0; i < 6; ++i) - msg[i] = (msg[i] ^ 0x17) + 0x17; + guitar_hero_3_pressed_buttons(gh3, from_big_endian_uint16_t(msg + 4)); - guitar_hero_3_pressed_buttons(gh3, BIG_ENDIAN_SHORT(*(short*)(msg + 4))); - /* whammy bar */ gh3->whammy_bar = (msg[3] - GUITAR_HERO_3_WHAMMY_BAR_MIN) / (float)(GUITAR_HERO_3_WHAMMY_BAR_MAX - GUITAR_HERO_3_WHAMMY_BAR_MIN); Modified: main/trunk/lib/wiiuse/guitar_hero_3.h =================================================================== --- main/trunk/lib/wiiuse/guitar_hero_3.h 2013-01-24 21:44:06 UTC (rev 12414) +++ main/trunk/lib/wiiuse/guitar_hero_3.h 2013-01-24 22:53:34 UTC (rev 12415) @@ -49,14 +49,18 @@ extern "C" { #endif -int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len); -void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3); + /** @defgroup internal_gh3 Internal: Guitar Hero 3 controller */ + /** @{ */ + int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, byte* data, unsigned short len); -void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg); + void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3); + void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg); + /** @} */ + #ifdef __cplusplus } #endif -#endif // GUITAR_HERO_3_H_INCLUDED +#endif /* GUITAR_HERO_3_H_INCLUDED */ Modified: main/trunk/lib/wiiuse/io.c =================================================================== --- main/trunk/lib/wiiuse/io.c 2013-01-24 21:44:06 UTC (rev 12414) +++ main/trunk/lib/wiiuse/io.c 2013-01-24 22:53:34 UTC (rev 12415) @@ -31,15 +31,162 @@ * @brief Handles device I/O (non-OS specific). */ -#include <stdio.h> -#include <stdlib.h> - -#include "definitions.h" +#include "io.h" +#include "ir.h" /* for wiiuse_set_ir_mode */ #include "wiiuse_internal.h" -#include "io.h" +#include "os.h" /* for wiiuse_os_* */ - /** +#include <stdlib.h> /* for free, malloc */ + +/** + * @brief Find a wiimote or wiimotes. + * + * @param wm An array of wiimote_t structures. + * @param max_wiimotes The number of wiimote structures in \a wm. + * @param timeout The number of seconds before the search times out. + * + * @return The number of wiimotes found. + * + * @see wiiuse_connect() + * @see wiiuse_os_find() + * + * This function will only look for wiimote devices. \n + * When a device is found the address in the structures will be set. \n + * You can then call wiiuse_connect() to connect to the found \n + * devices. + * + * This function only delegates to the platform-specific implementation + * wiiuse_os_find. + * + * This function is declared in wiiuse.h + */ +int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { + return wiiuse_os_find(wm, max_wiimotes, timeout); +} + +/** + * @brief Connect to a wiimote or wiimotes once an address is known. + * + * @param wm An array of wiimote_t structures. + * @param wiimotes The number of wiimote structures in \a wm. + * + * @return The number of wiimotes that successfully connected. + * + * @see wiiuse_find() + * @see wiiuse_disconnect() + * @see wiiuse_os_connect() + * + * Connect to a number of wiimotes when the address is already set + * in the wiimote_t structures. These addresses are normally set + * by the wiiuse_find() function, but can also be set manually. + * + * This function only delegates to the platform-specific implementation + * wiiuse_os_connect. + * + * This function is declared in wiiuse.h + */ +int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { + return wiiuse_os_connect(wm, wiimotes); +} + +/** + * @brief Disconnect a wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * + * @see wiiuse_connect() + * @see wiiuse_os_disconnect() + * + * Note that this will not free the wiimote structure. + * + * This function only delegates to the platform-specific implementation + * wiiuse_os_disconnect. + * + * This function is declared in wiiuse.h + */ +void wiiuse_disconnect(struct wiimote_t* wm) { + wiiuse_os_disconnect(wm); +} + +/** +* @brief Wait until specified report arrives and return it +* +* @param wm Pointer to a wiimote_t structure. +* @param buffer Pre-allocated memory to store the received data +* @param bufferLength size of buffer in bytes +* +* Synchronous/blocking, this function will not return until it receives the specified +* report from the Wiimote. +* +*/ +void wiiuse_wait_report(struct wiimote_t *wm, int report, byte *buffer, int bufferLength) { + for (;;) { + if (wiiuse_os_read(wm, buffer, bufferLength) > 0) { + if (buffer[0] == report) { + break; + } else { + WIIUSE_DEBUG("(id %i) dropping report 0x%x, waiting for 0x%x", wm->unid, buffer[0], report); + } + } + } +} + +/** +* @brief Read memory/register data synchronously +* +* @param wm Pointer to a wiimote_t structure. +* @param memory If set to non-zero, reads EEPROM, otherwise registers +* @param addr Address offset to read from +* @param size How many... [truncated message content] |