From c208b1bc60573add9635a2d05df906fd476a1019 Mon Sep 17 00:00:00 2001 From: "fires.gc" Date: Wed, 5 Nov 2008 16:46:30 +0000 Subject: [PATCH] added special wiiuse version git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1072 8ced0084-cf51-0410-be5f-012b33b47a6e --- Externals/WiiUse/Inc/wiiuse.h | 657 ++++++++++++++++ Externals/WiiUse/Win32/wiiuse.dll | Bin 0 -> 104960 bytes Externals/WiiUse/Win32/wiiuse.lib | Bin 0 -> 8610 bytes Externals/WiiUse/X64/wiiuse.dll | Bin 0 -> 103424 bytes Externals/WiiUse/X64/wiiuse.lib | Bin 0 -> 8462 bytes Externals/WiiUseSrc/Src/Makefile | 91 +++ Externals/WiiUseSrc/Src/classic.c | 190 +++++ Externals/WiiUseSrc/Src/classic.h | 53 ++ Externals/WiiUseSrc/Src/definitions.h | 79 ++ Externals/WiiUseSrc/Src/dynamics.c | 228 ++++++ Externals/WiiUseSrc/Src/dynamics.h | 56 ++ Externals/WiiUseSrc/Src/events.c | 878 ++++++++++++++++++++++ Externals/WiiUseSrc/Src/events.h | 54 ++ Externals/WiiUseSrc/Src/guitar_hero_3.c | 172 +++++ Externals/WiiUseSrc/Src/guitar_hero_3.h | 62 ++ Externals/WiiUseSrc/Src/io.c | 119 +++ Externals/WiiUseSrc/Src/io.h | 56 ++ Externals/WiiUseSrc/Src/io_nix.c | 270 +++++++ Externals/WiiUseSrc/Src/io_win.c | 247 ++++++ Externals/WiiUseSrc/Src/ir.c | 748 ++++++++++++++++++ Externals/WiiUseSrc/Src/ir.h | 56 ++ Externals/WiiUseSrc/Src/nunchuk.c | 210 ++++++ Externals/WiiUseSrc/Src/nunchuk.h | 53 ++ Externals/WiiUseSrc/Src/os.h | 56 ++ Externals/WiiUseSrc/Src/wiiuse.c | 764 +++++++++++++++++++ Externals/WiiUseSrc/Src/wiiuse.h | 657 ++++++++++++++++ Externals/WiiUseSrc/Src/wiiuse_internal.h | 226 ++++++ Externals/WiiUseSrc/wiiuse.sln | 26 + Externals/WiiUseSrc/wiiuse.suo | Bin 0 -> 32768 bytes Externals/WiiUseSrc/wiiuse.vcproj | 508 +++++++++++++ 30 files changed, 6516 insertions(+) create mode 100644 Externals/WiiUse/Inc/wiiuse.h create mode 100644 Externals/WiiUse/Win32/wiiuse.dll create mode 100644 Externals/WiiUse/Win32/wiiuse.lib create mode 100644 Externals/WiiUse/X64/wiiuse.dll create mode 100644 Externals/WiiUse/X64/wiiuse.lib create mode 100644 Externals/WiiUseSrc/Src/Makefile create mode 100644 Externals/WiiUseSrc/Src/classic.c create mode 100644 Externals/WiiUseSrc/Src/classic.h create mode 100644 Externals/WiiUseSrc/Src/definitions.h create mode 100644 Externals/WiiUseSrc/Src/dynamics.c create mode 100644 Externals/WiiUseSrc/Src/dynamics.h create mode 100644 Externals/WiiUseSrc/Src/events.c create mode 100644 Externals/WiiUseSrc/Src/events.h create mode 100644 Externals/WiiUseSrc/Src/guitar_hero_3.c create mode 100644 Externals/WiiUseSrc/Src/guitar_hero_3.h create mode 100644 Externals/WiiUseSrc/Src/io.c create mode 100644 Externals/WiiUseSrc/Src/io.h create mode 100644 Externals/WiiUseSrc/Src/io_nix.c create mode 100644 Externals/WiiUseSrc/Src/io_win.c create mode 100644 Externals/WiiUseSrc/Src/ir.c create mode 100644 Externals/WiiUseSrc/Src/ir.h create mode 100644 Externals/WiiUseSrc/Src/nunchuk.c create mode 100644 Externals/WiiUseSrc/Src/nunchuk.h create mode 100644 Externals/WiiUseSrc/Src/os.h create mode 100644 Externals/WiiUseSrc/Src/wiiuse.c create mode 100644 Externals/WiiUseSrc/Src/wiiuse.h create mode 100644 Externals/WiiUseSrc/Src/wiiuse_internal.h create mode 100644 Externals/WiiUseSrc/wiiuse.sln create mode 100644 Externals/WiiUseSrc/wiiuse.suo create mode 100644 Externals/WiiUseSrc/wiiuse.vcproj diff --git a/Externals/WiiUse/Inc/wiiuse.h b/Externals/WiiUse/Inc/wiiuse.h new file mode 100644 index 0000000000..a70dc9e344 --- /dev/null +++ b/Externals/WiiUse/Inc/wiiuse.h @@ -0,0 +1,657 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * + * @brief API header file. + * + * If this file is included from inside the wiiuse source + * and not from a third party program, then wiimote_internal.h + * is also included which extends this file. + */ + +#ifndef WIIUSE_H_INCLUDED +#define WIIUSE_H_INCLUDED + +#ifdef _WIN32 + /* windows */ + #include +#else + /* nix */ + #include +#endif + +#ifdef WIIUSE_INTERNAL_H_INCLUDED + #define WCONST +#else + #define WCONST const +#endif + +/* led bit masks */ +#define WIIMOTE_LED_NONE 0x00 +#define WIIMOTE_LED_1 0x10 +#define WIIMOTE_LED_2 0x20 +#define WIIMOTE_LED_3 0x40 +#define WIIMOTE_LED_4 0x80 + +/* button codes */ +#define WIIMOTE_BUTTON_TWO 0x0001 +#define WIIMOTE_BUTTON_ONE 0x0002 +#define WIIMOTE_BUTTON_B 0x0004 +#define WIIMOTE_BUTTON_A 0x0008 +#define WIIMOTE_BUTTON_MINUS 0x0010 +#define WIIMOTE_BUTTON_ZACCEL_BIT6 0x0020 +#define WIIMOTE_BUTTON_ZACCEL_BIT7 0x0040 +#define WIIMOTE_BUTTON_HOME 0x0080 +#define WIIMOTE_BUTTON_LEFT 0x0100 +#define WIIMOTE_BUTTON_RIGHT 0x0200 +#define WIIMOTE_BUTTON_DOWN 0x0400 +#define WIIMOTE_BUTTON_UP 0x0800 +#define WIIMOTE_BUTTON_PLUS 0x1000 +#define WIIMOTE_BUTTON_ZACCEL_BIT4 0x2000 +#define WIIMOTE_BUTTON_ZACCEL_BIT5 0x4000 +#define WIIMOTE_BUTTON_UNKNOWN 0x8000 +#define WIIMOTE_BUTTON_ALL 0x1F9F + +/* nunchul button codes */ +#define NUNCHUK_BUTTON_Z 0x01 +#define NUNCHUK_BUTTON_C 0x02 +#define NUNCHUK_BUTTON_ALL 0x03 + +/* classic controller button codes */ +#define CLASSIC_CTRL_BUTTON_UP 0x0001 +#define CLASSIC_CTRL_BUTTON_LEFT 0x0002 +#define CLASSIC_CTRL_BUTTON_ZR 0x0004 +#define CLASSIC_CTRL_BUTTON_X 0x0008 +#define CLASSIC_CTRL_BUTTON_A 0x0010 +#define CLASSIC_CTRL_BUTTON_Y 0x0020 +#define CLASSIC_CTRL_BUTTON_B 0x0040 +#define CLASSIC_CTRL_BUTTON_ZL 0x0080 +#define CLASSIC_CTRL_BUTTON_FULL_R 0x0200 +#define CLASSIC_CTRL_BUTTON_PLUS 0x0400 +#define CLASSIC_CTRL_BUTTON_HOME 0x0800 +#define CLASSIC_CTRL_BUTTON_MINUS 0x1000 +#define CLASSIC_CTRL_BUTTON_FULL_L 0x2000 +#define CLASSIC_CTRL_BUTTON_DOWN 0x4000 +#define CLASSIC_CTRL_BUTTON_RIGHT 0x8000 +#define CLASSIC_CTRL_BUTTON_ALL 0xFEFF + +/* guitar hero 3 button codes */ +#define GUITAR_HERO_3_BUTTON_STRUM_UP 0x0001 +#define GUITAR_HERO_3_BUTTON_YELLOW 0x0008 +#define GUITAR_HERO_3_BUTTON_GREEN 0x0010 +#define GUITAR_HERO_3_BUTTON_BLUE 0x0020 +#define GUITAR_HERO_3_BUTTON_RED 0x0040 +#define GUITAR_HERO_3_BUTTON_ORANGE 0x0080 +#define GUITAR_HERO_3_BUTTON_PLUS 0x0400 +#define GUITAR_HERO_3_BUTTON_MINUS 0x1000 +#define GUITAR_HERO_3_BUTTON_STRUM_DOWN 0x4000 +#define GUITAR_HERO_3_BUTTON_ALL 0xFEFF + + +/* wiimote option flags */ +#define WIIUSE_SMOOTHING 0x01 +#define WIIUSE_CONTINUOUS 0x02 +#define WIIUSE_ORIENT_THRESH 0x04 +#define WIIUSE_INIT_FLAGS (WIIUSE_SMOOTHING | WIIUSE_ORIENT_THRESH) + +#define WIIUSE_ORIENT_PRECISION 100.0f + +/* expansion codes */ +#define EXP_NONE 0 +#define EXP_NUNCHUK 1 +#define EXP_CLASSIC 2 +#define EXP_GUITAR_HERO_3 3 + +/* IR correction types */ +typedef enum ir_position_t { + WIIUSE_IR_ABOVE, + WIIUSE_IR_BELOW +} ir_position_t; + +/** + * @brief Check if a button is pressed. + * @param dev Pointer to a wiimote_t or expansion structure. + * @param button The button you are interested in. + * @return 1 if the button is pressed, 0 if not. + */ +#define IS_PRESSED(dev, button) ((dev->btns & button) == button) + +/** + * @brief Check if a button is being held. + * @param dev Pointer to a wiimote_t or expansion structure. + * @param button The button you are interested in. + * @return 1 if the button is held, 0 if not. + */ +#define IS_HELD(dev, button) ((dev->btns_held & button) == button) + +/** + * @brief Check if a button is released on this event. \n\n + * This does not mean the button is not pressed, it means \n + * this button was just now released. + * @param dev Pointer to a wiimote_t or expansion structure. + * @param button The button you are interested in. + * @return 1 if the button is released, 0 if not. + * + */ +#define IS_RELEASED(dev, button) ((dev->btns_released & button) == button) + +/** + * @brief Check if a button has just been pressed this event. + * @param dev Pointer to a wiimote_t or expansion structure. + * @param button The button you are interested in. + * @return 1 if the button is pressed, 0 if not. + */ +#define IS_JUST_PRESSED(dev, button) (IS_PRESSED(dev, button) && !IS_HELD(dev, button)) + +/** + * @brief Return the IR sensitivity level. + * @param wm Pointer to a wiimote_t structure. + * @param lvl [out] Pointer to an int that will hold the level setting. + * If no level is set 'lvl' will be set to 0. + */ +#define WIIUSE_GET_IR_SENSITIVITY(dev, lvl) \ + do { \ + if ((wm->state & 0x0200) == 0x0200) *lvl = 1; \ + else if ((wm->state & 0x0400) == 0x0400) *lvl = 2; \ + else if ((wm->state & 0x0800) == 0x0800) *lvl = 3; \ + else if ((wm->state & 0x1000) == 0x1000) *lvl = 4; \ + else if ((wm->state & 0x2000) == 0x2000) *lvl = 5; \ + else *lvl = 0; \ + } while (0) + +#define WIIUSE_USING_ACC(wm) ((wm->state & 0x020) == 0x020) +#define WIIUSE_USING_EXP(wm) ((wm->state & 0x040) == 0x040) +#define WIIUSE_USING_IR(wm) ((wm->state & 0x080) == 0x080) +#define WIIUSE_USING_SPEAKER(wm) ((wm->state & 0x100) == 0x100) + +#define WIIUSE_IS_LED_SET(wm, num) ((wm->leds & WIIMOTE_LED_##num) == WIIMOTE_LED_##num) + +/* + * Largest known payload is 21 bytes. + * Add 2 for the prefix and round up to a power of 2. + */ +#define MAX_PAYLOAD 32 + +/* + * This is left over from an old hack, but it may actually + * be a useful feature to keep so it wasn't removed. + */ +#ifdef WIN32 + #define WIIMOTE_DEFAULT_TIMEOUT 10 + #define WIIMOTE_EXP_TIMEOUT 10 +#endif + +typedef unsigned char byte; +typedef char sbyte; + +struct wiimote_t; +struct vec3b_t; +struct orient_t; +struct gforce_t; + + +/** + * @brief Callback that handles a read event. + * + * @param wm Pointer to a wiimote_t structure. + * @param data Pointer to the filled data block. + * @param len Length in bytes of the data block. + * + * @see wiiuse_init() + * + * A registered function of this type is called automatically by the wiiuse + * library when the wiimote has returned the full data requested by a previous + * call to wiiuse_read_data(). + */ +typedef void (*wiiuse_read_cb)(struct wiimote_t* wm, byte* data, unsigned short len); + + +/** + * @struct read_req_t + * @brief Data read request structure. + */ +struct read_req_t { + wiiuse_read_cb cb; /**< read data callback */ + byte* buf; /**< buffer where read data is written */ + unsigned int addr; /**< the offset that the read started at */ + unsigned short size; /**< the length of the data read */ + unsigned short wait; /**< num bytes still needed to finish read */ + byte dirty; /**< set to 1 if not using callback and needs to be cleaned up */ + + struct read_req_t* next; /**< next read request in the queue */ +}; + + +/** + * @struct vec2b_t + * @brief Unsigned x,y byte vector. + */ +typedef struct vec2b_t { + byte x, y; +} vec2b_t; + + +/** + * @struct vec3b_t + * @brief Unsigned x,y,z byte vector. + */ +typedef struct vec3b_t { + byte x, y, z; +} vec3b_t; + + +/** + * @struct vec3f_t + * @brief Signed x,y,z float struct. + */ +typedef struct vec3f_t { + float x, y, z; +} vec3f_t; + + +/** + * @struct orient_t + * @brief Orientation struct. + * + * Yaw, pitch, and roll range from -180 to 180 degrees. + */ +typedef struct orient_t { + float roll; /**< roll, this may be smoothed if enabled */ + float pitch; /**< pitch, this may be smoothed if enabled */ + float yaw; + + float a_roll; /**< absolute roll, unsmoothed */ + float a_pitch; /**< absolute pitch, unsmoothed */ +} orient_t; + + +/** + * @struct gforce_t + * @brief Gravity force struct. + */ +typedef struct gforce_t { + float x, y, z; +} gforce_t; + + +/** + * @struct accel_t + * @brief Accelerometer struct. For any device with an accelerometer. + */ +typedef struct accel_t { + struct vec3b_t cal_zero; /**< zero calibration */ + struct vec3b_t cal_g; /**< 1g difference around 0cal */ + + float st_roll; /**< last smoothed roll value */ + float st_pitch; /**< last smoothed roll pitch */ + float st_alpha; /**< alpha value for smoothing [0-1] */ +} accel_t; + + +/** + * @struct ir_dot_t + * @brief A single IR source. + */ +typedef struct ir_dot_t { + byte visible; /**< if the IR source is visible */ + + unsigned int x; /**< interpolated X coordinate */ + unsigned int y; /**< interpolated Y coordinate */ + + short rx; /**< raw X coordinate (0-1023) */ + short ry; /**< raw Y coordinate (0-767) */ + + byte order; /**< increasing order by x-axis value */ + + byte size; /**< size of the IR dot (0-15) */ +} ir_dot_t; + + +/** + * @enum aspect_t + * @brief Screen aspect ratio. + */ +typedef enum aspect_t { + WIIUSE_ASPECT_4_3, + WIIUSE_ASPECT_16_9 +} aspect_t; + + +/** + * @struct ir_t + * @brief IR struct. Hold all data related to the IR tracking. + */ +typedef struct ir_t { + struct ir_dot_t dot[4]; /**< IR dots */ + byte num_dots; /**< number of dots at this time */ + + enum aspect_t aspect; /**< aspect ratio of the screen */ + + enum ir_position_t pos; /**< IR sensor bar position */ + + unsigned int vres[2]; /**< IR virtual screen resolution */ + int offset[2]; /**< IR XY correction offset */ + int state; /**< keeps track of the IR state */ + + int ax; /**< absolute X coordinate */ + int ay; /**< absolute Y coordinate */ + + int x; /**< calculated X coordinate */ + int y; /**< calculated Y coordinate */ + + float distance; /**< pixel distance between first 2 dots*/ + float z; /**< calculated distance */ +} ir_t; + + +/** + * @struct joystick_t + * @brief Joystick calibration structure. + * + * The angle \a ang is relative to the positive y-axis into quadrant I + * and ranges from 0 to 360 degrees. So if the joystick is held straight + * upwards then angle is 0 degrees. If it is held to the right it is 90, + * down is 180, and left is 270. + * + * The magnitude \a mag is the distance from the center to where the + * joystick is being held. The magnitude ranges from 0 to 1. + * If the joystick is only slightly tilted from the center the magnitude + * will be low, but if it is closer to the outter edge the value will + * be higher. + */ +typedef struct joystick_t { + struct vec2b_t max; /**< maximum joystick values */ + struct vec2b_t min; /**< minimum joystick values */ + struct vec2b_t center; /**< center joystick values */ + + float ang; /**< angle the joystick is being held */ + float mag; /**< magnitude of the joystick (range 0-1) */ +} joystick_t; + + +/** + * @struct nunchuk_t + * @brief Nunchuk expansion device. + */ +typedef struct nunchuk_t { + struct accel_t accel_calib; /**< nunchuk accelerometer calibration */ + struct joystick_t js; /**< joystick calibration */ + + int* flags; /**< options flag (points to wiimote_t.flags) */ + + byte btns; /**< what buttons have just been pressed */ + byte btns_held; /**< what buttons are being held down */ + byte btns_released; /**< what buttons were just released this */ + + float orient_threshold; /**< threshold for orient to generate an event */ + int accel_threshold; /**< threshold for accel to generate an event */ + + struct vec3b_t accel; /**< current raw acceleration data */ + struct orient_t orient; /**< current orientation on each axis */ + struct gforce_t gforce; /**< current gravity forces on each axis */ +} nunchuk_t; + + +/** + * @struct classic_ctrl_t + * @brief Classic controller expansion device. + */ +typedef struct classic_ctrl_t { + short btns; /**< what buttons have just been pressed */ + short btns_held; /**< what buttons are being held down */ + short btns_released; /**< what buttons were just released this */ + + float r_shoulder; /**< right shoulder button (range 0-1) */ + float l_shoulder; /**< left shoulder button (range 0-1) */ + + struct joystick_t ljs; /**< left joystick calibration */ + struct joystick_t rjs; /**< right joystick calibration */ +} classic_ctrl_t; + + +/** + * @struct guitar_hero_3_t + * @brief Guitar Hero 3 expansion device. + */ +typedef struct guitar_hero_3_t { + short btns; /**< what buttons have just been pressed */ + short btns_held; /**< what buttons are being held down */ + short btns_released; /**< what buttons were just released this */ + + float whammy_bar; /**< whammy bar (range 0-1) */ + + struct joystick_t js; /**< joystick calibration */ +} guitar_hero_3_t; + + +/** + * @struct expansion_t + * @brief Generic expansion device plugged into wiimote. + */ +typedef struct expansion_t { + int type; /**< type of expansion attached */ + + union { + struct nunchuk_t nunchuk; + struct classic_ctrl_t classic; + struct guitar_hero_3_t gh3; + }; +} expansion_t; + + +/** + * @enum win32_bt_stack_t + * @brief Available bluetooth stacks for Windows. + */ +typedef enum win_bt_stack_t { + WIIUSE_STACK_UNKNOWN, + WIIUSE_STACK_MS, + WIIUSE_STACK_BLUESOLEIL +} win_bt_stack_t; + + +/** + * @struct wiimote_state_t + * @brief Significant data from the previous event. + */ +typedef struct wiimote_state_t { + /* expansion_t */ + float exp_ljs_ang; + float exp_rjs_ang; + float exp_ljs_mag; + float exp_rjs_mag; + unsigned short exp_btns; + struct orient_t exp_orient; + struct vec3b_t exp_accel; + float exp_r_shoulder; + float exp_l_shoulder; + + /* ir_t */ + int ir_ax; + int ir_ay; + float ir_distance; + + struct orient_t orient; + unsigned short btns; + + struct vec3b_t accel; +} wiimote_state_t; + + +/** + * @enum WIIUSE_EVENT_TYPE + * @brief Events that wiiuse can generate from a poll. + */ +typedef enum WIIUSE_EVENT_TYPE { + WIIUSE_NONE = 0, + WIIUSE_EVENT, + WIIUSE_STATUS, + WIIUSE_CONNECT, + WIIUSE_DISCONNECT, + WIIUSE_UNEXPECTED_DISCONNECT, + WIIUSE_READ_DATA, + WIIUSE_NUNCHUK_INSERTED, + WIIUSE_NUNCHUK_REMOVED, + WIIUSE_CLASSIC_CTRL_INSERTED, + WIIUSE_CLASSIC_CTRL_REMOVED, + WIIUSE_GUITAR_HERO_3_CTRL_INSERTED, + WIIUSE_GUITAR_HERO_3_CTRL_REMOVED +} WIIUSE_EVENT_TYPE; + +/** + * @struct wiimote_t + * @brief Wiimote structure. + */ +typedef struct wiimote_t { + WCONST int unid; /**< user specified id */ + + #ifndef WIN32 + WCONST bdaddr_t bdaddr; /**< bt address */ + WCONST char bdaddr_str[18]; /**< readable bt address */ + WCONST int out_sock; /**< output socket */ + WCONST int in_sock; /**< input socket */ + #else + WCONST HANDLE dev_handle; /**< HID handle */ + WCONST OVERLAPPED hid_overlap; /**< overlap handle */ + WCONST enum win_bt_stack_t stack; /**< type of bluetooth stack to use */ + WCONST int timeout; /**< read timeout */ + WCONST byte normal_timeout; /**< normal timeout */ + WCONST byte exp_timeout; /**< timeout for expansion handshake */ + #endif + + WCONST int state; /**< various state flags */ + WCONST byte leds; /**< currently lit leds */ + WCONST float battery_level; /**< battery level */ + + WCONST int flags; /**< options flag */ + + WCONST byte handshake_state; /**< the state of the connection handshake */ + + WCONST struct read_req_t* read_req; /**< list of data read requests */ + WCONST struct accel_t accel_calib; /**< wiimote accelerometer calibration */ + WCONST struct expansion_t exp; /**< wiimote expansion device */ + + WCONST struct vec3b_t accel; /**< current raw acceleration data */ + WCONST struct orient_t orient; /**< current orientation on each axis */ + WCONST struct gforce_t gforce; /**< current gravity forces on each axis */ + + WCONST struct ir_t ir; /**< IR data */ + + WCONST unsigned short btns; /**< what buttons have just been pressed */ + WCONST unsigned short btns_held; /**< what buttons are being held down */ + WCONST unsigned short btns_released; /**< what buttons were just released this */ + + WCONST float orient_threshold; /**< threshold for orient to generate an event */ + WCONST int accel_threshold; /**< threshold for accel to generate an event */ + + WCONST struct wiimote_state_t lstate; /**< last saved state */ + + WCONST WIIUSE_EVENT_TYPE event; /**< type of event that occured */ + WCONST byte event_buf[MAX_PAYLOAD]; /**< event buffer */ +} wiimote; + + +/***************************************** + * + * Include API specific stuff + * + *****************************************/ + +#ifdef _WIN32 + #define WIIUSE_EXPORT_DECL __declspec(dllexport) + #define WIIUSE_IMPORT_DECL __declspec(dllimport) +#else + #define WIIUSE_EXPORT_DECL + #define WIIUSE_IMPORT_DECL +#endif + +#ifdef WIIUSE_COMPILE_LIB + #define WIIUSE_EXPORT WIIUSE_EXPORT_DECL +#else + #define WIIUSE_EXPORT WIIUSE_IMPORT_DECL +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* wiiuse.c */ +WIIUSE_EXPORT extern const char* wiiuse_version(); + +WIIUSE_EXPORT extern struct wiimote_t** wiiuse_init(int wiimotes); +WIIUSE_EXPORT extern void wiiuse_disconnected(struct wiimote_t* wm); +WIIUSE_EXPORT extern void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes); +WIIUSE_EXPORT extern void wiiuse_rumble(struct wiimote_t* wm, int status); +WIIUSE_EXPORT extern void wiiuse_toggle_rumble(struct wiimote_t* wm); +WIIUSE_EXPORT extern void wiiuse_set_leds(struct wiimote_t* wm, int leds); +WIIUSE_EXPORT extern void wiiuse_motion_sensing(struct wiimote_t* wm, int status); +WIIUSE_EXPORT extern int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int offset, unsigned short len); +WIIUSE_EXPORT extern int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len); +WIIUSE_EXPORT extern void wiiuse_status(struct wiimote_t* wm); +WIIUSE_EXPORT extern struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid); +WIIUSE_EXPORT extern int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable); +WIIUSE_EXPORT extern float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha); +WIIUSE_EXPORT extern void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type); +WIIUSE_EXPORT extern void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold); +WIIUSE_EXPORT extern void wiiuse_resync(struct wiimote_t* wm); +WIIUSE_EXPORT extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout); +WIIUSE_EXPORT extern void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold); + +/* connect.c */ +WIIUSE_EXPORT extern int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout); +WIIUSE_EXPORT extern int wiiuse_connect(struct wiimote_t** wm, int wiimotes); +WIIUSE_EXPORT extern void wiiuse_disconnect(struct wiimote_t* wm); + +/* events.c */ +WIIUSE_EXPORT extern int wiiuse_poll(struct wiimote_t** wm, int wiimotes); + +/* ir.c */ +WIIUSE_EXPORT extern void wiiuse_set_ir(struct wiimote_t* wm, int status); +WIIUSE_EXPORT extern void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y); +WIIUSE_EXPORT extern void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos); +WIIUSE_EXPORT extern void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect); +WIIUSE_EXPORT extern void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level); + +/* nunchuk.c */ +WIIUSE_EXPORT extern void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold); +WIIUSE_EXPORT extern void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold); + +/* io.c */ +WIIUSE_EXPORT extern int wiiuse_io_read(struct wiimote_t* wm); +WIIUSE_EXPORT extern int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len); + + +#ifdef __cplusplus +} +#endif + + +#endif /* WIIUSE_H_INCLUDED */ + diff --git a/Externals/WiiUse/Win32/wiiuse.dll b/Externals/WiiUse/Win32/wiiuse.dll new file mode 100644 index 0000000000000000000000000000000000000000..6b52becf21dc232f1bd08bda98d382445e6e0504 GIT binary patch literal 104960 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 B7P$Zb literal 0 HcmV?d00001 diff --git a/Externals/WiiUse/Win32/wiiuse.lib b/Externals/WiiUse/Win32/wiiuse.lib new file mode 100644 index 0000000000000000000000000000000000000000..bf093f2f25eda06ee4a28894e5acd230be598a31 GIT binary patch literal 8610 zcmY$iNi0gvu;bEKKm~?IMy3{)rWVFVsNx1tuAzmA1%#Qv#lXPe%)r3+i-AE61x}}Kv=$pfdPaiRTvmRSRsso0fc2$7#KiU z{tW{I2rHT}Fo3Xl5d#AVOZYG_NchCZd-?|W2ZhADxCT21c?N{|2gR3XW|kJGGQ`LG zh5Gnl$}`kM6hNdyJVO1v<6Rs>92w%{Gjj{#q1xjM@^f++P&p{_X_`Sbr~rz(;?$D( z%%b?RqSRuzQWP<4stfXqGfOh_^U!r5#4&Uw78j%@m&6w(mSpCmXhW62(3e>hU!0l; zvaT$%q!L9Zx)c_@XzJ187Ua*o(!Au1((L&BqRiC1lK7I0qSWGy{2WB^;#Y)WC(OLW z)veK{2f?wWt_5jNyC~RmnN2iFu_3aF4?ID5^5^G7(7-!aqHl*AH53?mDnsLjm>6*G_$ATJ#rPUylYdO(FEs__UB((7DPc%7@vz`*c} zkAXo!kbxmgh=JjWI0HkBCD5hZ>R#S&U^j*tKqVkmmBRLr;vEG(rXp&Ay&D!geE(waa~ zk4T)TL4vg`fMr<}6F`|0e=!4Afl>iu7(lp`#8qZz7NNxh$hOR)csz{(B5H1Eiv+`+ z*b1H0l6aieE`|Xxl|+>5L?|IpFTu-gRA*o-7V#Co*sFfzQWIK+!}Af0kJkD`WD$5- ziVy zI>B-%sU1lIBb_73K~p%A2qTR0$;pA#!-RUgCYG?iZvvMOBQwK{ z^@5&Uj0_AM3}C>hmy()PnywNI<}olZI503U^uRb!+JQm9NiP%B+E6iq3NeTA@L0EvDfq?;J z97qnNfU`o#H#4~?zc@dwL_s4+Q^Cj6&l@C(jzM;TG=dCZU|?ZjU|?quU|?Wi1+x&A zFfceI=jRsaWu|aeOlJ81A7&j$2gpp2+n5-jJ~47&U;w)|1119Y8^|7Jn1~5T4M-k5HT z!;`m6p#cO=xuCoS6hzRq^Nb}HsxB^-T zg7Pp2s$Jlg2vQUwF^Th+DUMX3#K6G7iDVaA!xqVV2qtkh;)^jZBpbnPW`yA+`wU+? z~m6n2N_Coq>6xoI&WI?G^2+g+4BBTU^#3V92O|jQDppiw;$Q^8&36yq_2T&;S z9c=s(z1&n|U|3%iC;a39&1_lWn_G63-AUOcRB+~yl zT7()53=EQJ_EXbdd?lb1n!PAP9S9GSo@4Q(V`(%yVWTKW){$Jwo8T#nWRUHHjL;xi zgAidbEqN%1A{D*O{jxE2wO-`xA=NUa!5A929_wX3tz8A9?33nQxP&~g=8H7 D&M#pS literal 0 HcmV?d00001 diff --git a/Externals/WiiUse/X64/wiiuse.dll b/Externals/WiiUse/X64/wiiuse.dll new file mode 100644 index 0000000000000000000000000000000000000000..24905a297d43cd95bdf82777ed05caafe8e01663 GIT binary patch literal 103424 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�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 B8x#Nl literal 0 HcmV?d00001 diff --git a/Externals/WiiUse/X64/wiiuse.lib b/Externals/WiiUse/X64/wiiuse.lib new file mode 100644 index 0000000000000000000000000000000000000000..f0013849ea22c7b9b07dc7e8c9f2cbd4772153dc GIT binary patch literal 8462 zcmY$iNi0gvu;bEKKm~?IMy8eqMwS-FsNx1tuA#Yw351!z#lXPe%)r1`#lRr2fPq2q z8UurP3IvNhU|;}Y;Ta4JAS}YfzyQKxG7Jo0+{VBl*2cgfqXogzP7DknEZM}s0K(E+ z7#KiU>IMS?2+KAxFn}=&1A{CJ1A~GY1PkjiFo3Y=76t|o7Aat00AW!N1_lt8%3)vt zVYw;>1`w9~#=ro=a!d>iAS}tlzyQJ$77Pp^EccFq0fZ$MF))Cz{4oXw5SE$2zyQMX zF$@eKtgwKA0ffaqF))Cz_!$NU@iX!9p1uM8K_T%juEEYho&h2LLGk68nWe?44Ds=P zp*}vC@(lG51rX^Fk5E7Fco)YIM~3+L%-jN~?)ZZIoE!$ILNFUeHZ3zR1ttq-qsS)b z=jEj)m%tRjxF~8;GK*p2P+O2hP*i5-#}}n0!mWdG(bbd}WtODEtjx@hhwxEU6{nWO zXBNem6{Qx#6e0^@Q(KT@B2A^j{fi=o zqB=dbBtEG!J`=7KA%LO|6k=&PiRmb*2qJ)?t~fV8za%3*F{dCS5#|w)eiU>}e5m zsU={I#U+W!*~l8vr7-m3i)Rcu4BhCF2F;uxC!BmXspY zKzJxBz{N^@N@58-HjzY7ROaS`3JyrV&P#`d44Np44p1?NVl+a4^g7cLUS}#ZFfdf{ zF)%C;U|_f=$iR>y&cN_Mgn?m(FaraV2m^zR7z0C_7z2Zr3U+gL>L%6L>U-zq!<{g3 zNH8$GlVf05B*DONOrC*Zh71Ekj64Iw0tE(!Pht!VXT-r3I0GXC6N3-~8v{Fo2m>pF zD1$Hq2LmUA5(5i^GJ`aOEQ1sS4}%1Q7y};zHv=yN7lS;500TdRB!f7E41)rL9D^W( zBE|Zd8OW(UQDO{hkp!#PP*fsH9n=yUA)cCoDuY?C;wX+Vi#_~xB#OK6rAN$qACVwY z48fM&p*a&p9VipxEk(czkZVv3?F5TI9OZCk5o+jyY|1Q($6b*Vu6Q902@DrvDOFNS z;&IiR7}{Y92^ZCbRp75=V1+TN6R?zdc#2i5^)^z82rZal`2@yAZ6G4@0IZZmh#=~1 zaDIRqfXE3@0dO9Gu`wEqUMoaNfP2jW+Wg}8KTmYqVL#doV2?;$-L$!gWkW({~ zIC?rpl7ggQB!SE#nA<@nBBxpuMUbkdBoj*$61~X_PNPVgVTlfpM_@`YQXP^p_~cO1 zB9b0hDuf9^(jSzEn)0B6urvqdf+H7FZQ|?jG#gcA`A=+XBZe5 z9zX?{89;gs4nWnJL4_H37#JA-A*ln2J1{65U}9ik5MFHJ7GP&!V7LI5 zU;r!NtPt|eOfJeV&QB{*&BA3TMS+hX4OT>Ocm8bbx4(+n5-jJ~47&U;w)|1119Y8^{i3n1~5T4M-l*e51VWx?T$V=w_J84{Pbj9`N~3ZPJf8Ch+l2)EE`3;YGzGy{k?bRL?4c*k z0BR4wV+lUuh%ldw6o@1A6d6F3I@~U-Em*MUNDoIGHiFV17a|;yTE}GCgC`AgBkVzM zd4nxOgeY)?;s`%A1_lN`giWCS z0roaL*jiFU(iDgPKqE^0XtrYZbHG-T9H#huDu8My_C6HYT2g&#f+KuEWuzdgt;pRo z^6bJ9s-W~KglZSO=Lfck^st1E0iw4Flo%Kogwbt6jD;Wq52-#SF7KJ*C@obP7#Kt_ zY{Z=NAk&|)?iyMq4KZ0rmF;v@-`q^NsNRB}>9QB+Y z0|SFNs$H-SIu-N384jQ7GcYhnV7DE|5CD0;H^tHZQ)ggckVLhgy7uD8p`db43e{dL z!y07z6;B$LMzs@l$OLR1$!Qpe4?$&+43cfgqcLEMNKV0~M%Zg(1qKENS%gj4MtZ;& llI$}aIR?}Zl0(>sI*3G`O*m2~sCOcdunB2=3gH(9E #Kj#1d literal 0 HcmV?d00001 diff --git a/Externals/WiiUseSrc/Src/Makefile b/Externals/WiiUseSrc/Src/Makefile new file mode 100644 index 0000000000..bab5b140f4 --- /dev/null +++ b/Externals/WiiUseSrc/Src/Makefile @@ -0,0 +1,91 @@ +# +# wiiuse Makefile +# + +# +# Change this to your GCC version. +# +CC = gcc + +#################################################### +# +# You should not need to edit below this line. +# +#################################################### + +# +# Universal cflags +# +CFLAGS = -Wall -pipe -fPIC -funroll-loops + +ifeq ($(debug),1) + OBJ_PREFIX = debug + CFLAGS += -g -pg -DWITH_WIIUSE_DEBUG + +else + OBJ_PREFIX = release + CFLAGS += -O2 +endif + +OBJ_DIR = $(OBJ_PREFIX)-$(shell $(CC) -v 2>&1|grep ^Target:|cut -d' ' -f2) + +# +# Linking flags +# +LDFLAGS = -shared -lm -lbluetooth + +# +# Target binaries (always created as BIN) +# +BIN = ./$(OBJ_DIR)/libwiiuse.so + +# +# Inclusion paths. +# +INCLUDES = -I. + +# +# Generate a list of object files +# +OBJS = \ + $(OBJ_DIR)/classic.o \ + $(OBJ_DIR)/dynamics.o \ + $(OBJ_DIR)/events.o \ + $(OBJ_DIR)/io.o \ + $(OBJ_DIR)/io_nix.o \ + $(OBJ_DIR)/ir.o \ + $(OBJ_DIR)/nunchuk.o \ + $(OBJ_DIR)/guitar_hero_3.o \ + $(OBJ_DIR)/wiiuse.o + +############################### +# +# Build targets. +# +############################### + +all: $(BIN) + +clean: + @-rm $(OBJS) 2> /dev/null + +distclean: + @-rm -r debug-* release-* 2> /dev/null + +install: + @if [ -e $(BIN) ]; then \ + cp -v $(BIN) /usr/lib ; \ + fi + @cp -v wiiuse.h /usr/include + +$(BIN): mkdir $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(BIN) + +$(OBJ_DIR)/%.o: %.c + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + +mkdir: + @if [ ! -d $(OBJ_DIR) ]; then \ + mkdir $(OBJ_DIR); \ + fi + diff --git a/Externals/WiiUseSrc/Src/classic.c b/Externals/WiiUseSrc/Src/classic.c new file mode 100644 index 0000000000..1d2c3ab275 --- /dev/null +++ b/Externals/WiiUseSrc/Src/classic.c @@ -0,0 +1,190 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Classic controller expansion device. + */ + +#include +#include +#include + +#ifdef WIN32 + #include +#endif + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "dynamics.h" +#include "events.h" +#include "classic.h" + +static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now); + +/** + * @brief Handle the handshake data from the classic controller. + * + * @param cc A pointer to a classic_ctrl_t structure. + * @param data The data read in from the device. + * @param len The length of the data block, in bytes. + * + * @return Returns 1 if handshake was successful, 0 if not. + */ +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; + cc->btns_released = 0; + 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) { + /* + * Sometimes the data returned here is not correct. + * This might happen because the wiimote is lagging + * behind our initialization sequence. + * To fix this just request the handshake again. + * + * Other times it's just the first 16 bytes are 0xFF, + * but since the next 16 bytes are the same, just use + * those. + */ + if (data[offset + 16] == 0xFF) { + /* get the calibration data */ + byte* handshake_buf = 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; + } + + + /* 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->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; + + /* handshake done */ + wm->exp.type = EXP_CLASSIC; + + #ifdef WIN32 + wm->timeout = WIIMOTE_DEFAULT_TIMEOUT; + #endif + + return 1; +} + + +/** + * @brief The classic controller disconnected. + * + * @param cc A pointer to a classic_ctrl_t structure. + */ +void classic_ctrl_disconnected(struct classic_ctrl_t* cc) { + memset(cc, 0, sizeof(struct classic_ctrl_t)); +} + + + +/** + * @brief Handle classic controller event. + * + * @param cc A pointer to a classic_ctrl_t structure. + * @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; + byte l, r; + + /* decrypt data */ + for (i = 0; i < 6; ++i) + msg[i] = (msg[i] ^ 0x17) + 0x17; + + 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); + + /* + * TODO - LR range hardcoded from 0x00 to 0x1F. + * This is probably in the calibration somewhere. + */ + cc->r_shoulder = ((float)r / 0x1F); + cc->l_shoulder = ((float)l / 0x1F); + + /* calculate joystick orientation */ + lx = (msg[0] & 0x3F); + ly = (msg[1] & 0x3F); + 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); +} + + +/** + * @brief Find what buttons are pressed. + * + * @param cc A pointer to a classic_ctrl_t structure. + * @param msg The message byte specified in the event packet. + */ +static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now) { + /* message is inverted (0 is active, 1 is inactive) */ + now = ~now & CLASSIC_CTRL_BUTTON_ALL; + + /* pressed now & were pressed, then held */ + cc->btns_held = (now & cc->btns); + + /* were pressed or were held & not pressed now, then released */ + cc->btns_released = ((cc->btns | cc->btns_held) & ~now); + + /* buttons pressed now */ + cc->btns = now; +} diff --git a/Externals/WiiUseSrc/Src/classic.h b/Externals/WiiUseSrc/Src/classic.h new file mode 100644 index 0000000000..356f6a458b --- /dev/null +++ b/Externals/WiiUseSrc/Src/classic.h @@ -0,0 +1,53 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Classic controller expansion device. + */ + +#ifndef CLASSIC_H_INCLUDED +#define CLASSIC_H_INCLUDED + +#include "wiiuse_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +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_event(struct classic_ctrl_t* cc, byte* msg); + +#ifdef __cplusplus +} +#endif + +#endif // CLASSIC_H_INCLUDED diff --git a/Externals/WiiUseSrc/Src/definitions.h b/Externals/WiiUseSrc/Src/definitions.h new file mode 100644 index 0000000000..5a8da85def --- /dev/null +++ b/Externals/WiiUseSrc/Src/definitions.h @@ -0,0 +1,79 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief General definitions. + */ + +#ifndef DEFINITIONS_H_INCLUDED +#define DEFINITIONS_H_INCLUDED + +/* this is wiiuse - used to distinguish from third party programs using wiiuse.h */ +#include "os.h" + +#define WIIMOTE_PI 3.14159265f + +//#define WITH_WIIUSE_DEBUG + +/* Error output macros */ +#define WIIUSE_ERROR(fmt, ...) fprintf(stderr, "[ERROR] " fmt "\n", ##__VA_ARGS__) + +/* Warning output macros */ +#define WIIUSE_WARNING(fmt, ...) fprintf(stderr, "[WARNING] " fmt "\n", ##__VA_ARGS__) + +/* Information output macros */ +#define WIIUSE_INFO(fmt, ...) fprintf(stderr, "[INFO] " fmt "\n", ##__VA_ARGS__) + +#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__); \ + } while (0) + #else + #define WIIUSE_DEBUG(fmt, ...) fprintf(stderr, "[DEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__) + #endif +#else + #define WIIUSE_DEBUG(fmt, ...) +#endif + +/* Convert between radians and degrees */ +#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 diff --git a/Externals/WiiUseSrc/Src/dynamics.c b/Externals/WiiUseSrc/Src/dynamics.c new file mode 100644 index 0000000000..53612a6b90 --- /dev/null +++ b/Externals/WiiUseSrc/Src/dynamics.c @@ -0,0 +1,228 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles the dynamics of the wiimote. + * + * The file includes functions that handle the dynamics + * of the wiimote. Such dynamics include orientation and + * motion sensing. + */ + +#include +#include +#include + +#ifdef WIN32 + #include +#endif + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "ir.h" +#include "dynamics.h" + +/** + * @brief Calculate the roll, pitch, yaw. + * + * @param ac An accelerometer (accel_t) structure. + * @param accel [in] Pointer to a vec3b_t structure that holds the raw acceleration data. + * @param orient [out] Pointer to a orient_t structure that will hold the orientation data. + * @param rorient [out] Pointer to a orient_t structure that will hold the non-smoothed orientation data. + * @param smooth If smoothing should be performed on the angles calculated. 1 to enable, 0 to disable. + * + * Given the raw acceleration data from the accelerometer struct, calculate + * the orientation of the device and set it in the \a orient parameter. + */ +void calculate_orientation(struct accel_t* ac, struct vec3b_t* accel, struct orient_t* orient, int smooth) { + float xg, yg, zg; + float x, y, z; + + /* + * roll - use atan(z / x) [ ranges from -180 to 180 ] + * pitch - use atan(z / y) [ ranges from -180 to 180 ] + * yaw - impossible to tell without IR + */ + + /* yaw - set to 0, IR will take care of it if it's enabled */ + orient->yaw = 0.0f; + + /* find out how much it has to move to be 1g */ + xg = (float)ac->cal_g.x; + yg = (float)ac->cal_g.y; + zg = (float)ac->cal_g.z; + + /* find out how much it actually moved and normalize to +/- 1g */ + x = ((float)accel->x - (float)ac->cal_zero.x) / xg; + y = ((float)accel->y - (float)ac->cal_zero.y) / yg; + 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 it is over 1g then it is probably accelerating and not reliable */ + if (abs(accel->x - ac->cal_zero.x) <= ac->cal_g.x) { + /* roll */ + x = RAD_TO_DEGREE(atan2f(x, z)); + + orient->roll = x; + orient->a_roll = x; + } + + if (abs(accel->y - ac->cal_zero.y) <= ac->cal_g.y) { + /* pitch */ + y = RAD_TO_DEGREE(atan2f(y, z)); + + orient->pitch = y; + orient->a_pitch = y; + } + + /* smooth the angles if enabled */ + if (smooth) { + apply_smoothing(ac, orient, SMOOTH_ROLL); + apply_smoothing(ac, orient, SMOOTH_PITCH); + } +} + + +/** + * @brief Calculate the gravity forces on each axis. + * + * @param ac An accelerometer (accel_t) structure. + * @param accel [in] Pointer to a vec3b_t structure that holds the raw acceleration data. + * @param gforce [out] Pointer to a gforce_t structure that will hold the gravity force data. + */ +void calculate_gforce(struct accel_t* ac, struct vec3b_t* accel, struct gforce_t* gforce) { + float xg, yg, zg; + + /* find out how much it has to move to be 1g */ + xg = (float)ac->cal_g.x; + yg = (float)ac->cal_g.y; + zg = (float)ac->cal_g.z; + + /* find out how much it actually moved and normalize to +/- 1g */ + gforce->x = ((float)accel->x - (float)ac->cal_zero.x) / xg; + gforce->y = ((float)accel->y - (float)ac->cal_zero.y) / yg; + gforce->z = ((float)accel->z - (float)ac->cal_zero.z) / zg; +} + + +/** + * @brief Calculate the angle and magnitude of a joystick. + * + * @param js [out] Pointer to a joystick_t structure. + * @param x The raw x-axis value. + * @param y The raw y-axis value. + */ +void calc_joystick_state(struct joystick_t* js, float x, float y) { + float rx, ry, ang; + + /* + * Since the joystick center may not be exactly: + * (min + max) / 2 + * 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 + * between the center and the minimum or maxmimum rather than between + * the minimum and maximum. + * + * So we have something like this: + * (x min) [-1] ---------*------ [0] (x center) [0] -------- [1] (x max) + * Where the * is the current x value. + * 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; + + /* 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)); +} + + +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; + + /* + * 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; + } + + 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; + } + + return; + } + } +} diff --git a/Externals/WiiUseSrc/Src/dynamics.h b/Externals/WiiUseSrc/Src/dynamics.h new file mode 100644 index 0000000000..2a8f96500b --- /dev/null +++ b/Externals/WiiUseSrc/Src/dynamics.h @@ -0,0 +1,56 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles the dynamics of the wiimote. + * + * The file includes functions that handle the dynamics + * of the wiimote. Such dynamics include orientation and + * motion sensing. + */ + +#ifndef DYNAMICS_H_INCLUDED +#define DYNAMICS_H_INCLUDED + +#include "wiiuse_internal.h" + +#ifdef __cplusplus +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); + +#ifdef __cplusplus +} +#endif + +#endif // DYNAMICS_H_INCLUDED diff --git a/Externals/WiiUseSrc/Src/events.c b/Externals/WiiUseSrc/Src/events.c new file mode 100644 index 0000000000..6668eda5c8 --- /dev/null +++ b/Externals/WiiUseSrc/Src/events.c @@ -0,0 +1,878 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles wiimote events. + * + * The file includes functions that handle the events + * that are sent from the wiimote to us. + */ + +#include + +#ifndef WIN32 + #include + #include + #include +#else + #include +#endif + +#include +#include +#include + +#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" + +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_status(struct wiimote_t* wm, byte* msg); +static void handle_expansion(struct wiimote_t* wm, byte* msg); + +static void save_state(struct wiimote_t* wm); +static int state_changed(struct wiimote_t* wm); + +/** + * @brief Poll the wiimotes for any events. + * + * @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. + * + * 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) { + 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; + } + + 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) { + /* + * Smooth the angles. + * + * This is done to make sure that on every cycle the orientation + * angles are smoothed. Normally when an event occurs the angles + * are updated and smoothed, but if no packet comes in then the + * angles remain the same. This means the angle wiiuse reports + * is still an old value. Smoothing needs to be applied in this + * case in order for the angle it reports to converge to the true + * angle of the device. + */ + if (WIIUSE_USING_ACC(wm) && WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING)) { + apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_ROLL); + apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_PITCH); + } + + /* clear out any old read requests */ + clear_dirty_reads(wm); +} + + +/** + * @brief Clear out all old 'dirty' read requests. + * + * @param wm Pointer to a wiimote_t structure. + */ +static void clear_dirty_reads(struct wiimote_t* wm) { + struct read_req_t* req = wm->read_req; + + while (req && req->dirty) { + WIIUSE_DEBUG("Cleared old read request for address: %x", req->addr); + + wm->read_req = req->next; + free(req); + req = wm->read_req; + } +} + + +/** + * @brief Analyze the event that occured on a wiimote. + * + * @param wm An array of pointers to wiimote_t structures. + * @param event The event that occured. + * @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) { + 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); + + 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); + + break; + } + case WM_RPT_READ: + { + /* data read */ + event_data_read(wm, msg); + + /* yeah buttons may be pressed, but this wasn't an "event" */ + return; + } + case WM_RPT_CTRL_STATUS: + { + /* controller status */ + event_status(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); + + break; + } + case WM_RPT_BTN_ACC_EXP: + { + /* button - motion - 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+5); + + break; + } + case WM_RPT_BTN_ACC_IR: + { + /* button - motion - ir */ + 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); + + /* ir */ + calculate_extended_ir(wm, msg+5); + + break; + } + case WM_RPT_BTN_IR_EXP: + { + /* button - ir - expansion */ + wiiuse_pressed_buttons(wm, msg); + handle_expansion(wm, msg+12); + + /* ir */ + calculate_basic_ir(wm, msg+2); + + 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; + } + } + + /* was there an event? */ + if (state_changed(wm)) + wm->event = WIIUSE_EVENT; +} + + +/** + * @brief Find what buttons are pressed. + * + * @param wm Pointer to a wiimote_t structure. + * @param msg The message specified in the event packet. + */ +void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg) { + short now; + + /* convert to big endian */ + now = BIG_ENDIAN_SHORT(*(short*)msg) & WIIMOTE_BUTTON_ALL; + + /* pressed now & were pressed, then held */ + wm->btns_held = (now & wm->btns); + + /* were pressed or were held & not pressed now, then released */ + wm->btns_released = ((wm->btns | wm->btns_held) & ~now); + + /* buttons pressed now */ + wm->btns = now; +} + + +/** + * @brief Received a data packet from a read request. + * + * @param wm Pointer to a wiimote_t structure. + * @param msg The message specified in the event packet. + * + * Data from the wiimote comes in packets. If the requested + * data segment size is bigger than one packet can hold then + * several packets will be received. These packets are first + * reassembled into one, then the registered callback function + * that handles data reads is invoked. + */ +static void event_data_read(struct wiimote_t* wm, byte* msg) { + /* we must always assume the packet received is from the most recent request */ + byte err; + byte len; + unsigned short offset; + struct read_req_t* req = wm->read_req; + + wiiuse_pressed_buttons(wm, msg); + + /* find the next non-dirty request */ + 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) { + WIIUSE_WARNING("Received data packet when no request was made."); + return; + } + + err = msg[2] & 0x0F; + + if (err == 0x08) + WIIUSE_WARNING("Unable to read data - address does not exist."); + else if (err == 0x07) + WIIUSE_WARNING("Unable to read data - address is for write-only registers."); + 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 */ + + /* delete this request */ + wm->read_req = req->next; + free(req); + + /* if another request exists send it to the wiimote */ + 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)); + 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); + WIIUSE_DEBUG(" Request read offset: %i bytes", req->addr); + WIIUSE_DEBUG(" Read offset into buf: %i bytes", offset - req->addr); + WIIUSE_DEBUG(" Read data size: %i bytes", len); + WIIUSE_DEBUG(" Still need: %i bytes", req->wait); + + /* reconstruct this part of the data */ + memcpy((req->buf + offset - req->addr), (msg + 5), len); + + #ifdef WITH_WIIUSE_DEBUG + { + int i = 0; + printf("Read: "); + for (; i < req->size - req->wait; ++i) + printf("%x ", req->buf[i]); + printf("\n"); + } + #endif + + /* if all data has been received, execute the read event callback or generate event */ + if (!req->wait) { + if (req->cb) { + /* this was a callback, so invoke it now */ + req->cb(wm, req->buf, req->size); + + /* delete this request */ + wm->read_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 'dirty' + * and give the client one cycle to use it. Next event + * we will remove it from the list. + */ + wm->event = WIIUSE_READ_DATA; + req->dirty = 1; + } + + /* if another request exists send it to the wiimote */ + if (wm->read_req) + wiiuse_send_next_pending_read_request(wm); + } +} + + +/** + * @brief Read the controller status. + * + * @param wm Pointer to a wiimote_t structure. + * @param msg The message specified in the event packet. + * + * 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 attachment = 0; + int ir = 0; + int exp_changed = 0; + + /* + * An event occured. + * This event can be overwritten by a more specific + * event type during a handshake or expansion removal. + */ + wm->event = WIIUSE_STATUS; + + 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; + + /* is an attachment connected to the expansion port? */ + if ((msg[2] & WM_CTRL_STATUS_BYTE1_ATTACHMENT) == WM_CTRL_STATUS_BYTE1_ATTACHMENT) + attachment = 1; + + /* is the 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) + 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)) { + /* send the initialization code for the attachment */ + handshake_expansion(wm, NULL, 0); + exp_changed = 1; + } else if (!attachment && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) { + /* attachment removed */ + disable_expansion(wm); + exp_changed = 1; + } + + #ifdef WIN32 + if (!attachment) { + WIIUSE_DEBUG("Setting timeout to normal %i ms.", wm->normal_timeout); + wm->timeout = wm->normal_timeout; + } + #endif + + /* + * From now on the remote will only send status packets. + * We need to send a WIIMOTE_CMD_REPORT_TYPE packet to + * reenable other incoming reports. + */ + 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. + */ + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR); + wiiuse_set_ir(wm, 1); + } else + wiiuse_set_report_type(wm); +} + + +/** + * @brief Handle data from the expansion. + * + * @param wm A pointer to a wiimote_t structure. + * @param msg The message specified in the event packet for the expansion. + */ +static void handle_expansion(struct wiimote_t* wm, byte* msg) { + switch (wm->exp.type) { + case EXP_NUNCHUK: + nunchuk_event(&wm->exp.nunchuk, msg); + break; + case EXP_CLASSIC: + classic_ctrl_event(&wm->exp.classic, msg); + break; + case EXP_GUITAR_HERO_3: + guitar_hero_3_event(&wm->exp.gh3, msg); + break; + default: + break; + } +} + + +/** + * @brief Handle the handshake data from the expansion device. + * + * @param wm A pointer to a wiimote_t structure. + * @param data The data read in from the device. + * @param len The length of the data block, in bytes. + * + * Tries to determine what kind of expansion was attached + * and invoke the correct handshake function. + * + * 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) { + int id; + + if (!data) { + byte* handshake_buf; + byte buf = 0x00; + + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) + disable_expansion(wm); + + /* 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 + + wiiuse_write_data(wm, WM_EXP_MEM_ENABLE, &buf, 1); + + /* 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); + + /* 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; + 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); +} + + + +/** + * @brief Disable the expansion device if it was enabled. + * + * @param wm A pointer to a wiimote_t structure. + * @param data The data read in from the device. + * @param len The length of the data block, in bytes. + * + * If the data is NULL then this function will try to start + * a handshake with the expansion. + */ +void disable_expansion(struct wiimote_t* wm) { + if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) + return; + + /* tell the assoicated module the expansion was removed */ + switch (wm->exp.type) { + case EXP_NUNCHUK: + nunchuk_disconnected(&wm->exp.nunchuk); + wm->event = WIIUSE_NUNCHUK_REMOVED; + break; + case EXP_CLASSIC: + classic_ctrl_disconnected(&wm->exp.classic); + wm->event = WIIUSE_CLASSIC_CTRL_REMOVED; + break; + case EXP_GUITAR_HERO_3: + guitar_hero_3_disconnected(&wm->exp.gh3); + wm->event = WIIUSE_GUITAR_HERO_3_CTRL_REMOVED; + break; + default: + break; + } + + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP); + wm->exp.type = EXP_NONE; +} + + +/** + * @brief Save important state data. + * @param wm A pointer to a wiimote_t structure. + */ +static void save_state(struct wiimote_t* wm) { + /* wiimote */ + wm->lstate.btns = wm->btns; + wm->lstate.accel = wm->accel; + + /* ir */ + if (WIIUSE_USING_IR(wm)) { + wm->lstate.ir_ax = wm->ir.ax; + wm->lstate.ir_ay = wm->ir.ay; + wm->lstate.ir_distance = wm->ir.distance; + } + + /* expansion */ + switch (wm->exp.type) { + case EXP_NUNCHUK: + 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_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; + break; + + case EXP_GUITAR_HERO_3: + wm->lstate.exp_ljs_ang = wm->exp.gh3.js.ang; + wm->lstate.exp_ljs_mag = wm->exp.gh3.js.mag; + wm->lstate.exp_r_shoulder = wm->exp.gh3.whammy_bar; + wm->lstate.exp_btns = wm->exp.gh3.btns; + break; + + case EXP_NONE: + break; + } +} + + +/** + * @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. + */ +static int state_changed(struct wiimote_t* wm) { + #define STATE_CHANGED(a, b) if (a != b) return 1 + + #define CROSS_THRESH(last, now, thresh) \ + do { \ + if (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_ORIENT_THRESH)) { \ + if ((diff_f(last.roll, now.roll) >= thresh) || \ + (diff_f(last.pitch, now.pitch) >= thresh) || \ + (diff_f(last.yaw, now.yaw) >= thresh)) \ + { \ + last = now; \ + return 1; \ + } \ + } else { \ + if (last.roll != now.roll) return 1; \ + if (last.pitch != now.pitch) return 1; \ + if (last.yaw != now.yaw) return 1; \ + } \ + } while (0) + + #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) || \ + (diff_f(last.y, now.y) >= thresh) || \ + (diff_f(last.z, now.z) >= thresh)) \ + { \ + last = now; \ + return 1; \ + } \ + } else { \ + if (last.x != now.x) return 1; \ + if (last.y != now.y) return 1; \ + if (last.z != now.z) return 1; \ + } \ + } while (0) + + /* ir */ + if (WIIUSE_USING_IR(wm)) { + STATE_CHANGED(wm->lstate.ir_ax, wm->ir.ax); + STATE_CHANGED(wm->lstate.ir_ay, wm->ir.ay); + STATE_CHANGED(wm->lstate.ir_distance, wm->ir.distance); + } + + /* accelerometer */ + if (WIIUSE_USING_ACC(wm)) { + /* raw accelerometer */ + CROSS_THRESH_XYZ(wm->lstate.accel, wm->accel, wm->accel_threshold); + + /* orientation */ + 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); + + 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; + } + } + + STATE_CHANGED(wm->lstate.btns, wm->btns); + + return 0; +} diff --git a/Externals/WiiUseSrc/Src/events.h b/Externals/WiiUseSrc/Src/events.h new file mode 100644 index 0000000000..5e9b955c55 --- /dev/null +++ b/Externals/WiiUseSrc/Src/events.h @@ -0,0 +1,54 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles wiimote events. + * + * The file includes functions that handle the events + * that are sent from the wiimote to us. + */ + +#ifndef EVENTS_H_INCLUDED +#define EVENTS_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg); + +void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len); +void disable_expansion(struct wiimote_t* wm); + +#ifdef __cplusplus +} +#endif + + +#endif // EVENTS_H_INCLUDED diff --git a/Externals/WiiUseSrc/Src/guitar_hero_3.c b/Externals/WiiUseSrc/Src/guitar_hero_3.c new file mode 100644 index 0000000000..5837dc016f --- /dev/null +++ b/Externals/WiiUseSrc/Src/guitar_hero_3.c @@ -0,0 +1,172 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Guitar Hero 3 expansion device. + */ + +#include +#include +#include + +#ifdef WIN32 + #include +#endif + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "dynamics.h" +#include "events.h" +#include "guitar_hero_3.h" + +static void guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now); + +/** + * @brief Handle the handshake data from the guitar. + * + * @param cc A pointer to a classic_ctrl_t structure. + * @param data The data read in from the device. + * @param len The length of the data block, in bytes. + * + * @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 + * failed to factory calibrate the devices. There is no + * calibration data on the device. + */ + + gh3->btns = 0; + gh3->btns_held = 0; + 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) { + /* + * Sometimes the data returned here is not correct. + * This might happen because the wiimote is lagging + * behind our initialization sequence. + * To fix this just request the handshake again. + * + * Other times it's just the first 16 bytes are 0xFF, + * but since the next 16 bytes are the same, just use + * those. + */ + if (data[offset + 16] == 0xFF) { + /* get the calibration data */ + byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte)); + + WIIUSE_DEBUG("Guitar Hero 3 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; + } + + /* joystick stuff */ + gh3->js.max.x = GUITAR_HERO_3_JS_MAX_X; + gh3->js.min.x = GUITAR_HERO_3_JS_MIN_X; + gh3->js.center.x = GUITAR_HERO_3_JS_CENTER_X; + gh3->js.max.y = GUITAR_HERO_3_JS_MAX_Y; + gh3->js.min.y = GUITAR_HERO_3_JS_MIN_Y; + gh3->js.center.y = GUITAR_HERO_3_JS_CENTER_Y; + + /* handshake done */ + wm->exp.type = EXP_GUITAR_HERO_3; + + #ifdef WIN32 + wm->timeout = WIIMOTE_DEFAULT_TIMEOUT; + #endif + + return 1; +} + + +/** + * @brief The guitar disconnected. + * + * @param cc A pointer to a classic_ctrl_t structure. + */ +void guitar_hero_3_disconnected(struct guitar_hero_3_t* gh3) { + memset(gh3, 0, sizeof(struct guitar_hero_3_t)); +} + + + +/** + * @brief Handle guitar event. + * + * @param cc A pointer to a classic_ctrl_t structure. + * @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, 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); + + /* joy stick */ + calc_joystick_state(&gh3->js, msg[0], msg[1]); +} + + +/** + * @brief Find what buttons are pressed. + * + * @param cc A pointer to a classic_ctrl_t structure. + * @param msg The message byte specified in the event packet. + */ +static void guitar_hero_3_pressed_buttons(struct guitar_hero_3_t* gh3, short now) { + /* message is inverted (0 is active, 1 is inactive) */ + now = ~now & GUITAR_HERO_3_BUTTON_ALL; + + /* pressed now & were pressed, then held */ + gh3->btns_held = (now & gh3->btns); + + /* were pressed or were held & not pressed now, then released */ + gh3->btns_released = ((gh3->btns | gh3->btns_held) & ~now); + + /* buttons pressed now */ + gh3->btns = now; +} diff --git a/Externals/WiiUseSrc/Src/guitar_hero_3.h b/Externals/WiiUseSrc/Src/guitar_hero_3.h new file mode 100644 index 0000000000..024d603177 --- /dev/null +++ b/Externals/WiiUseSrc/Src/guitar_hero_3.h @@ -0,0 +1,62 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Guitar Hero 3 expansion device. + */ + +#ifndef GUITAR_HERO_3_H_INCLUDED +#define GUITAR_HERO_3_H_INCLUDED + +#include "wiiuse_internal.h" + +#define GUITAR_HERO_3_JS_MIN_X 0xC5 +#define GUITAR_HERO_3_JS_MAX_X 0xFC +#define GUITAR_HERO_3_JS_CENTER_X 0xE0 +#define GUITAR_HERO_3_JS_MIN_Y 0xC5 +#define GUITAR_HERO_3_JS_MAX_Y 0xFA +#define GUITAR_HERO_3_JS_CENTER_Y 0xE0 +#define GUITAR_HERO_3_WHAMMY_BAR_MIN 0xEF +#define GUITAR_HERO_3_WHAMMY_BAR_MAX 0xFA + +#ifdef __cplusplus +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); + +void guitar_hero_3_event(struct guitar_hero_3_t* gh3, byte* msg); + +#ifdef __cplusplus +} +#endif + +#endif // GUITAR_HERO_3_H_INCLUDED diff --git a/Externals/WiiUseSrc/Src/io.c b/Externals/WiiUseSrc/Src/io.c new file mode 100644 index 0000000000..ae420b9ef3 --- /dev/null +++ b/Externals/WiiUseSrc/Src/io.c @@ -0,0 +1,119 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles device I/O (non-OS specific). + */ + +#include +#include + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "io.h" + + + /** + * @brief Get initialization data from the wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * @param data unused + * @param len unused + * + * When first called for a wiimote_t structure, a request + * is sent to the wiimote for initialization information. + * This includes factory set accelerometer data. + * The handshake will be concluded when the wiimote responds + * with this data. + */ +void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len) { + if (!wm) return; + + switch (wm->handshake_state) { + case 0: + { + /* send request to wiimote for accelerometer calibration */ + byte* buf; + + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); + wiiuse_set_leds(wm, WIIMOTE_LED_NONE); + + buf = (byte*)malloc(sizeof(byte) * 8); + wiiuse_read_data_cb(wm, wiiuse_handshake, buf, WM_MEM_OFFSET_CALIBRATION, 7); + wm->handshake_state++; + + wiiuse_set_leds(wm, WIIMOTE_LED_NONE); + + break; + } + case 1: + { + struct read_req_t* req = wm->read_req; + struct accel_t* accel = &wm->accel_calib; + + /* received read data */ + accel->cal_zero.x = req->buf[0]; + accel->cal_zero.y = req->buf[1]; + accel->cal_zero.z = req->buf[2]; + + accel->cal_g.x = req->buf[4] - accel->cal_zero.x; + accel->cal_g.y = req->buf[5] - accel->cal_zero.y; + accel->cal_g.z = req->buf[6] - accel->cal_zero.z; + + /* done with the buffer */ + free(req->buf); + + /* handshake is done */ + WIIUSE_DEBUG("Handshake finished. Calibration: Idle: X=%x Y=%x Z=%x\t+1g: X=%x Y=%x Z=%x", + accel->cal_zero.x, accel->cal_zero.y, accel->cal_zero.z, + accel->cal_g.x, accel->cal_g.y, accel->cal_g.z); + + + /* request the status of the wiimote to see if there is an expansion */ + wiiuse_status(wm); + + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE); + wm->handshake_state++; + + /* now enable IR if it was set before the handshake completed */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) { + WIIUSE_DEBUG("Handshake finished, enabling IR."); + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR); + wiiuse_set_ir(wm, 1); + } + + break; + } + default: + { + break; + } + } +} diff --git a/Externals/WiiUseSrc/Src/io.h b/Externals/WiiUseSrc/Src/io.h new file mode 100644 index 0000000000..7a683e4ee5 --- /dev/null +++ b/Externals/WiiUseSrc/Src/io.h @@ -0,0 +1,56 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles device I/O. + */ + +#ifndef CONNECT_H_INCLUDED +#define CONNECT_H_INCLUDED + +#ifndef WIN32 + #include +#endif + +#include "wiiuse_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len); + +int wiiuse_io_read(struct wiimote_t* wm); +int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len); + +#ifdef __cplusplus +} +#endif + +#endif // CONNECT_H_INCLUDED diff --git a/Externals/WiiUseSrc/Src/io_nix.c b/Externals/WiiUseSrc/Src/io_nix.c new file mode 100644 index 0000000000..ec4e0e1780 --- /dev/null +++ b/Externals/WiiUseSrc/Src/io_nix.c @@ -0,0 +1,270 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles device I/O for *nix. + */ + +#ifndef WIN32 + +#include +#include +#include + +#include +#include +#include +#include + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "io.h" + +static int wiiuse_connect_single(struct wiimote_t* wm, char* address); + +/** + * @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 wiimote_connect() + * + * 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 wiimote_connect() to connect to the found \n + * devices. + */ +int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { + int device_id; + int device_sock; + int found_devices; + int found_wiimotes; + + /* reset all wiimote bluetooth device addresses */ + for (found_wiimotes = 0; found_wiimotes < max_wiimotes; ++found_wiimotes) + wm[found_wiimotes]->bdaddr = *BDADDR_ANY; + found_wiimotes = 0; + + /* get the id of the first bluetooth device. */ + device_id = hci_get_route(NULL); + if (device_id < 0) { + perror("hci_get_route"); + return 0; + } + + /* create a socket to the device */ + device_sock = hci_open_dev(device_id); + if (device_sock < 0) { + perror("hci_open_dev"); + return 0; + } + + inquiry_info scan_info_arr[128]; + inquiry_info* scan_info = scan_info_arr; + memset(&scan_info_arr, 0, sizeof(scan_info_arr)); + + /* scan for bluetooth devices for 'timeout' seconds */ + found_devices = hci_inquiry(device_id, timeout, 128, NULL, &scan_info, IREQ_CACHE_FLUSH); + if (found_devices < 0) { + perror("hci_inquiry"); + return 0; + } + + WIIUSE_INFO("Found %i bluetooth device(s).", found_devices); + + int i = 0; + + /* display discovered devices */ + for (; (i < found_devices) && (found_wiimotes < max_wiimotes); ++i) { + if ((scan_info[i].dev_class[0] == WM_DEV_CLASS_0) && + (scan_info[i].dev_class[1] == WM_DEV_CLASS_1) && + (scan_info[i].dev_class[2] == WM_DEV_CLASS_2)) + { + /* found a device */ + ba2str(&scan_info[i].bdaddr, wm[found_wiimotes]->bdaddr_str); + + WIIUSE_INFO("Found wiimote (%s) [id %i].", wm[found_wiimotes]->bdaddr_str, wm[found_wiimotes]->unid); + + wm[found_wiimotes]->bdaddr = scan_info[i].bdaddr; + WIIMOTE_ENABLE_STATE(wm[found_wiimotes], WIIMOTE_STATE_DEV_FOUND); + ++found_wiimotes; + } + } + + close(device_sock); + return found_wiimotes; +} + + +/** + * @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_connect_single() + * @see wiiuse_disconnect() + * + * 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. + */ +int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { + int connected = 0; + int i = 0; + + for (; i < wiimotes; ++i) { + if (!WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND)) + /* if the device address is not set, skip it */ + continue; + + if (wiiuse_connect_single(wm[i], NULL)) + ++connected; + } + + return connected; +} + + +/** + * @brief Connect to a wiimote with a known address. + * + * @param wm Pointer to a wiimote_t structure. + * @param address The address of the device to connect to. + * If NULL, use the address in the struct set by wiiuse_find(). + * + * @return 1 on success, 0 on failure + */ +static int wiiuse_connect_single(struct wiimote_t* wm, char* address) { + struct sockaddr_l2 addr; + + if (!wm || WIIMOTE_IS_CONNECTED(wm)) + return 0; + + addr.l2_family = AF_BLUETOOTH; + + if (address) + /* use provided address */ + str2ba(address, &addr.l2_bdaddr); + else + /* use address of device discovered */ + addr.l2_bdaddr = wm->bdaddr; + + /* + * OUTPUT CHANNEL + */ + wm->out_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (wm->out_sock == -1) + return 0; + + addr.l2_psm = htobs(WM_OUTPUT_CHANNEL); + + /* connect to wiimote */ + if (connect(wm->out_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + perror("connect() output sock"); + return 0; + } + + /* + * INPUT CHANNEL + */ + wm->in_sock = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); + if (wm->in_sock == -1) { + close(wm->out_sock); + wm->out_sock = -1; + return 0; + } + + addr.l2_psm = htobs(WM_INPUT_CHANNEL); + + /* connect to wiimote */ + if (connect(wm->in_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + perror("connect() interrupt sock"); + close(wm->out_sock); + wm->out_sock = -1; + return 0; + } + + WIIUSE_INFO("Connected to wiimote [id %i].", wm->unid); + + /* do the handshake */ + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + wiiuse_handshake(wm, NULL, 0); + + wiiuse_set_report_type(wm); + + return 1; +} + + +/** + * @brief Disconnect a wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * + * @see wiiuse_connect() + * + * Note that this will not free the wiimote structure. + */ +void wiiuse_disconnect(struct wiimote_t* wm) { + if (!wm || WIIMOTE_IS_CONNECTED(wm)) + return; + + close(wm->out_sock); + close(wm->in_sock); + + wm->out_sock = -1; + wm->in_sock = -1; + wm->event = WIIUSE_NONE; + + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); +} + + +int wiiuse_io_read(struct wiimote_t* wm) { + /* not used */ + return 0; +} + + +int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) { + return write(wm->out_sock, buf, len); +} + + + +#endif /* ifndef WIN32 */ diff --git a/Externals/WiiUseSrc/Src/io_win.c b/Externals/WiiUseSrc/Src/io_win.c new file mode 100644 index 0000000000..17fac360d3 --- /dev/null +++ b/Externals/WiiUseSrc/Src/io_win.c @@ -0,0 +1,247 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles device I/O for Windows. + */ + +#ifdef WIN32 + +#include +#include + +#include +#include +#include + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "io.h" + + +int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { + GUID device_id; + HANDLE dev; + HDEVINFO device_info; + int i, index; + DWORD len; + SP_DEVICE_INTERFACE_DATA device_data; + PSP_DEVICE_INTERFACE_DETAIL_DATA detail_data = NULL; + HIDD_ATTRIBUTES attr; + int found = 0; + + (void) timeout; // unused + + device_data.cbSize = sizeof(device_data); + index = 0; + + /* get the device id */ + HidD_GetHidGuid(&device_id); + + /* get all hid devices connected */ + device_info = SetupDiGetClassDevs(&device_id, NULL, NULL, (DIGCF_DEVICEINTERFACE | DIGCF_PRESENT)); + + for (;; ++index) { + + if (detail_data) { + free(detail_data); + detail_data = NULL; + } + + /* query the next hid device info */ + if (!SetupDiEnumDeviceInterfaces(device_info, NULL, &device_id, index, &device_data)) + break; + + /* get the size of the data block required */ + i = SetupDiGetDeviceInterfaceDetail(device_info, &device_data, NULL, 0, &len, NULL); + detail_data = malloc(len); + detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + + /* query the data for this device */ + if (!SetupDiGetDeviceInterfaceDetail(device_info, &device_data, detail_data, len, NULL, NULL)) + continue; + + /* open the device */ + dev = CreateFile(detail_data->DevicePath, + (GENERIC_READ | GENERIC_WRITE), + (FILE_SHARE_READ | FILE_SHARE_WRITE), + NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (dev == INVALID_HANDLE_VALUE) + continue; + + /* get device attributes */ + attr.Size = sizeof(attr); + i = HidD_GetAttributes(dev, &attr); + + if ((attr.VendorID == WM_VENDOR_ID) && (attr.ProductID == WM_PRODUCT_ID)) { + /* this is a wiimote */ + wm[found]->dev_handle = dev; + + wm[found]->hid_overlap.hEvent = CreateEvent(NULL, 1, 1, ""); + wm[found]->hid_overlap.Offset = 0; + wm[found]->hid_overlap.OffsetHigh = 0; + + WIIMOTE_ENABLE_STATE(wm[found], WIIMOTE_STATE_DEV_FOUND); + WIIMOTE_ENABLE_STATE(wm[found], WIIMOTE_STATE_CONNECTED); + + /* try to set the output report to see if the device is actually connected */ + if (!wiiuse_set_report_type(wm[found])) { + WIIMOTE_DISABLE_STATE(wm[found], WIIMOTE_STATE_CONNECTED); + continue; + } + + /* do the handshake */ + wiiuse_handshake(wm[found], NULL, 0); + + WIIUSE_INFO("Connected to wiimote [id %i].", wm[found]->unid); + + ++found; + if (found >= max_wiimotes) + break; + } else { + /* not a wiimote */ + CloseHandle(dev); + } + } + + if (detail_data) + free(detail_data); + + SetupDiDestroyDeviceInfoList(device_info); + + return found; +} + + +int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { + int connected = 0; + int i = 0; + + for (; i < wiimotes; ++i) { + if (WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_CONNECTED)) + ++connected; + } + + return connected; +} + + +void wiiuse_disconnect(struct wiimote_t* wm) { + if (!wm || WIIMOTE_IS_CONNECTED(wm)) + return; + + CloseHandle(wm->dev_handle); + wm->dev_handle = 0; + + ResetEvent(&wm->hid_overlap); + + wm->event = WIIUSE_NONE; + + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); +} + + +int wiiuse_io_read(struct wiimote_t* wm) { + DWORD b, r; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0; + + if (!ReadFile(wm->dev_handle, wm->event_buf, sizeof(wm->event_buf), &b, &wm->hid_overlap)) { + /* partial read */ + b = GetLastError(); + + if ((b == ERROR_HANDLE_EOF) || (b == ERROR_DEVICE_NOT_CONNECTED)) { + /* remote disconnect */ + wiiuse_disconnected(wm); + return 0; + } + + r = WaitForSingleObject(wm->hid_overlap.hEvent, wm->timeout); + if (r == WAIT_TIMEOUT) { + /* timeout - cancel and continue */ + + if (*wm->event_buf) + WIIUSE_WARNING("Packet ignored. This may indicate a problem (timeout is %i ms).", wm->timeout); + + CancelIo(wm->dev_handle); + ResetEvent(wm->hid_overlap.hEvent); + return 0; + } else if (r == WAIT_FAILED) { + WIIUSE_WARNING("A wait error occured on reading from wiimote %i.", wm->unid); + return 0; + } + + if (!GetOverlappedResult(wm->dev_handle, &wm->hid_overlap, &b, 0)) + return 0; + } + + ResetEvent(wm->hid_overlap.hEvent); + return 1; +} + + +int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) { + DWORD bytes; + int i; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0; + + switch (wm->stack) { + case WIIUSE_STACK_UNKNOWN: + { + /* try to auto-detect the stack type */ + if (i = WriteFile(wm->dev_handle, buf, 22, &bytes, &wm->hid_overlap)) { + /* bluesoleil will always return 1 here, even if it's not connected */ + wm->stack = WIIUSE_STACK_BLUESOLEIL; + return i; + } + + if (i = HidD_SetOutputReport(wm->dev_handle, buf, len)) { + wm->stack = WIIUSE_STACK_MS; + return i; + } + + WIIUSE_ERROR("Unable to determine bluetooth stack type."); + return 0; + } + + case WIIUSE_STACK_MS: + return HidD_SetOutputReport(wm->dev_handle, buf, len); + + case WIIUSE_STACK_BLUESOLEIL: + return WriteFile(wm->dev_handle, buf, 22, &bytes, &wm->hid_overlap); + } + + return 0; +} + +#endif /* ifdef WIN32 */ diff --git a/Externals/WiiUseSrc/Src/ir.c b/Externals/WiiUseSrc/Src/ir.c new file mode 100644 index 0000000000..7a9bb68289 --- /dev/null +++ b/Externals/WiiUseSrc/Src/ir.c @@ -0,0 +1,748 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles IR data. + */ + +#include +#include + +#ifndef WIN32 + #include +#endif + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "ir.h" + +static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2); +static void interpret_ir_data(struct wiimote_t* wm); +static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang); +static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y); +static void reorder_ir_dots(struct ir_dot_t* dot); +static float ir_distance(struct ir_dot_t* dot); +static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y); +static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, int vx, int vy); + + +/** + * @brief Set if the wiimote should track IR targets. + * + * @param wm Pointer to a wiimote_t structure. + * @param status 1 to enable, 0 to disable. + */ +void wiiuse_set_ir(struct wiimote_t* wm, int status) { + byte buf; + char* block1 = NULL; + char* block2 = NULL; + int ir_level; + + if (!wm) + return; + + /* + * Wait for the handshake to finish first. + * When it handshake finishes and sees that + * IR is enabled, it will call this function + * again to actually enable IR. + */ + if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE)) { + WIIUSE_DEBUG("Tried to enable IR, will wait until handshake finishes."); + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR); + return; + } + + /* + * Check to make sure a sensitivity setting is selected. + */ + ir_level = get_ir_sens(wm, &block1, &block2); + if (!ir_level) { + WIIUSE_ERROR("No IR sensitivity setting selected."); + return; + } + + if (status) { + /* if already enabled then stop */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) + return; + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR); + } else { + /* if already disabled then stop */ + if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) + return; + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR); + } + + /* set camera 1 and 2 */ + buf = (status ? 0x04 : 0x00); + wiiuse_send(wm, WM_CMD_IR, &buf, 1); + wiiuse_send(wm, WM_CMD_IR_2, &buf, 1); + + if (!status) { + WIIUSE_DEBUG("Disabled IR cameras for wiimote id %i.", wm->unid); + wiiuse_set_report_type(wm); + return; + } + + /* enable IR, set sensitivity */ + buf = 0x08; + wiiuse_write_data(wm, WM_REG_IR, &buf, 1); + + /* wait for the wiimote to catch up */ + #ifndef WIN32 + usleep(50000); + #else + Sleep(50); + #endif + + /* write sensitivity blocks */ + wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9); + wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2); + + /* set the IR mode */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) + buf = WM_IR_TYPE_BASIC; + else + buf = WM_IR_TYPE_EXTENDED; + wiiuse_write_data(wm, WM_REG_IR_MODENUM, &buf, 1); + + #ifndef WIN32 + usleep(50000); + #else + Sleep(50); + #endif + + /* set the wiimote report type */ + wiiuse_set_report_type(wm); + + WIIUSE_DEBUG("Enabled IR camera for wiimote id %i (sensitivity level %i).", wm->unid, ir_level); +} + + +/** + * @brief Get the IR sensitivity settings. + * + * @param wm Pointer to a wiimote_t structure. + * @param block1 [out] Pointer to where block1 will be set. + * @param block2 [out] Pointer to where block2 will be set. + * + * @return Returns the sensitivity level. + */ +static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2) { + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL1)) { + *block1 = WM_IR_BLOCK1_LEVEL1; + *block2 = WM_IR_BLOCK2_LEVEL1; + return 1; + } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL2)) { + *block1 = WM_IR_BLOCK1_LEVEL2; + *block2 = WM_IR_BLOCK2_LEVEL2; + return 2; + } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL3)) { + *block1 = WM_IR_BLOCK1_LEVEL3; + *block2 = WM_IR_BLOCK2_LEVEL3; + return 3; + } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL4)) { + *block1 = WM_IR_BLOCK1_LEVEL4; + *block2 = WM_IR_BLOCK2_LEVEL4; + return 4; + } else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL5)) { + *block1 = WM_IR_BLOCK1_LEVEL5; + *block2 = WM_IR_BLOCK2_LEVEL5; + return 5; + } + + *block1 = NULL; + *block2 = NULL; + return 0; +} + + +/** + * @brief Set the virtual screen resolution for IR tracking. + * + * @param wm Pointer to a wiimote_t structure. + * @param status 1 to enable, 0 to disable. + */ +void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y) { + if (!wm) return; + + wm->ir.vres[0] = (x-1); + wm->ir.vres[1] = (y-1); +} + + +/** + * @brief Set the XY position for the IR cursor. + * + * @param wm Pointer to a wiimote_t structure. + */ +void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos) { + if (!wm) return; + + wm->ir.pos = pos; + + switch (pos) { + + case WIIUSE_IR_ABOVE: + wm->ir.offset[0] = 0; + + if (wm->ir.aspect == WIIUSE_ASPECT_16_9) + wm->ir.offset[1] = WM_ASPECT_16_9_Y/2 - 70; + else if (wm->ir.aspect == WIIUSE_ASPECT_4_3) + wm->ir.offset[1] = WM_ASPECT_4_3_Y/2 - 100; + + return; + + case WIIUSE_IR_BELOW: + wm->ir.offset[0] = 0; + + if (wm->ir.aspect == WIIUSE_ASPECT_16_9) + wm->ir.offset[1] = -WM_ASPECT_16_9_Y/2 + 100; + else if (wm->ir.aspect == WIIUSE_ASPECT_4_3) + wm->ir.offset[1] = -WM_ASPECT_4_3_Y/2 + 70; + + return; + + default: + return; + }; +} + + +/** + * @brief Set the aspect ratio of the TV/monitor. + * + * @param wm Pointer to a wiimote_t structure. + * @param aspect Either WIIUSE_ASPECT_16_9 or WIIUSE_ASPECT_4_3 + */ +void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect) { + if (!wm) return; + + wm->ir.aspect = aspect; + + if (aspect == WIIUSE_ASPECT_4_3) { + wm->ir.vres[0] = WM_ASPECT_4_3_X; + wm->ir.vres[1] = WM_ASPECT_4_3_Y; + } else { + wm->ir.vres[0] = WM_ASPECT_16_9_X; + wm->ir.vres[1] = WM_ASPECT_16_9_Y; + } + + /* reset the position offsets */ + wiiuse_set_ir_position(wm, wm->ir.pos); +} + + +/** + * @brief Set the IR sensitivity. + * + * @param wm Pointer to a wiimote_t structure. + * @param level 1-5, same as Wii system sensitivity setting. + * + * If the level is < 1, then level will be set to 1. + * If the level is > 5, then level will be set to 5. + */ +void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level) { + char* block1 = NULL; + char* block2 = NULL; + + if (!wm) return; + + if (level > 5) level = 5; + if (level < 1) level = 1; + + WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR_SENS_LVL1 | + WIIMOTE_STATE_IR_SENS_LVL2 | + WIIMOTE_STATE_IR_SENS_LVL3 | + WIIMOTE_STATE_IR_SENS_LVL4 | + WIIMOTE_STATE_IR_SENS_LVL5)); + + switch (level) { + case 1: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL1); + break; + case 2: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL2); + break; + case 3: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL3); + break; + case 4: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL4); + break; + case 5: + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL5); + break; + default: + return; + } + + /* set the new sensitivity */ + get_ir_sens(wm, &block1, &block2); + + wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (byte*)block1, 9); + wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (byte*)block2, 2); + + WIIUSE_DEBUG("Set IR sensitivity to level %i (unid %i)", level, wm->unid); +} + + +/** + * @brief Calculate the data from the IR spots. Basic IR mode. + * + * @param wm Pointer to a wiimote_t structure. + * @param data Data returned by the wiimote for the IR spots. + */ +void calculate_basic_ir(struct wiimote_t* wm, byte* data) { + struct ir_dot_t* dot = wm->ir.dot; + int i; + + dot[0].rx = 1023 - (data[0] | ((data[2] & 0x30) << 4)); + dot[0].ry = data[1] | ((data[2] & 0xC0) << 2); + + dot[1].rx = 1023 - (data[3] | ((data[2] & 0x03) << 8)); + dot[1].ry = data[4] | ((data[2] & 0x0C) << 6); + + dot[2].rx = 1023 - (data[5] | ((data[7] & 0x30) << 4)); + dot[2].ry = data[6] | ((data[7] & 0xC0) << 2); + + dot[3].rx = 1023 - (data[8] | ((data[7] & 0x03) << 8)); + dot[3].ry = data[9] | ((data[7] & 0x0C) << 6); + + /* set each IR spot to visible if spot is in range */ + for (i = 0; i < 4; ++i) { + if (dot[i].ry == 1023) + dot[i].visible = 0; + else { + dot[i].visible = 1; + dot[i].size = 0; /* since we don't know the size, set it as 0 */ + } + } + + interpret_ir_data(wm); +} + + +/** + * @brief Calculate the data from the IR spots. Extended IR mode. + * + * @param wm Pointer to a wiimote_t structure. + * @param data Data returned by the wiimote for the IR spots. + */ +void calculate_extended_ir(struct wiimote_t* wm, byte* data) { + struct ir_dot_t* dot = wm->ir.dot; + int i; + + for (i = 0; i < 4; ++i) { + dot[i].rx = 1023 - (data[3*i] | ((data[(3*i)+2] & 0x30) << 4)); + dot[i].ry = data[(3*i)+1] | ((data[(3*i)+2] & 0xC0) << 2); + + dot[i].size = data[(3*i)+2] & 0x0F; + + /* if in range set to visible */ + if (dot[i].ry == 1023) + dot[i].visible = 0; + else + dot[i].visible = 1; + } + + interpret_ir_data(wm); +} + + +/** + * @brief Interpret IR data into more user friendly variables. + * + * @param wm Pointer to a wiimote_t structure. + */ +static void interpret_ir_data(struct wiimote_t* wm) { + struct ir_dot_t* dot = wm->ir.dot; + int i; + float roll = 0.0f; + int last_num_dots = wm->ir.num_dots; + + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC)) + roll = wm->orient.roll; + + /* count visible dots */ + wm->ir.num_dots = 0; + for (i = 0; i < 4; ++i) { + if (dot[i].visible) + wm->ir.num_dots++; + } + + switch (wm->ir.num_dots) { + case 0: + { + wm->ir.state = 0; + + /* reset the dot ordering */ + for (i = 0; i < 4; ++i) + dot[i].order = 0; + + wm->ir.x = 0; + wm->ir.y = 0; + wm->ir.z = 0.0f; + + return; + } + case 1: + { + fix_rotated_ir_dots(wm->ir.dot, roll); + + if (wm->ir.state < 2) { + /* + * Only 1 known dot, so use just that. + */ + for (i = 0; i < 4; ++i) { + if (dot[i].visible) { + wm->ir.x = dot[i].x; + wm->ir.y = dot[i].y; + + wm->ir.ax = wm->ir.x; + wm->ir.ay = wm->ir.y; + + /* can't calculate yaw because we don't have the distance */ + //wm->orient.yaw = calc_yaw(&wm->ir); + + ir_convert_to_vres(&wm->ir.x, &wm->ir.y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]); + break; + } + } + } else { + /* + * Only see 1 dot but know theres 2. + * Try to estimate where the other one + * should be and use that. + */ + for (i = 0; i < 4; ++i) { + if (dot[i].visible) { + int ox = 0; + int x, y; + + if (dot[i].order == 1) + /* visible is the left dot - estimate where the right is */ + ox = dot[i].x + wm->ir.distance; + else if (dot[i].order == 2) + /* visible is the right dot - estimate where the left is */ + ox = dot[i].x - wm->ir.distance; + + x = ((signed int)dot[i].x + ox) / 2; + y = dot[i].y; + + wm->ir.ax = x; + wm->ir.ay = y; + wm->orient.yaw = calc_yaw(&wm->ir); + + if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) { + ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]); + wm->ir.x = x; + wm->ir.y = y; + } + + break; + } + } + } + + break; + } + case 2: + case 3: + case 4: + { + /* + * Two (or more) dots known and seen. + * Average them together to estimate the true location. + */ + int x, y; + wm->ir.state = 2; + + fix_rotated_ir_dots(wm->ir.dot, roll); + + /* if there is at least 1 new dot, reorder them all */ + if (wm->ir.num_dots > last_num_dots) { + reorder_ir_dots(dot); + wm->ir.x = 0; + wm->ir.y = 0; + } + + wm->ir.distance = ir_distance(dot); + wm->ir.z = 1023 - wm->ir.distance; + + get_ir_dot_avg(wm->ir.dot, &x, &y); + + wm->ir.ax = x; + wm->ir.ay = y; + wm->orient.yaw = calc_yaw(&wm->ir); + + if (ir_correct_for_bounds(&x, &y, wm->ir.aspect, wm->ir.offset[0], wm->ir.offset[1])) { + ir_convert_to_vres(&x, &y, wm->ir.aspect, wm->ir.vres[0], wm->ir.vres[1]); + wm->ir.x = x; + wm->ir.y = y; + } + + break; + } + default: + { + break; + } + } + + #ifdef WITH_WIIUSE_DEBUG + { + int ir_level; + WIIUSE_GET_IR_SENSITIVITY(wm, &ir_level); + WIIUSE_DEBUG("IR sensitivity: %i", ir_level); + WIIUSE_DEBUG("IR visible dots: %i", wm->ir.num_dots); + for (i = 0; i < 4; ++i) + if (dot[i].visible) + WIIUSE_DEBUG("IR[%i][order %i] (%.3i, %.3i) -> (%.3i, %.3i)", i, dot[i].order, dot[i].rx, dot[i].ry, dot[i].x, dot[i].y); + WIIUSE_DEBUG("IR[absolute]: (%i, %i)", wm->ir.x, wm->ir.y); + } + #endif +} + + + +/** + * @brief Fix the rotation of the IR dots. + * + * @param dot An array of 4 ir_dot_t objects. + * @param ang The roll angle to correct by (-180, 180) + * + * If there is roll then the dots are rotated + * around the origin and give a false cursor + * position. Correct for the roll. + * + * If the accelerometer is off then obviously + * this will not do anything and the cursor + * position may be inaccurate. + */ +static void fix_rotated_ir_dots(struct ir_dot_t* dot, float ang) { + float s, c; + int x, y; + int i; + + if (!ang) { + for (i = 0; i < 4; ++i) { + dot[i].x = dot[i].rx; + dot[i].y = dot[i].ry; + } + return; + } + + s = sin(DEGREE_TO_RAD(ang)); + c = cos(DEGREE_TO_RAD(ang)); + + /* + * [ cos(theta) -sin(theta) ][ ir->rx ] + * [ sin(theta) cos(theta) ][ ir->ry ] + */ + + for (i = 0; i < 4; ++i) { + if (!dot[i].visible) + continue; + + x = dot[i].rx - (1024/2); + y = dot[i].ry - (768/2); + + dot[i].x = (c * x) + (-s * y); + dot[i].y = (s * x) + (c * y); + + dot[i].x += (1024/2); + dot[i].y += (768/2); + } +} + + +/** + * @brief Average IR dots. + * + * @param dot An array of 4 ir_dot_t objects. + * @param x [out] Average X + * @param y [out] Average Y + */ +static void get_ir_dot_avg(struct ir_dot_t* dot, int* x, int* y) { + int vis = 0, i = 0; + + *x = 0; + *y = 0; + + for (; i < 4; ++i) { + if (dot[i].visible) { + *x += dot[i].x; + *y += dot[i].y; + ++vis; + } + } + + *x /= vis; + *y /= vis; +} + + +/** + * @brief Reorder the IR dots. + * + * @param dot An array of 4 ir_dot_t objects. + */ +static void reorder_ir_dots(struct ir_dot_t* dot) { + int i, j, order; + + /* reset the dot ordering */ + for (i = 0; i < 4; ++i) + dot[i].order = 0; + + for (order = 1; order < 5; ++order) { + i = 0; + + for (; !dot[i].visible || dot[i].order; ++i) + if (i > 4) + return; + + for (j = 0; j < 4; ++j) { + if (dot[j].visible && !dot[j].order && (dot[j].x < dot[i].x)) + i = j; + } + + dot[i].order = order; + } +} + + +/** + * @brief Calculate the distance between the first 2 visible IR dots. + * + * @param dot An array of 4 ir_dot_t objects. + */ +static float ir_distance(struct ir_dot_t* dot) { + int i1, i2; + int xd, yd; + + for (i1 = 0; i1 < 4; ++i1) + if (dot[i1].visible) + break; + if (i1 == 4) + return 0.0f; + + for (i2 = i1+1; i2 < 4; ++i2) + if (dot[i2].visible) + break; + if (i2 == 4) + return 0.0f; + + xd = dot[i2].x - dot[i1].x; + yd = dot[i2].y - dot[i1].y; + + return sqrt(xd*xd + yd*yd); +} + + +/** + * @brief Correct for the IR bounding box. + * + * @param x [out] The current X, it will be updated if valid. + * @param y [out] The current Y, it will be updated if valid. + * @param aspect Aspect ratio of the screen. + * @param offset_x The X offset of the bounding box. + * @param offset_y The Y offset of the bounding box. + * + * @return Returns 1 if the point is valid and was updated. + * + * Nintendo was smart with this bit. They sacrifice a little + * precision for a big increase in usability. + */ +static int ir_correct_for_bounds(int* x, int* y, enum aspect_t aspect, int offset_x, int offset_y) { + int x0, y0; + int xs, ys; + + if (aspect == WIIUSE_ASPECT_16_9) { + xs = WM_ASPECT_16_9_X; + ys = WM_ASPECT_16_9_Y; + } else { + xs = WM_ASPECT_4_3_X; + ys = WM_ASPECT_4_3_Y; + } + + x0 = ((1024 - xs) / 2) + offset_x; + y0 = ((768 - ys) / 2) + offset_y; + + if ((*x >= x0) + && (*x <= (x0 + xs)) + && (*y >= y0) + && (*y <= (y0 + ys))) + { + *x -= offset_x; + *y -= offset_y; + + return 1; + } + + return 0; +} + + +/** + * @brief Interpolate the point to the user defined virtual screen resolution. + */ +static void ir_convert_to_vres(int* x, int* y, enum aspect_t aspect, int vx, int vy) { + int xs, ys; + + if (aspect == WIIUSE_ASPECT_16_9) { + xs = WM_ASPECT_16_9_X; + ys = WM_ASPECT_16_9_Y; + } else { + xs = WM_ASPECT_4_3_X; + ys = WM_ASPECT_4_3_Y; + } + + *x -= ((1024-xs)/2); + *y -= ((768-ys)/2); + + *x = (*x / (float)xs) * vx; + *y = (*y / (float)ys) * vy; +} + + +/** + * @brief Calculate yaw given the IR data. + * + * @param ir IR data structure. + */ +float calc_yaw(struct ir_t* ir) { + float x; + + x = ir->ax - 512; + x = x * (ir->z / 1024.0f); + + return RAD_TO_DEGREE( atanf(x / ir->z) ); +} diff --git a/Externals/WiiUseSrc/Src/ir.h b/Externals/WiiUseSrc/Src/ir.h new file mode 100644 index 0000000000..9082492987 --- /dev/null +++ b/Externals/WiiUseSrc/Src/ir.h @@ -0,0 +1,56 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Handles IR data. + */ + +#ifndef IR_H_INCLUDED +#define IR_H_INCLUDED + +#include "wiiuse_internal.h" + +#define WII_VRES_X 560 +#define WII_VRES_Y 340 + +#ifdef __cplusplus +extern "C" { +#endif + +void calculate_basic_ir(struct wiimote_t* wm, byte* data); +void calculate_extended_ir(struct wiimote_t* wm, byte* data); +float calc_yaw(struct ir_t* ir); + +#ifdef __cplusplus +} +#endif + +#endif // IR_H_INCLUDED + + diff --git a/Externals/WiiUseSrc/Src/nunchuk.c b/Externals/WiiUseSrc/Src/nunchuk.c new file mode 100644 index 0000000000..48dbe6a089 --- /dev/null +++ b/Externals/WiiUseSrc/Src/nunchuk.c @@ -0,0 +1,210 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Nunchuk expansion device. + */ + +#include +#include +#include + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "dynamics.h" +#include "events.h" +#include "nunchuk.h" + +static void nunchuk_pressed_buttons(struct nunchuk_t* nc, byte now); + +/** + * @brief Handle the handshake data from the nunchuk. + * + * @param nc A pointer to a nunchuk_t structure. + * @param data The data read in from the device. + * @param len The length of the data block, in bytes. + * + * @return Returns 1 if handshake was successful, 0 if not. + */ +int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len) { + int i; + int offset = 0; + + nc->btns = 0; + nc->btns_held = 0; + nc->btns_released = 0; + + /* set the smoothing to the same as the wiimote */ + nc->flags = &wm->flags; + nc->accel_calib.st_alpha = wm->accel_calib.st_alpha; + + /* decrypt data */ + for (i = 0; i < len; ++i) + data[i] = (data[i] ^ 0x17) + 0x17; + + if (data[offset] == 0xFF) { + /* + * Sometimes the data returned here is not correct. + * This might happen because the wiimote is lagging + * behind our initialization sequence. + * To fix this just request the handshake again. + * + * Other times it's just the first 16 bytes are 0xFF, + * but since the next 16 bytes are the same, just use + * those. + */ + if (data[offset + 16] == 0xFF) { + /* get the calibration data */ + byte* handshake_buf = malloc(EXP_HANDSHAKE_LEN * sizeof(byte)); + + WIIUSE_DEBUG("Nunchuk 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; + } + + nc->accel_calib.cal_zero.x = data[offset + 0]; + nc->accel_calib.cal_zero.y = data[offset + 1]; + nc->accel_calib.cal_zero.z = data[offset + 2]; + nc->accel_calib.cal_g.x = data[offset + 4]; + nc->accel_calib.cal_g.y = data[offset + 5]; + nc->accel_calib.cal_g.z = data[offset + 6]; + nc->js.max.x = data[offset + 8]; + nc->js.min.x = data[offset + 9]; + nc->js.center.x = data[offset + 10]; + nc->js.max.y = data[offset + 11]; + nc->js.min.y = data[offset + 12]; + nc->js.center.y = data[offset + 13]; + + /* default the thresholds to the same as the wiimote */ + nc->orient_threshold = wm->orient_threshold; + nc->accel_threshold = wm->accel_threshold; + + /* handshake done */ + wm->exp.type = EXP_NUNCHUK; + + #ifdef WIN32 + wm->timeout = WIIMOTE_DEFAULT_TIMEOUT; + #endif + + return 1; +} + + +/** + * @brief The nunchuk disconnected. + * + * @param nc A pointer to a nunchuk_t structure. + */ +void nunchuk_disconnected(struct nunchuk_t* nc) { + memset(nc, 0, sizeof(struct nunchuk_t)); +} + + + +/** + * @brief Handle nunchuk event. + * + * @param nc A pointer to a nunchuk_t structure. + * @param msg The message specified in the event packet. + */ +void nunchuk_event(struct nunchuk_t* nc, byte* msg) { + int i; + + /* decrypt data */ + for (i = 0; i < 6; ++i) + msg[i] = (msg[i] ^ 0x17) + 0x17; + + /* get button states */ + nunchuk_pressed_buttons(nc, msg[5]); + + /* calculate joystick state */ + calc_joystick_state(&nc->js, msg[0], msg[1]); + + /* calculate orientation */ + nc->accel.x = msg[2]; + nc->accel.y = msg[3]; + nc->accel.z = msg[4]; + + calculate_orientation(&nc->accel_calib, &nc->accel, &nc->orient, NUNCHUK_IS_FLAG_SET(nc, WIIUSE_SMOOTHING)); + calculate_gforce(&nc->accel_calib, &nc->accel, &nc->gforce); +} + + +/** + * @brief Find what buttons are pressed. + * + * @param nc Pointer to a nunchuk_t structure. + * @param msg The message byte specified in the event packet. + */ +static void nunchuk_pressed_buttons(struct nunchuk_t* nc, byte now) { + /* message is inverted (0 is active, 1 is inactive) */ + now = ~now & NUNCHUK_BUTTON_ALL; + + /* pressed now & were pressed, then held */ + nc->btns_held = (now & nc->btns); + + /* were pressed or were held & not pressed now, then released */ + nc->btns_released = ((nc->btns | nc->btns_held) & ~now); + + /* buttons pressed now */ + nc->btns = now; +} + + +/** + * @brief Set the orientation event threshold for the nunchuk. + * + * @param wm Pointer to a wiimote_t structure with a nunchuk attached. + * @param threshold The decimal place that should be considered a significant change. + * + * See wiiuse_set_orient_threshold() for details. + */ +void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold) { + if (!wm) return; + + wm->exp.nunchuk.orient_threshold = threshold; +} + + +/** + * @brief Set the accelerometer event threshold for the nunchuk. + * + * @param wm Pointer to a wiimote_t structure with a nunchuk attached. + * @param threshold The decimal place that should be considered a significant change. + * + * See wiiuse_set_orient_threshold() for details. + */ +void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold) { + if (!wm) return; + + wm->exp.nunchuk.accel_threshold = threshold; +} diff --git a/Externals/WiiUseSrc/Src/nunchuk.h b/Externals/WiiUseSrc/Src/nunchuk.h new file mode 100644 index 0000000000..f036073d64 --- /dev/null +++ b/Externals/WiiUseSrc/Src/nunchuk.h @@ -0,0 +1,53 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief Nunchuk expansion device. + */ + +#ifndef NUNCHUK_H_INCLUDED +#define NUNCHUK_H_INCLUDED + +#include "wiiuse_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, unsigned short len); + +void nunchuk_disconnected(struct nunchuk_t* nc); + +void nunchuk_event(struct nunchuk_t* nc, byte* msg); + +#ifdef __cplusplus +} +#endif + +#endif // NUNCHUK_H_INCLUDED diff --git a/Externals/WiiUseSrc/Src/os.h b/Externals/WiiUseSrc/Src/os.h new file mode 100644 index 0000000000..53b80f557c --- /dev/null +++ b/Externals/WiiUseSrc/Src/os.h @@ -0,0 +1,56 @@ +/* + * 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 . + * + * $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 OS_H_INCLUDED +#define OS_H_INCLUDED + +#ifdef WIN32 + /* windows */ + #define isnan(x) _isnan(x) + #define isinf(x) !_finite(x) + + /* disable warnings I don't care about */ + #pragma warning(disable:4244) /* possible loss of data conversion */ + #pragma warning(disable:4273) /* inconsistent dll linkage */ + #pragma warning(disable:4217) +#else + /* nix */ +#endif + + +#endif // OS_H_INCLUDED diff --git a/Externals/WiiUseSrc/Src/wiiuse.c b/Externals/WiiUseSrc/Src/wiiuse.c new file mode 100644 index 0000000000..8d4b763864 --- /dev/null +++ b/Externals/WiiUseSrc/Src/wiiuse.c @@ -0,0 +1,764 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief General wiimote operations. + * + * The file includes functions that handle general + * tasks. Most of these are functions that are part + * of the API. + */ + +#include +#include + +#ifndef WIN32 + #include +#else + #include +#endif + +#include "definitions.h" +#include "wiiuse_internal.h" +#include "events.h" +#include "io.h" + +static int g_banner = 0; + +/** + * @breif Returns the version of the library. + */ +const char* wiiuse_version() { + return WIIUSE_VERSION; +} + + +/** + * @brief Clean up wiimote_t array created by wiiuse_init() + */ +void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes) { + int i = 0; + + if (!wm) + return; + + WIIUSE_INFO("wiiuse clean up..."); + + for (; i < wiimotes; ++i) { + wiiuse_disconnect(wm[i]); + free(wm[i]); + } + + free(wm); + + return; +} + + +/** + * @brief Initialize an array of wiimote structures. + * + * @param wiimotes Number of wiimote_t structures to create. + * + * @return An array of initialized wiimote_t structures. + * + * @see wiiuse_connect() + * + * The array returned by this function can be passed to various + * functions, including wiiuse_connect(). + */ +struct wiimote_t** wiiuse_init(int wiimotes) { + int i = 0; + struct wiimote_t** wm = NULL; + + /* + * Please do not remove this banner. + * GPL asks that you please leave output credits intact. + * Thank you. + * + * This banner is only displayed once so that if you need + * to call this function again it won't be intrusive. + */ + if (!g_banner) { + printf( "wiiuse v" WIIUSE_VERSION " loaded.\n" + " By: Michael Laforest \n" + " http://wiiuse.net http://wiiuse.sf.net\n"); + g_banner = 1; + } + + if (!wiimotes) + return NULL; + + wm = malloc(sizeof(struct wiimote_t*) * wiimotes); + + for (i = 0; i < wiimotes; ++i) { + wm[i] = malloc(sizeof(struct wiimote_t)); + memset(wm[i], 0, sizeof(struct wiimote_t)); + + wm[i]->unid = i+1; + + #ifndef WIN32 + wm[i]->bdaddr = *BDADDR_ANY; + wm[i]->out_sock = -1; + wm[i]->in_sock = -1; + #else + wm[i]->dev_handle = 0; + wm[i]->stack = WIIUSE_STACK_UNKNOWN; + wm[i]->normal_timeout = WIIMOTE_DEFAULT_TIMEOUT; + wm[i]->exp_timeout = WIIMOTE_EXP_TIMEOUT; + wm[i]->timeout = wm[i]->normal_timeout; + #endif + + wm[i]->state = WIIMOTE_INIT_STATES; + wm[i]->flags = WIIUSE_INIT_FLAGS; + + wm[i]->event = WIIUSE_NONE; + + wm[i]->exp.type = EXP_NONE; + + wiiuse_set_aspect_ratio(wm[i], WIIUSE_ASPECT_4_3); + wiiuse_set_ir_position(wm[i], WIIUSE_IR_ABOVE); + + wm[i]->orient_threshold = 0.5f; + wm[i]->accel_threshold = 5; + + wm[i]->accel_calib.st_alpha = WIIUSE_DEFAULT_SMOOTH_ALPHA; + } + + return wm; +} + + +/** + * @brief The wiimote disconnected. + * + * @param wm Pointer to a wiimote_t structure. + */ +void wiiuse_disconnected(struct wiimote_t* wm) { + if (!wm) return; + + WIIUSE_INFO("Wiimote disconnected [id %i].", wm->unid); + + /* disable the connected flag */ + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); + + /* reset a bunch of stuff */ + #ifndef WIN32 + wm->out_sock = -1; + wm->in_sock = -1; + #else + wm->dev_handle = 0; + #endif + + wm->leds = 0; + wm->state = WIIMOTE_INIT_STATES; + wm->read_req = NULL; + wm->handshake_state = 0; + wm->btns = 0; + wm->btns_held = 0; + wm->btns_released = 0; + memset(wm->event_buf, 0, sizeof(wm->event_buf)); + + wm->event = WIIUSE_DISCONNECT; +} + + +/** + * @brief Enable or disable the rumble. + * + * @param wm Pointer to a wiimote_t structure. + * @param status 1 to enable, 0 to disable. + */ +void wiiuse_rumble(struct wiimote_t* wm, int status) { + byte buf; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return; + + /* make sure to keep the current lit leds */ + buf = wm->leds; + + if (status) { + WIIUSE_DEBUG("Starting rumble..."); + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_RUMBLE); + buf |= 0x01; + } else { + WIIUSE_DEBUG("Stopping rumble..."); + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_RUMBLE); + } + + /* preserve IR state */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) + buf |= 0x04; + + wiiuse_send(wm, WM_CMD_RUMBLE, &buf, 1); +} + + +/** + * @brief Toggle the state of the rumble. + * + * @param wm Pointer to a wiimote_t structure. + */ +void wiiuse_toggle_rumble(struct wiimote_t* wm) { + if (!wm) return; + + wiiuse_rumble(wm, !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE)); +} + + +/** + * @brief Set the enabled LEDs. + * + * @param wm Pointer to a wiimote_t structure. + * @param leds What LEDs to enable. + * + * \a leds is a bitwise or of WIIMOTE_LED_1, WIIMOTE_LED_2, WIIMOTE_LED_3, or WIIMOTE_LED_4. + */ +void wiiuse_set_leds(struct wiimote_t* wm, int leds) { + byte buf; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return; + + /* remove the lower 4 bits because they control rumble */ + wm->leds = (leds & 0xF0); + + /* make sure if the rumble is on that we keep it on */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE)) + wm->leds |= 0x01; + + buf = wm->leds; + + wiiuse_send(wm, WM_CMD_LED, &buf, 1); +} + + +/** + * @brief Set if the wiimote should report motion sensing. + * + * @param wm Pointer to a wiimote_t structure. + * @param status 1 to enable, 0 to disable. + * + * Since reporting motion sensing sends a lot of data, + * the wiimote saves power by not transmitting it + * by default. + */ +void wiiuse_motion_sensing(struct wiimote_t* wm, int status) { + if (status) + WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_ACC); + else + WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC); + + wiiuse_set_report_type(wm); +} + + +/** + * @brief Set the report type based on the current wiimote state. + * + * @param wm Pointer to a wiimote_t structure. + * + * @return The report type sent. + * + * The wiimote reports formatted packets depending on the + * report type that was last requested. This function will + * update the type of report that should be sent based on + * the current state of the device. + */ +int wiiuse_set_report_type(struct wiimote_t* wm) { + byte buf[2]; + int motion, exp, ir; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0; + + buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00); /* set to 0x04 for continuous reporting */ + buf[1] = 0x00; + + /* if rumble is enabled, make sure we keep it */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE)) + buf[0] |= 0x01; + + motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC); + exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP); + ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR); + + if (motion && ir && exp) buf[1] = WM_RPT_BTN_ACC_IR_EXP; + else if (motion && exp) buf[1] = WM_RPT_BTN_ACC_EXP; + else if (motion && ir) buf[1] = WM_RPT_BTN_ACC_IR; + else if (ir && exp) buf[1] = WM_RPT_BTN_IR_EXP; + else if (ir) buf[1] = WM_RPT_BTN_ACC_IR; + else if (exp) buf[1] = WM_RPT_BTN_EXP; + else if (motion) buf[1] = WM_RPT_BTN_ACC; + else buf[1] = WM_RPT_BTN; + + WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]); + + exp = wiiuse_send(wm, WM_CMD_REPORT_TYPE, buf, 2); + if (exp <= 0) + return exp; + + return buf[1]; +} + + +/** + * @brief Read data from the wiimote (callback version). + * + * @param wm Pointer to a wiimote_t structure. + * @param read_cb Function pointer to call when the data arrives from the wiimote. + * @param buffer An allocated buffer to store the data as it arrives from the wiimote. + * Must be persistent in memory and large enough to hold the data. + * @param addr The address of wiimote memory to read from. + * @param len The length of the block to be read. + * + * The library can only handle one data read request at a time + * because it must keep track of the buffer and other + * events that are specific to that request. So if a request + * has already been made, subsequent requests will be added + * to a pending list and be sent out when the previous + * finishes. + */ +int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buffer, unsigned int addr, unsigned short len) { + struct read_req_t* req; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0; + if (!buffer || !len || !read_cb) + return 0; + + /* make this request structure */ + req = (struct read_req_t*)malloc(sizeof(struct read_req_t)); + req->cb = read_cb; + req->buf = buffer; + req->addr = addr; + req->size = len; + req->wait = len; + req->dirty = 0; + req->next = NULL; + + /* add this to the request list */ + if (!wm->read_req) { + /* root node */ + wm->read_req = req; + + WIIUSE_DEBUG("Data read request can be sent out immediately."); + + /* send the request out immediately */ + wiiuse_send_next_pending_read_request(wm); + } else { + struct read_req_t* nptr = wm->read_req; + for (; nptr->next; nptr = nptr->next); + nptr->next = req; + + WIIUSE_DEBUG("Added pending data read request."); + } + + return 1; +} + + +/** + * @brief Read data from the wiimote (event version). + * + * @param wm Pointer to a wiimote_t structure. + * @param buffer An allocated buffer to store the data as it arrives from the wiimote. + * Must be persistent in memory and large enough to hold the data. + * @param addr The address of wiimote memory to read from. + * @param len The length of the block to be read. + * + * The library can only handle one data read request at a time + * because it must keep track of the buffer and other + * events that are specific to that request. So if a request + * has already been made, subsequent requests will be added + * to a pending list and be sent out when the previous + * finishes. + */ +int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int addr, unsigned short len) { + struct read_req_t* req; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0; + if (!buffer || !len) + return 0; + + /* make this request structure */ + req = (struct read_req_t*)malloc(sizeof(struct read_req_t)); + req->cb = NULL; + req->buf = buffer; + req->addr = addr; + req->size = len; + req->wait = len; + req->dirty = 0; + req->next = NULL; + + /* add this to the request list */ + if (!wm->read_req) { + /* root node */ + wm->read_req = req; + + WIIUSE_DEBUG("Data read request can be sent out immediately."); + + /* send the request out immediately */ + wiiuse_send_next_pending_read_request(wm); + } else { + struct read_req_t* nptr = wm->read_req; + for (; nptr->next; nptr = nptr->next); + nptr->next = req; + + WIIUSE_DEBUG("Added pending data read request."); + } + + return 1; +} + + +/** + * @brief Send the next pending data read request to the wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * + * @see wiiuse_read_data() + * + * This function is not part of the wiiuse API. + */ +void wiiuse_send_next_pending_read_request(struct wiimote_t* wm) { + byte buf[6]; + struct read_req_t* req; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return; + if (!wm->read_req) return; + + /* skip over dirty ones since they have already been read */ + req = wm->read_req; + while (req && req->dirty) + req = req->next; + if (!req) + return; + + /* the offset is in big endian */ + *(int*)(buf) = BIG_ENDIAN_LONG(req->addr); + + /* the length is in big endian */ + *(short*)(buf + 4) = BIG_ENDIAN_SHORT(req->size); + + WIIUSE_DEBUG("Request read at address: 0x%x length: %i", req->addr, req->size); + wiiuse_send(wm, WM_CMD_READ_DATA, buf, 6); +} + + +/** + * @brief Request the wiimote controller status. + * + * @param wm Pointer to a wiimote_t structure. + * + * Controller status includes: battery level, LED status, expansions + */ +void wiiuse_status(struct wiimote_t* wm) { + byte buf = 0; + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return; + + WIIUSE_DEBUG("Requested wiimote status."); + + wiiuse_send(wm, WM_CMD_CTRL_STATUS, &buf, 1); +} + + +/** + * @brief Find a wiimote_t structure by its unique identifier. + * + * @param wm Pointer to a wiimote_t structure. + * @param wiimotes The number of wiimote_t structures in \a wm. + * @param unid The unique identifier to search for. + * + * @return Pointer to a wiimote_t structure, or NULL if not found. + */ +struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid) { + int i = 0; + + for (; i < wiimotes; ++i) { + if (wm[i]->unid == unid) + return wm[i]; + } + + return NULL; +} + + +/** + * @brief Write data to the wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * @param addr The address to write to. + * @param data The data to be written to the memory location. + * @param len The length of the block to be written. + */ +int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len) { + byte buf[21] = {0}; /* the payload is always 23 */ + + if (!wm || !WIIMOTE_IS_CONNECTED(wm)) + return 0; + if (!data || !len) + return 0; + + WIIUSE_DEBUG("Writing %i bytes to memory location 0x%x...", len, addr); + + #ifdef WITH_WIIUSE_DEBUG + { + int i = 0; + printf("Write data is: "); + for (; i < len; ++i) + printf("%x ", data[i]); + printf("\n"); + } + #endif + + /* the offset is in big endian */ + *(int*)(buf) = BIG_ENDIAN_LONG(addr); + + /* length */ + *(byte*)(buf + 4) = len; + + /* data */ + memcpy(buf + 5, data, len); + + wiiuse_send(wm, WM_CMD_WRITE_DATA, buf, 21); + return 1; +} + + +/** + * @brief Send a packet to the wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * @param report_type The report type to send (WIIMOTE_CMD_LED, WIIMOTE_CMD_RUMBLE, etc). Found in wiiuse.h + * @param msg The payload. + * @param len Length of the payload in bytes. + * + * This function should replace any write()s directly to the wiimote device. + */ +int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len) { + byte buf[32]; /* no payload is better than this */ + int rumble = 0; + + #ifndef WIN32 + buf[0] = WM_SET_REPORT | WM_BT_OUTPUT; + buf[1] = report_type; + #else + buf[0] = report_type; + #endif + + switch (report_type) { + case WM_CMD_LED: + case WM_CMD_RUMBLE: + case WM_CMD_CTRL_STATUS: + { + /* Rumble flag for: 0x11, 0x13, 0x14, 0x15, 0x19 or 0x1a */ + if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_RUMBLE)) + rumble = 1; + break; + } + default: + break; + } + + #ifndef WIN32 + memcpy(buf+2, msg, len); + if (rumble) + buf[2] |= 0x01; + #else + memcpy(buf+1, msg, len); + if (rumble) + buf[1] |= 0x01; + #endif + + #ifdef WITH_WIIUSE_DEBUG + { + int x = 2; + printf("[DEBUG] (id %i) SEND: (%x) %.2x ", wm->unid, buf[0], buf[1]); + #ifndef WIN32 + for (; x < len+2; ++x) + #else + for (; x < len+1; ++x) + #endif + printf("%.2x ", buf[x]); + printf("\n"); + } + #endif + + #ifndef WIN32 + return wiiuse_io_write(wm, buf, len+2); + #else + return wiiuse_io_write(wm, buf, len+1); + #endif +} + + +/** + * @brief Set flags for the specified wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * @param enable Flags to enable. + * @param disable Flags to disable. + * + * @return The flags set after 'enable' and 'disable' have been applied. + * + * The values 'enable' and 'disable' may be any flags OR'ed together. + * Flags are defined in wiiuse.h. + */ +int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable) { + if (!wm) return 0; + + /* remove mutually exclusive flags */ + enable &= ~disable; + disable &= ~enable; + + wm->flags |= enable; + wm->flags &= ~disable; + + return wm->flags; +} + + +/** + * @brief Set the wiimote smoothing alpha value. + * + * @param wm Pointer to a wiimote_t structure. + * @param alpha The alpha value to set. Between 0 and 1. + * + * @return Returns the old alpha value. + * + * The alpha value is between 0 and 1 and is used in an exponential + * smoothing algorithm. + * + * Smoothing is only performed if the WIIMOTE_USE_SMOOTHING is set. + */ +float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha) { + float old; + + if (!wm) return 0.0f; + + old = wm->accel_calib.st_alpha; + + wm->accel_calib.st_alpha = alpha; + + /* if there is a nunchuk set that too */ + if (wm->exp.type == EXP_NUNCHUK) + wm->exp.nunchuk.accel_calib.st_alpha = alpha; + + return old; +} + + +/** + * @brief Set the bluetooth stack type to use. + * + * @param wm Array of wiimote_t structures. + * @param wiimotes Number of objects in the wm array. + * @param type The type of bluetooth stack to use. + */ +void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type) { + #ifdef WIN32 + int i; + + if (!wm) return; + + for (i = 0; i < wiimotes; ++i) + wm[i]->stack = type; + #endif +} + + +/** + * @brief Set the orientation event threshold. + * + * @param wm Pointer to a wiimote_t structure. + * @param threshold The decimal place that should be considered a significant change. + * + * If threshold is 0.01, and any angle changes by 0.01 then a significant change + * has occured and the event callback will be invoked. If threshold is 1 then + * the angle has to change by a full degree to generate an event. + */ +void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold) { + if (!wm) return; + + wm->orient_threshold = threshold; +} + + +/** + * @brief Set the accelerometer event threshold. + * + * @param wm Pointer to a wiimote_t structure. + * @param threshold The decimal place that should be considered a significant change. + */ +void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold) { + if (!wm) return; + + wm->accel_threshold = threshold; +} + + +/** + * @brief Try to resync with the wiimote by starting a new handshake. + * + * @param wm Pointer to a wiimote_t structure. + */ +void wiiuse_resync(struct wiimote_t* wm) { + if (!wm) return; + + wm->handshake_state = 0; + wiiuse_handshake(wm, NULL, 0); +} + + +/** + * @brief Set the normal and expansion handshake timeouts. + * + * @param wm Array of wiimote_t structures. + * @param wiimotes Number of objects in the wm array. + * @param normal_timeout The timeout in milliseconds for a normal read. + * @param exp_timeout The timeout in millisecondsd to wait for an expansion handshake. + */ +void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout) { + #ifdef WIN32 + int i; + + if (!wm) return; + + for (i = 0; i < wiimotes; ++i) { + wm[i]->normal_timeout = normal_timeout; + wm[i]->exp_timeout = exp_timeout; + } + #endif +} diff --git a/Externals/WiiUseSrc/Src/wiiuse.h b/Externals/WiiUseSrc/Src/wiiuse.h new file mode 100644 index 0000000000..a70dc9e344 --- /dev/null +++ b/Externals/WiiUseSrc/Src/wiiuse.h @@ -0,0 +1,657 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * + * @brief API header file. + * + * If this file is included from inside the wiiuse source + * and not from a third party program, then wiimote_internal.h + * is also included which extends this file. + */ + +#ifndef WIIUSE_H_INCLUDED +#define WIIUSE_H_INCLUDED + +#ifdef _WIN32 + /* windows */ + #include +#else + /* nix */ + #include +#endif + +#ifdef WIIUSE_INTERNAL_H_INCLUDED + #define WCONST +#else + #define WCONST const +#endif + +/* led bit masks */ +#define WIIMOTE_LED_NONE 0x00 +#define WIIMOTE_LED_1 0x10 +#define WIIMOTE_LED_2 0x20 +#define WIIMOTE_LED_3 0x40 +#define WIIMOTE_LED_4 0x80 + +/* button codes */ +#define WIIMOTE_BUTTON_TWO 0x0001 +#define WIIMOTE_BUTTON_ONE 0x0002 +#define WIIMOTE_BUTTON_B 0x0004 +#define WIIMOTE_BUTTON_A 0x0008 +#define WIIMOTE_BUTTON_MINUS 0x0010 +#define WIIMOTE_BUTTON_ZACCEL_BIT6 0x0020 +#define WIIMOTE_BUTTON_ZACCEL_BIT7 0x0040 +#define WIIMOTE_BUTTON_HOME 0x0080 +#define WIIMOTE_BUTTON_LEFT 0x0100 +#define WIIMOTE_BUTTON_RIGHT 0x0200 +#define WIIMOTE_BUTTON_DOWN 0x0400 +#define WIIMOTE_BUTTON_UP 0x0800 +#define WIIMOTE_BUTTON_PLUS 0x1000 +#define WIIMOTE_BUTTON_ZACCEL_BIT4 0x2000 +#define WIIMOTE_BUTTON_ZACCEL_BIT5 0x4000 +#define WIIMOTE_BUTTON_UNKNOWN 0x8000 +#define WIIMOTE_BUTTON_ALL 0x1F9F + +/* nunchul button codes */ +#define NUNCHUK_BUTTON_Z 0x01 +#define NUNCHUK_BUTTON_C 0x02 +#define NUNCHUK_BUTTON_ALL 0x03 + +/* classic controller button codes */ +#define CLASSIC_CTRL_BUTTON_UP 0x0001 +#define CLASSIC_CTRL_BUTTON_LEFT 0x0002 +#define CLASSIC_CTRL_BUTTON_ZR 0x0004 +#define CLASSIC_CTRL_BUTTON_X 0x0008 +#define CLASSIC_CTRL_BUTTON_A 0x0010 +#define CLASSIC_CTRL_BUTTON_Y 0x0020 +#define CLASSIC_CTRL_BUTTON_B 0x0040 +#define CLASSIC_CTRL_BUTTON_ZL 0x0080 +#define CLASSIC_CTRL_BUTTON_FULL_R 0x0200 +#define CLASSIC_CTRL_BUTTON_PLUS 0x0400 +#define CLASSIC_CTRL_BUTTON_HOME 0x0800 +#define CLASSIC_CTRL_BUTTON_MINUS 0x1000 +#define CLASSIC_CTRL_BUTTON_FULL_L 0x2000 +#define CLASSIC_CTRL_BUTTON_DOWN 0x4000 +#define CLASSIC_CTRL_BUTTON_RIGHT 0x8000 +#define CLASSIC_CTRL_BUTTON_ALL 0xFEFF + +/* guitar hero 3 button codes */ +#define GUITAR_HERO_3_BUTTON_STRUM_UP 0x0001 +#define GUITAR_HERO_3_BUTTON_YELLOW 0x0008 +#define GUITAR_HERO_3_BUTTON_GREEN 0x0010 +#define GUITAR_HERO_3_BUTTON_BLUE 0x0020 +#define GUITAR_HERO_3_BUTTON_RED 0x0040 +#define GUITAR_HERO_3_BUTTON_ORANGE 0x0080 +#define GUITAR_HERO_3_BUTTON_PLUS 0x0400 +#define GUITAR_HERO_3_BUTTON_MINUS 0x1000 +#define GUITAR_HERO_3_BUTTON_STRUM_DOWN 0x4000 +#define GUITAR_HERO_3_BUTTON_ALL 0xFEFF + + +/* wiimote option flags */ +#define WIIUSE_SMOOTHING 0x01 +#define WIIUSE_CONTINUOUS 0x02 +#define WIIUSE_ORIENT_THRESH 0x04 +#define WIIUSE_INIT_FLAGS (WIIUSE_SMOOTHING | WIIUSE_ORIENT_THRESH) + +#define WIIUSE_ORIENT_PRECISION 100.0f + +/* expansion codes */ +#define EXP_NONE 0 +#define EXP_NUNCHUK 1 +#define EXP_CLASSIC 2 +#define EXP_GUITAR_HERO_3 3 + +/* IR correction types */ +typedef enum ir_position_t { + WIIUSE_IR_ABOVE, + WIIUSE_IR_BELOW +} ir_position_t; + +/** + * @brief Check if a button is pressed. + * @param dev Pointer to a wiimote_t or expansion structure. + * @param button The button you are interested in. + * @return 1 if the button is pressed, 0 if not. + */ +#define IS_PRESSED(dev, button) ((dev->btns & button) == button) + +/** + * @brief Check if a button is being held. + * @param dev Pointer to a wiimote_t or expansion structure. + * @param button The button you are interested in. + * @return 1 if the button is held, 0 if not. + */ +#define IS_HELD(dev, button) ((dev->btns_held & button) == button) + +/** + * @brief Check if a button is released on this event. \n\n + * This does not mean the button is not pressed, it means \n + * this button was just now released. + * @param dev Pointer to a wiimote_t or expansion structure. + * @param button The button you are interested in. + * @return 1 if the button is released, 0 if not. + * + */ +#define IS_RELEASED(dev, button) ((dev->btns_released & button) == button) + +/** + * @brief Check if a button has just been pressed this event. + * @param dev Pointer to a wiimote_t or expansion structure. + * @param button The button you are interested in. + * @return 1 if the button is pressed, 0 if not. + */ +#define IS_JUST_PRESSED(dev, button) (IS_PRESSED(dev, button) && !IS_HELD(dev, button)) + +/** + * @brief Return the IR sensitivity level. + * @param wm Pointer to a wiimote_t structure. + * @param lvl [out] Pointer to an int that will hold the level setting. + * If no level is set 'lvl' will be set to 0. + */ +#define WIIUSE_GET_IR_SENSITIVITY(dev, lvl) \ + do { \ + if ((wm->state & 0x0200) == 0x0200) *lvl = 1; \ + else if ((wm->state & 0x0400) == 0x0400) *lvl = 2; \ + else if ((wm->state & 0x0800) == 0x0800) *lvl = 3; \ + else if ((wm->state & 0x1000) == 0x1000) *lvl = 4; \ + else if ((wm->state & 0x2000) == 0x2000) *lvl = 5; \ + else *lvl = 0; \ + } while (0) + +#define WIIUSE_USING_ACC(wm) ((wm->state & 0x020) == 0x020) +#define WIIUSE_USING_EXP(wm) ((wm->state & 0x040) == 0x040) +#define WIIUSE_USING_IR(wm) ((wm->state & 0x080) == 0x080) +#define WIIUSE_USING_SPEAKER(wm) ((wm->state & 0x100) == 0x100) + +#define WIIUSE_IS_LED_SET(wm, num) ((wm->leds & WIIMOTE_LED_##num) == WIIMOTE_LED_##num) + +/* + * Largest known payload is 21 bytes. + * Add 2 for the prefix and round up to a power of 2. + */ +#define MAX_PAYLOAD 32 + +/* + * This is left over from an old hack, but it may actually + * be a useful feature to keep so it wasn't removed. + */ +#ifdef WIN32 + #define WIIMOTE_DEFAULT_TIMEOUT 10 + #define WIIMOTE_EXP_TIMEOUT 10 +#endif + +typedef unsigned char byte; +typedef char sbyte; + +struct wiimote_t; +struct vec3b_t; +struct orient_t; +struct gforce_t; + + +/** + * @brief Callback that handles a read event. + * + * @param wm Pointer to a wiimote_t structure. + * @param data Pointer to the filled data block. + * @param len Length in bytes of the data block. + * + * @see wiiuse_init() + * + * A registered function of this type is called automatically by the wiiuse + * library when the wiimote has returned the full data requested by a previous + * call to wiiuse_read_data(). + */ +typedef void (*wiiuse_read_cb)(struct wiimote_t* wm, byte* data, unsigned short len); + + +/** + * @struct read_req_t + * @brief Data read request structure. + */ +struct read_req_t { + wiiuse_read_cb cb; /**< read data callback */ + byte* buf; /**< buffer where read data is written */ + unsigned int addr; /**< the offset that the read started at */ + unsigned short size; /**< the length of the data read */ + unsigned short wait; /**< num bytes still needed to finish read */ + byte dirty; /**< set to 1 if not using callback and needs to be cleaned up */ + + struct read_req_t* next; /**< next read request in the queue */ +}; + + +/** + * @struct vec2b_t + * @brief Unsigned x,y byte vector. + */ +typedef struct vec2b_t { + byte x, y; +} vec2b_t; + + +/** + * @struct vec3b_t + * @brief Unsigned x,y,z byte vector. + */ +typedef struct vec3b_t { + byte x, y, z; +} vec3b_t; + + +/** + * @struct vec3f_t + * @brief Signed x,y,z float struct. + */ +typedef struct vec3f_t { + float x, y, z; +} vec3f_t; + + +/** + * @struct orient_t + * @brief Orientation struct. + * + * Yaw, pitch, and roll range from -180 to 180 degrees. + */ +typedef struct orient_t { + float roll; /**< roll, this may be smoothed if enabled */ + float pitch; /**< pitch, this may be smoothed if enabled */ + float yaw; + + float a_roll; /**< absolute roll, unsmoothed */ + float a_pitch; /**< absolute pitch, unsmoothed */ +} orient_t; + + +/** + * @struct gforce_t + * @brief Gravity force struct. + */ +typedef struct gforce_t { + float x, y, z; +} gforce_t; + + +/** + * @struct accel_t + * @brief Accelerometer struct. For any device with an accelerometer. + */ +typedef struct accel_t { + struct vec3b_t cal_zero; /**< zero calibration */ + struct vec3b_t cal_g; /**< 1g difference around 0cal */ + + float st_roll; /**< last smoothed roll value */ + float st_pitch; /**< last smoothed roll pitch */ + float st_alpha; /**< alpha value for smoothing [0-1] */ +} accel_t; + + +/** + * @struct ir_dot_t + * @brief A single IR source. + */ +typedef struct ir_dot_t { + byte visible; /**< if the IR source is visible */ + + unsigned int x; /**< interpolated X coordinate */ + unsigned int y; /**< interpolated Y coordinate */ + + short rx; /**< raw X coordinate (0-1023) */ + short ry; /**< raw Y coordinate (0-767) */ + + byte order; /**< increasing order by x-axis value */ + + byte size; /**< size of the IR dot (0-15) */ +} ir_dot_t; + + +/** + * @enum aspect_t + * @brief Screen aspect ratio. + */ +typedef enum aspect_t { + WIIUSE_ASPECT_4_3, + WIIUSE_ASPECT_16_9 +} aspect_t; + + +/** + * @struct ir_t + * @brief IR struct. Hold all data related to the IR tracking. + */ +typedef struct ir_t { + struct ir_dot_t dot[4]; /**< IR dots */ + byte num_dots; /**< number of dots at this time */ + + enum aspect_t aspect; /**< aspect ratio of the screen */ + + enum ir_position_t pos; /**< IR sensor bar position */ + + unsigned int vres[2]; /**< IR virtual screen resolution */ + int offset[2]; /**< IR XY correction offset */ + int state; /**< keeps track of the IR state */ + + int ax; /**< absolute X coordinate */ + int ay; /**< absolute Y coordinate */ + + int x; /**< calculated X coordinate */ + int y; /**< calculated Y coordinate */ + + float distance; /**< pixel distance between first 2 dots*/ + float z; /**< calculated distance */ +} ir_t; + + +/** + * @struct joystick_t + * @brief Joystick calibration structure. + * + * The angle \a ang is relative to the positive y-axis into quadrant I + * and ranges from 0 to 360 degrees. So if the joystick is held straight + * upwards then angle is 0 degrees. If it is held to the right it is 90, + * down is 180, and left is 270. + * + * The magnitude \a mag is the distance from the center to where the + * joystick is being held. The magnitude ranges from 0 to 1. + * If the joystick is only slightly tilted from the center the magnitude + * will be low, but if it is closer to the outter edge the value will + * be higher. + */ +typedef struct joystick_t { + struct vec2b_t max; /**< maximum joystick values */ + struct vec2b_t min; /**< minimum joystick values */ + struct vec2b_t center; /**< center joystick values */ + + float ang; /**< angle the joystick is being held */ + float mag; /**< magnitude of the joystick (range 0-1) */ +} joystick_t; + + +/** + * @struct nunchuk_t + * @brief Nunchuk expansion device. + */ +typedef struct nunchuk_t { + struct accel_t accel_calib; /**< nunchuk accelerometer calibration */ + struct joystick_t js; /**< joystick calibration */ + + int* flags; /**< options flag (points to wiimote_t.flags) */ + + byte btns; /**< what buttons have just been pressed */ + byte btns_held; /**< what buttons are being held down */ + byte btns_released; /**< what buttons were just released this */ + + float orient_threshold; /**< threshold for orient to generate an event */ + int accel_threshold; /**< threshold for accel to generate an event */ + + struct vec3b_t accel; /**< current raw acceleration data */ + struct orient_t orient; /**< current orientation on each axis */ + struct gforce_t gforce; /**< current gravity forces on each axis */ +} nunchuk_t; + + +/** + * @struct classic_ctrl_t + * @brief Classic controller expansion device. + */ +typedef struct classic_ctrl_t { + short btns; /**< what buttons have just been pressed */ + short btns_held; /**< what buttons are being held down */ + short btns_released; /**< what buttons were just released this */ + + float r_shoulder; /**< right shoulder button (range 0-1) */ + float l_shoulder; /**< left shoulder button (range 0-1) */ + + struct joystick_t ljs; /**< left joystick calibration */ + struct joystick_t rjs; /**< right joystick calibration */ +} classic_ctrl_t; + + +/** + * @struct guitar_hero_3_t + * @brief Guitar Hero 3 expansion device. + */ +typedef struct guitar_hero_3_t { + short btns; /**< what buttons have just been pressed */ + short btns_held; /**< what buttons are being held down */ + short btns_released; /**< what buttons were just released this */ + + float whammy_bar; /**< whammy bar (range 0-1) */ + + struct joystick_t js; /**< joystick calibration */ +} guitar_hero_3_t; + + +/** + * @struct expansion_t + * @brief Generic expansion device plugged into wiimote. + */ +typedef struct expansion_t { + int type; /**< type of expansion attached */ + + union { + struct nunchuk_t nunchuk; + struct classic_ctrl_t classic; + struct guitar_hero_3_t gh3; + }; +} expansion_t; + + +/** + * @enum win32_bt_stack_t + * @brief Available bluetooth stacks for Windows. + */ +typedef enum win_bt_stack_t { + WIIUSE_STACK_UNKNOWN, + WIIUSE_STACK_MS, + WIIUSE_STACK_BLUESOLEIL +} win_bt_stack_t; + + +/** + * @struct wiimote_state_t + * @brief Significant data from the previous event. + */ +typedef struct wiimote_state_t { + /* expansion_t */ + float exp_ljs_ang; + float exp_rjs_ang; + float exp_ljs_mag; + float exp_rjs_mag; + unsigned short exp_btns; + struct orient_t exp_orient; + struct vec3b_t exp_accel; + float exp_r_shoulder; + float exp_l_shoulder; + + /* ir_t */ + int ir_ax; + int ir_ay; + float ir_distance; + + struct orient_t orient; + unsigned short btns; + + struct vec3b_t accel; +} wiimote_state_t; + + +/** + * @enum WIIUSE_EVENT_TYPE + * @brief Events that wiiuse can generate from a poll. + */ +typedef enum WIIUSE_EVENT_TYPE { + WIIUSE_NONE = 0, + WIIUSE_EVENT, + WIIUSE_STATUS, + WIIUSE_CONNECT, + WIIUSE_DISCONNECT, + WIIUSE_UNEXPECTED_DISCONNECT, + WIIUSE_READ_DATA, + WIIUSE_NUNCHUK_INSERTED, + WIIUSE_NUNCHUK_REMOVED, + WIIUSE_CLASSIC_CTRL_INSERTED, + WIIUSE_CLASSIC_CTRL_REMOVED, + WIIUSE_GUITAR_HERO_3_CTRL_INSERTED, + WIIUSE_GUITAR_HERO_3_CTRL_REMOVED +} WIIUSE_EVENT_TYPE; + +/** + * @struct wiimote_t + * @brief Wiimote structure. + */ +typedef struct wiimote_t { + WCONST int unid; /**< user specified id */ + + #ifndef WIN32 + WCONST bdaddr_t bdaddr; /**< bt address */ + WCONST char bdaddr_str[18]; /**< readable bt address */ + WCONST int out_sock; /**< output socket */ + WCONST int in_sock; /**< input socket */ + #else + WCONST HANDLE dev_handle; /**< HID handle */ + WCONST OVERLAPPED hid_overlap; /**< overlap handle */ + WCONST enum win_bt_stack_t stack; /**< type of bluetooth stack to use */ + WCONST int timeout; /**< read timeout */ + WCONST byte normal_timeout; /**< normal timeout */ + WCONST byte exp_timeout; /**< timeout for expansion handshake */ + #endif + + WCONST int state; /**< various state flags */ + WCONST byte leds; /**< currently lit leds */ + WCONST float battery_level; /**< battery level */ + + WCONST int flags; /**< options flag */ + + WCONST byte handshake_state; /**< the state of the connection handshake */ + + WCONST struct read_req_t* read_req; /**< list of data read requests */ + WCONST struct accel_t accel_calib; /**< wiimote accelerometer calibration */ + WCONST struct expansion_t exp; /**< wiimote expansion device */ + + WCONST struct vec3b_t accel; /**< current raw acceleration data */ + WCONST struct orient_t orient; /**< current orientation on each axis */ + WCONST struct gforce_t gforce; /**< current gravity forces on each axis */ + + WCONST struct ir_t ir; /**< IR data */ + + WCONST unsigned short btns; /**< what buttons have just been pressed */ + WCONST unsigned short btns_held; /**< what buttons are being held down */ + WCONST unsigned short btns_released; /**< what buttons were just released this */ + + WCONST float orient_threshold; /**< threshold for orient to generate an event */ + WCONST int accel_threshold; /**< threshold for accel to generate an event */ + + WCONST struct wiimote_state_t lstate; /**< last saved state */ + + WCONST WIIUSE_EVENT_TYPE event; /**< type of event that occured */ + WCONST byte event_buf[MAX_PAYLOAD]; /**< event buffer */ +} wiimote; + + +/***************************************** + * + * Include API specific stuff + * + *****************************************/ + +#ifdef _WIN32 + #define WIIUSE_EXPORT_DECL __declspec(dllexport) + #define WIIUSE_IMPORT_DECL __declspec(dllimport) +#else + #define WIIUSE_EXPORT_DECL + #define WIIUSE_IMPORT_DECL +#endif + +#ifdef WIIUSE_COMPILE_LIB + #define WIIUSE_EXPORT WIIUSE_EXPORT_DECL +#else + #define WIIUSE_EXPORT WIIUSE_IMPORT_DECL +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* wiiuse.c */ +WIIUSE_EXPORT extern const char* wiiuse_version(); + +WIIUSE_EXPORT extern struct wiimote_t** wiiuse_init(int wiimotes); +WIIUSE_EXPORT extern void wiiuse_disconnected(struct wiimote_t* wm); +WIIUSE_EXPORT extern void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes); +WIIUSE_EXPORT extern void wiiuse_rumble(struct wiimote_t* wm, int status); +WIIUSE_EXPORT extern void wiiuse_toggle_rumble(struct wiimote_t* wm); +WIIUSE_EXPORT extern void wiiuse_set_leds(struct wiimote_t* wm, int leds); +WIIUSE_EXPORT extern void wiiuse_motion_sensing(struct wiimote_t* wm, int status); +WIIUSE_EXPORT extern int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int offset, unsigned short len); +WIIUSE_EXPORT extern int wiiuse_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len); +WIIUSE_EXPORT extern void wiiuse_status(struct wiimote_t* wm); +WIIUSE_EXPORT extern struct wiimote_t* wiiuse_get_by_id(struct wiimote_t** wm, int wiimotes, int unid); +WIIUSE_EXPORT extern int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable); +WIIUSE_EXPORT extern float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float alpha); +WIIUSE_EXPORT extern void wiiuse_set_bluetooth_stack(struct wiimote_t** wm, int wiimotes, enum win_bt_stack_t type); +WIIUSE_EXPORT extern void wiiuse_set_orient_threshold(struct wiimote_t* wm, float threshold); +WIIUSE_EXPORT extern void wiiuse_resync(struct wiimote_t* wm); +WIIUSE_EXPORT extern void wiiuse_set_timeout(struct wiimote_t** wm, int wiimotes, byte normal_timeout, byte exp_timeout); +WIIUSE_EXPORT extern void wiiuse_set_accel_threshold(struct wiimote_t* wm, int threshold); + +/* connect.c */ +WIIUSE_EXPORT extern int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout); +WIIUSE_EXPORT extern int wiiuse_connect(struct wiimote_t** wm, int wiimotes); +WIIUSE_EXPORT extern void wiiuse_disconnect(struct wiimote_t* wm); + +/* events.c */ +WIIUSE_EXPORT extern int wiiuse_poll(struct wiimote_t** wm, int wiimotes); + +/* ir.c */ +WIIUSE_EXPORT extern void wiiuse_set_ir(struct wiimote_t* wm, int status); +WIIUSE_EXPORT extern void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y); +WIIUSE_EXPORT extern void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos); +WIIUSE_EXPORT extern void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect); +WIIUSE_EXPORT extern void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level); + +/* nunchuk.c */ +WIIUSE_EXPORT extern void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold); +WIIUSE_EXPORT extern void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold); + +/* io.c */ +WIIUSE_EXPORT extern int wiiuse_io_read(struct wiimote_t* wm); +WIIUSE_EXPORT extern int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len); + + +#ifdef __cplusplus +} +#endif + + +#endif /* WIIUSE_H_INCLUDED */ + diff --git a/Externals/WiiUseSrc/Src/wiiuse_internal.h b/Externals/WiiUseSrc/Src/wiiuse_internal.h new file mode 100644 index 0000000000..1b2f423862 --- /dev/null +++ b/Externals/WiiUseSrc/Src/wiiuse_internal.h @@ -0,0 +1,226 @@ +/* + * 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 . + * + * $Header$ + * + */ + +/** + * @file + * @brief General internal wiiuse stuff. + * + * Since Wiiuse is a library, wiiuse.h is a duplicate + * of the API header. + * + * The code that would normally go in that file, but + * which is not needed by third party developers, + * is put here. + * + * So wiiuse_internal.h is included by other files + * internally, wiiuse.h is included only here. + */ + +#ifndef WIIUSE_INTERNAL_H_INCLUDED +#define WIIUSE_INTERNAL_H_INCLUDED + +#ifndef WIN32 + #include /* htons() */ + #include +#endif + +#include "definitions.h" + +/* wiiuse version */ +#define WIIUSE_VERSION "0.12" + +/******************** + * + * Wiimote internal codes + * + ********************/ + +/* Communication channels */ +#define WM_OUTPUT_CHANNEL 0x11 +#define WM_INPUT_CHANNEL 0x13 + +#define WM_SET_REPORT 0x50 + +/* commands */ +#define WM_CMD_LED 0x11 +#define WM_CMD_REPORT_TYPE 0x12 +#define WM_CMD_RUMBLE 0x13 +#define WM_CMD_IR 0x13 +#define WM_CMD_CTRL_STATUS 0x15 +#define WM_CMD_WRITE_DATA 0x16 +#define WM_CMD_READ_DATA 0x17 +#define WM_CMD_IR_2 0x1A + +/* input report ids */ +#define WM_RPT_CTRL_STATUS 0x20 +#define WM_RPT_READ 0x21 +#define WM_RPT_WRITE 0x22 +#define WM_RPT_BTN 0x30 +#define WM_RPT_BTN_ACC 0x31 +#define WM_RPT_BTN_ACC_IR 0x33 +#define WM_RPT_BTN_EXP 0x34 +#define WM_RPT_BTN_ACC_EXP 0x35 +#define WM_RPT_BTN_IR_EXP 0x36 +#define WM_RPT_BTN_ACC_IR_EXP 0x37 + +#define WM_BT_INPUT 0x01 +#define WM_BT_OUTPUT 0x02 + +/* Identify the wiimote device by its class */ +#define WM_DEV_CLASS_0 0x04 +#define WM_DEV_CLASS_1 0x25 +#define WM_DEV_CLASS_2 0x00 +#define WM_VENDOR_ID 0x057E +#define WM_PRODUCT_ID 0x0306 + +/* controller status stuff */ +#define WM_MAX_BATTERY_CODE 0xC8 + +/* offsets in wiimote memory */ +#define WM_MEM_OFFSET_CALIBRATION 0x16 +#define WM_EXP_MEM_BASE 0x04A40000 +#define WM_EXP_MEM_ENABLE 0x04A40040 +#define WM_EXP_MEM_CALIBR 0x04A40020 + +#define WM_REG_IR 0x04B00030 +#define WM_REG_IR_BLOCK1 0x04B00000 +#define WM_REG_IR_BLOCK2 0x04B0001A +#define WM_REG_IR_MODENUM 0x04B00033 + +/* ir block data */ +#define WM_IR_BLOCK1_LEVEL1 "\x02\x00\x00\x71\x01\x00\x64\x00\xfe" +#define WM_IR_BLOCK2_LEVEL1 "\xfd\x05" +#define WM_IR_BLOCK1_LEVEL2 "\x02\x00\x00\x71\x01\x00\x96\x00\xb4" +#define WM_IR_BLOCK2_LEVEL2 "\xb3\x04" +#define WM_IR_BLOCK1_LEVEL3 "\x02\x00\x00\x71\x01\x00\xaa\x00\x64" +#define WM_IR_BLOCK2_LEVEL3 "\x63\x03" +#define WM_IR_BLOCK1_LEVEL4 "\x02\x00\x00\x71\x01\x00\xc8\x00\x36" +#define WM_IR_BLOCK2_LEVEL4 "\x35\x03" +#define WM_IR_BLOCK1_LEVEL5 "\x07\x00\x00\x71\x01\x00\x72\x00\x20" +#define WM_IR_BLOCK2_LEVEL5 "\x1f\x03" + +#define WM_IR_TYPE_BASIC 0x01 +#define WM_IR_TYPE_EXTENDED 0x03 + +/* controller status flags for the first message byte */ +/* bit 1 is unknown */ +#define WM_CTRL_STATUS_BYTE1_ATTACHMENT 0x02 +#define WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED 0x04 +#define WM_CTRL_STATUS_BYTE1_IR_ENABLED 0x08 +#define WM_CTRL_STATUS_BYTE1_LED_1 0x10 +#define WM_CTRL_STATUS_BYTE1_LED_2 0x20 +#define WM_CTRL_STATUS_BYTE1_LED_3 0x40 +#define WM_CTRL_STATUS_BYTE1_LED_4 0x80 + +/* aspect ratio */ +#define WM_ASPECT_16_9_X 660 +#define WM_ASPECT_16_9_Y 370 +#define WM_ASPECT_4_3_X 560 +#define WM_ASPECT_4_3_Y 420 + + +/** + * Expansion stuff + */ + +/* encrypted expansion id codes (located at 0x04A400FC) */ +#define EXP_ID_CODE_NUNCHUK 0x9A1EFEFE +#define EXP_ID_CODE_CLASSIC_CONTROLLER 0x9A1EFDFD +#define EXP_ID_CODE_GUITAR 0x9A1EFDFB + +#define EXP_HANDSHAKE_LEN 224 + +/******************** + * + * End Wiimote internal codes + * + ********************/ + +/* wiimote state flags - (some duplicated in wiiuse.h)*/ +#define WIIMOTE_STATE_DEV_FOUND 0x0001 +#define WIIMOTE_STATE_HANDSHAKE 0x0002 /* actual connection exists but no handshake yet */ +#define WIIMOTE_STATE_HANDSHAKE_COMPLETE 0x0004 /* actual connection exists but no handshake yet */ +#define WIIMOTE_STATE_CONNECTED 0x0008 +#define WIIMOTE_STATE_RUMBLE 0x0010 +#define WIIMOTE_STATE_ACC 0x0020 +#define WIIMOTE_STATE_EXP 0x0040 +#define WIIMOTE_STATE_IR 0x0080 +#define WIIMOTE_STATE_SPEAKER 0x0100 +#define WIIMOTE_STATE_IR_SENS_LVL1 0x0200 +#define WIIMOTE_STATE_IR_SENS_LVL2 0x0400 +#define WIIMOTE_STATE_IR_SENS_LVL3 0x0800 +#define WIIMOTE_STATE_IR_SENS_LVL4 0x1000 +#define WIIMOTE_STATE_IR_SENS_LVL5 0x2000 + +#define WIIMOTE_INIT_STATES (WIIMOTE_STATE_IR_SENS_LVL3) + +/* macro to manage states */ +#define WIIMOTE_IS_SET(wm, s) ((wm->state & (s)) == (s)) +#define WIIMOTE_ENABLE_STATE(wm, s) (wm->state |= (s)) +#define WIIMOTE_DISABLE_STATE(wm, s) (wm->state &= ~(s)) +#define WIIMOTE_TOGGLE_STATE(wm, s) ((wm->state & (s)) ? WIIMOTE_DISABLE_STATE(wm, s) : WIIMOTE_ENABLE_STATE(wm, s)) + +#define WIIMOTE_IS_FLAG_SET(wm, s) ((wm->flags & (s)) == (s)) +#define WIIMOTE_ENABLE_FLAG(wm, s) (wm->flags |= (s)) +#define WIIMOTE_DISABLE_FLAG(wm, s) (wm->flags &= ~(s)) +#define WIIMOTE_TOGGLE_FLAG(wm, s) ((wm->flags & (s)) ? WIIMOTE_DISABLE_FLAG(wm, s) : WIIMOTE_ENABLE_FLAG(wm, s)) + +#define NUNCHUK_IS_FLAG_SET(wm, s) ((*(wm->flags) & (s)) == (s)) + +/* misc macros */ +#define WIIMOTE_ID(wm) (wm->unid) +#define WIIMOTE_IS_CONNECTED(wm) (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED)) + +/* + * Smooth tilt calculations are computed with the + * exponential moving average formula: + * St = St_last + (alpha * (tilt - St_last)) + * alpha is between 0 and 1 + */ +#define WIIUSE_DEFAULT_SMOOTH_ALPHA 0.07f + +#define SMOOTH_ROLL 0x01 +#define SMOOTH_PITCH 0x02 + +#include "wiiuse.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* not part of the api */ +int wiiuse_set_report_type(struct wiimote_t* wm); +void wiiuse_send_next_pending_read_request(struct wiimote_t* wm); +int wiiuse_send(struct wiimote_t* wm, byte report_type, byte* msg, int len); +int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buffer, unsigned int offset, unsigned short len); + +#ifdef __cplusplus +} +#endif + +#endif /* WIIUSE_INTERNAL_H_INCLUDED */ diff --git a/Externals/WiiUseSrc/wiiuse.sln b/Externals/WiiUseSrc/wiiuse.sln new file mode 100644 index 0000000000..beece4e143 --- /dev/null +++ b/Externals/WiiUseSrc/wiiuse.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wiiuse", "wiiuse.vcproj", "{944EF6DE-471D-447E-A2FD-D37D58805169}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {944EF6DE-471D-447E-A2FD-D37D58805169}.Debug|Win32.ActiveCfg = Debug|Win32 + {944EF6DE-471D-447E-A2FD-D37D58805169}.Debug|Win32.Build.0 = Debug|Win32 + {944EF6DE-471D-447E-A2FD-D37D58805169}.Debug|x64.ActiveCfg = Debug|x64 + {944EF6DE-471D-447E-A2FD-D37D58805169}.Debug|x64.Build.0 = Debug|x64 + {944EF6DE-471D-447E-A2FD-D37D58805169}.Release|Win32.ActiveCfg = Release|Win32 + {944EF6DE-471D-447E-A2FD-D37D58805169}.Release|Win32.Build.0 = Release|Win32 + {944EF6DE-471D-447E-A2FD-D37D58805169}.Release|x64.ActiveCfg = Release|x64 + {944EF6DE-471D-447E-A2FD-D37D58805169}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Externals/WiiUseSrc/wiiuse.suo b/Externals/WiiUseSrc/wiiuse.suo new file mode 100644 index 0000000000000000000000000000000000000000..3dfa0ede367a79e83c3a920cbf205a15e9c3fcd3 GIT binary patch literal 32768 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 TnG0H%LF|5Jkor+fUI+jHZL`d? literal 0 HcmV?d00001 diff --git a/Externals/WiiUseSrc/wiiuse.vcproj b/Externals/WiiUseSrc/wiiuse.vcproj new file mode 100644 index 0000000000..b18604f18a --- /dev/null +++ b/Externals/WiiUseSrc/wiiuse.vcproj @@ -0,0 +1,508 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +