From dde5bb965a996e3c3a4d138bb4bb76f13953051b Mon Sep 17 00:00:00 2001 From: Ryan Pavlik Date: Thu, 22 Jul 2010 18:42:04 -0500 Subject: [PATCH] Improve balance board, use stdint.h --- src/events.c | 27 +- src/events.h | 3 +- src/io.c | 2 +- src/io.h | 2 +- src/wiiboard.c | 94 +-- src/wiiboard.h | 4 +- src/wiiuse.c | 1408 ++++++++++++++++++++--------------------- src/wiiuse.h | 75 ++- src/wiiuse_internal.h | 4 +- 9 files changed, 804 insertions(+), 815 deletions(-) diff --git a/src/events.c b/src/events.c index 612891a..4c2380c 100644 --- a/src/events.c +++ b/src/events.c @@ -389,10 +389,10 @@ static void propagate_event(struct wiimote_t* wm, byte event, byte* msg) { * @param msg The message specified in the event packet. */ void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg) { - short now; + int16_t now; /* convert to big endian */ - now = BIG_ENDIAN_SHORT(*(short*)msg) & WIIMOTE_BUTTON_ALL; + now = BIG_ENDIAN_SHORT(*(int16_t*)msg) & WIIMOTE_BUTTON_ALL; /* pressed now & were pressed, then held */ wm->btns_held = (now & wm->btns); @@ -421,7 +421,7 @@ 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; + uint16_t offset; struct read_req_t* req = wm->read_req; wiiuse_pressed_buttons(wm, msg); @@ -460,7 +460,7 @@ static void event_data_read(struct wiimote_t* wm, byte* msg) { } len = ((msg[2] & 0xF0) >> 4) + 1; - offset = BIG_ENDIAN_SHORT(*(unsigned short*)(msg + 3)); + offset = BIG_ENDIAN_SHORT(*(uint16_t*)(msg + 3)); req->addr = (req->addr & 0xFFFF); req->wait -= len; @@ -634,7 +634,7 @@ static void handle_expansion(struct wiimote_t* wm, byte* msg) { * If the data is NULL then this function will try to start * a handshake with the expansion. */ -void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len) { +void handshake_expansion(struct wiimote_t* wm, byte* data, uint16_t len) { int id; if (!data) { @@ -731,7 +731,7 @@ void disable_expansion(struct wiimote_t* wm) { wm->event = WIIUSE_GUITAR_HERO_3_CTRL_REMOVED; break; case EXP_WII_BOARD: - guitar_hero_3_disconnected(&wm->exp.gh3); + wii_board_disconnected(&wm->exp.wb); wm->event = WIIUSE_WII_BOARD_CTRL_REMOVED; break; default: @@ -785,6 +785,13 @@ static void save_state(struct wiimote_t* wm) { wm->lstate.exp_btns = wm->exp.gh3.btns; break; + case EXP_WII_BOARD: + wm->lstate.exp_wb_rtr = wm->exp.wb.rtr; + wm->lstate.exp_wb_rtl = wm->exp.wb.rtl; + wm->lstate.exp_wb_rbr = wm->exp.wb.rbr; + wm->lstate.exp_wb_rbl = wm->exp.wb.rbl; + break; + case EXP_NONE: break; } @@ -882,10 +889,10 @@ static int state_changed(struct wiimote_t* wm) { } case EXP_WII_BOARD: { - STATE_CHANGED(wm->exp.wb.ltr,wm->exp.wb.tr); - STATE_CHANGED(wm->exp.wb.ltl,wm->exp.wb.tl); - STATE_CHANGED(wm->exp.wb.lbr,wm->exp.wb.br); - STATE_CHANGED(wm->exp.wb.lbl,wm->exp.wb.bl); + STATE_CHANGED(wm->lstate.exp_wb_rtr,wm->exp.wb.tr); + STATE_CHANGED(wm->lstate.exp_wb_rtl,wm->exp.wb.tl); + STATE_CHANGED(wm->lstate.exp_wb_rbr,wm->exp.wb.br); + STATE_CHANGED(wm->lstate.exp_wb_rbl,wm->exp.wb.bl); break; } case EXP_NONE: diff --git a/src/events.h b/src/events.h index 5e9b955..e720a34 100644 --- a/src/events.h +++ b/src/events.h @@ -40,10 +40,11 @@ #ifdef __cplusplus extern "C" { #endif +#include void wiiuse_pressed_buttons(struct wiimote_t* wm, byte* msg); -void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len); +void handshake_expansion(struct wiimote_t* wm, byte* data, uint16_t len); void disable_expansion(struct wiimote_t* wm); #ifdef __cplusplus diff --git a/src/io.c b/src/io.c index ae420b9..df23a4f 100644 --- a/src/io.c +++ b/src/io.c @@ -52,7 +52,7 @@ * The handshake will be concluded when the wiimote responds * with this data. */ -void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len) { +void wiiuse_handshake(struct wiimote_t* wm, byte* data, uint16_t len) { if (!wm) return; switch (wm->handshake_state) { diff --git a/src/io.h b/src/io.h index 7a683e4..7c5fd97 100644 --- a/src/io.h +++ b/src/io.h @@ -44,7 +44,7 @@ extern "C" { #endif -void wiiuse_handshake(struct wiimote_t* wm, byte* data, unsigned short len); +void wiiuse_handshake(struct wiimote_t* wm, byte* data, uint16_t len); int wiiuse_io_read(struct wiimote_t* wm); int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len); diff --git a/src/wiiboard.c b/src/wiiboard.c index 72b593d..94ac71d 100644 --- a/src/wiiboard.c +++ b/src/wiiboard.c @@ -33,6 +33,7 @@ #include #include +#include #include #ifdef WIN32 @@ -45,34 +46,34 @@ #include "events.h" #include "wiiboard.h" -static short big_to_lil(unsigned short num) +static uint16_t big_to_lil(uint16_t num) { - short ret = num; - char *bret = (char*)&ret; - char tmp = bret[1]; + uint16_t ret = num; + uint8_t *bret = (uint8_t*)&ret; + uint8_t tmp = bret[1]; bret[1] = bret[0]; bret[0] = tmp; return ret; } /** - * @brief Handle the handshake data from the guitar. + * @brief Handle the handshake data from the wiiboard. * - * @param cc A pointer to a classic_ctrl_t structure. + * @param wb A pointer to a wii_board_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 wii_board_handshake(struct wiimote_t* wm, struct wii_board_t* wb, byte* data, unsigned short len) { +int wii_board_handshake(struct wiimote_t* wm, struct wii_board_t* wb, byte* data, uint16_t len) { int i; /* decrypt data */ printf("DECRYPTED DATA WIIBOARD\n"); for (i = 0; i < len; ++i) { if(i%16==0) - { + { if(i!=0) printf("\n"); @@ -81,9 +82,9 @@ int wii_board_handshake(struct wiimote_t* wm, struct wii_board_t* wb, byte* data printf("%02X ", data[i]); } printf("\n"); - - short *handshake_short = (short*)data; - + + uint16_t *handshake_short = (uint16_t*)data; + wb->ctr[0] = big_to_lil(handshake_short[2]); wb->cbr[0] = big_to_lil(handshake_short[3]); wb->ctl[0] = big_to_lil(handshake_short[4]); @@ -100,6 +101,7 @@ int wii_board_handshake(struct wiimote_t* wm, struct wii_board_t* wb, byte* data wb->cbl[2] = big_to_lil(handshake_short[13]); /* handshake done */ + wm->event = WIIUSE_WII_BOARD_CTRL_INSERTED; wm->exp.type = EXP_WII_BOARD; #ifdef WIN32 @@ -119,63 +121,35 @@ void wii_board_disconnected(struct wii_board_t* wb) { memset(wb, 0, sizeof(struct wii_board_t)); } +static float do_interpolate(uint16_t raw, uint16_t cal[3]) { + if (raw < cal[1]) { + return ((raw-cal[0]) * 14.0f)/(float)(cal[1] - cal[0]); + } else if (raw > cal[1]) { + return ((raw-cal[1]) * 14.0f)/(float)(cal[2] - cal[1]) + 14.0f; + } +} + /** - * @brief Handle guitar event. + * @brief Handle wii board event. * - * @param cc A pointer to a classic_ctrl_t structure. + * @param wb A pointer to a wii_board_t structure. * @param msg The message specified in the event packet. */ void wii_board_event(struct wii_board_t* wb, byte* msg) { - short *shmsg = (short*)(msg); - wb->rtr = big_to_lil(shmsg[0]); - if(wb->rtr<0) wb->rtr = 0; - wb->rbr = big_to_lil(shmsg[1]); - if(wb->rbr<0) wb->rbr = 0; - wb->rtl = big_to_lil(shmsg[2]); - if(wb->rtl<0) wb->rtl = 0; - wb->rbl = big_to_lil(shmsg[3]); - if(wb->rbl<0) wb->rbl = 0; + uint16_t *shmsg = (uint16_t*)(msg); + wb->rtr = (msg[0] << 8) + msg[1];// big_to_lil(shmsg[0]); + wb->rbr = (msg[2] << 8) + msg[3];// big_to_lil(shmsg[1]); + wb->rtl = (msg[4] << 8) + msg[5];// big_to_lil(shmsg[2]); + wb->rbl = (msg[6] << 8) + msg[7];// big_to_lil(shmsg[3]); - /* - Interpolate values + /* + Interpolate values Calculations borrowed from wiili.org - No names to mention sadly :( http://www.wiili.org/index.php/Wii_Balance_Board_PC_Drivers page however! */ - - if(wb->rtrctr[1]) - { - wb->tr = 68*(wb->rtr-wb->ctr[0])/(wb->ctr[1]-wb->ctr[0]); - } - else if(wb->rtr >= wb->ctr[1]) - { - wb->tr = 68*(wb->rtr-wb->ctr[1])/(wb->ctr[2]-wb->ctr[1]) + 68; - } - - if(wb->rtlctl[1]) - { - wb->tl = 68*(wb->rtl-wb->ctl[0])/(wb->ctl[1]-wb->ctl[0]); - } - else if(wb->rtl >= wb->ctl[1]) - { - wb->tl = 68*(wb->rtl-wb->ctl[1])/(wb->ctl[2]-wb->ctl[1]) + 68; - } - - if(wb->rbrcbr[1]) - { - wb->br = 68*(wb->rbr-wb->cbr[0])/(wb->cbr[1]-wb->cbr[0]); - } - else if(wb->rbr >= wb->cbr[1]) - { - wb->br = 68*(wb->rbr-wb->cbr[1])/(wb->cbr[2]-wb->cbr[1]) + 68; - } - - if(wb->rblcbl[1]) - { - wb->bl = 68*(wb->rbl-wb->cbl[0])/(wb->cbl[1]-wb->cbl[0]); - } - else if(wb->rbl >= wb->cbl[1]) - { - wb->bl = 68*(wb->rbl-wb->cbl[1])/(wb->cbl[2]-wb->cbl[1]) + 68; - } + wb->tr = do_interpolate(wb->rtr, wb->ctr); + wb->tl = do_interpolate(wb->rtl, wb->ctl); + wb->br = do_interpolate(wb->rbr, wb->cbr); + wb->bl = do_interpolate(wb->rbl, wb->cbl); } void wiiuse_set_wii_board_calib(struct wiimote_t *wm) diff --git a/src/wiiboard.h b/src/wiiboard.h index eabbcf6..2c49029 100644 --- a/src/wiiboard.h +++ b/src/wiiboard.h @@ -28,7 +28,7 @@ /** * @file - * @brief Guitar Hero 3 expansion device. + * @brief Wii board expansion device. */ #ifndef WII_BOARD_H_INCLUDED @@ -40,7 +40,7 @@ extern "C" { #endif -int wii_board_handshake(struct wiimote_t* wm, struct wii_board_t* wb, byte* data, unsigned short len); +int wii_board_handshake(struct wiimote_t* wm, struct wii_board_t* wb, byte* data, uint16_t len); void wii_board_disconnected(struct wii_board_t* wb); diff --git a/src/wiiuse.c b/src/wiiuse.c index 8d4b763..6b522ad 100644 --- a/src/wiiuse.c +++ b/src/wiiuse.c @@ -1,390 +1,390 @@ -/* - * 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; +/* + * 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, uint16_t 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; -} - - + 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). * @@ -401,7 +401,7 @@ int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buff * 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) { +int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int addr, uint16_t len) { struct read_req_t* req; if (!wm || !WIIMOTE_IS_CONNECTED(wm)) @@ -440,325 +440,325 @@ int wiiuse_read_data(struct wiimote_t* wm, byte* buffer, unsigned int addr, unsi } -/** - * @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; - +/** + * @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 -} + return; + + /* the offset is in big endian */ + *(int32_t*)(buf) = BIG_ENDIAN_LONG(req->addr); + + /* the length is in big endian */ + *(int16_t*)(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/src/wiiuse.h b/src/wiiuse.h index 6543bc9..afa0270 100644 --- a/src/wiiuse.h +++ b/src/wiiuse.h @@ -53,6 +53,8 @@ #define WCONST const #endif +#include + /* led bit masks */ #define WIIMOTE_LED_NONE 0x00 #define WIIMOTE_LED_1 0x10 @@ -231,7 +233,7 @@ struct gforce_t; * 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); +typedef void (*wiiuse_read_cb)(struct wiimote_t* wm, byte* data, uint16_t len); /** @@ -241,9 +243,9 @@ typedef void (*wiiuse_read_cb)(struct wiimote_t* wm, byte* data, unsigned short 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 */ + uint32_t addr; /**< the offset that the read started at */ + uint16_t size; /**< the length of the data read */ + uint16_t 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 */ @@ -326,8 +328,8 @@ typedef struct ir_dot_t { 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) */ + int16_t rx; /**< raw X coordinate (0-1023) */ + int16_t ry; /**< raw Y coordinate (0-767) */ byte order; /**< increasing order by x-axis value */ @@ -425,9 +427,9 @@ typedef struct nunchuk_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 */ + int16_t btns; /**< what buttons have just been pressed */ + int16_t btns_held; /**< what buttons are being held down */ + int16_t 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) */ @@ -442,9 +444,9 @@ typedef struct classic_ctrl_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 */ + int16_t btns; /**< what buttons have just been pressed */ + int16_t btns_held; /**< what buttons are being held down */ + int16_t btns_released; /**< what buttons were just released this */ float whammy_bar; /**< whammy bar (range 0-1) */ @@ -455,22 +457,19 @@ typedef struct guitar_hero_3_t { Wii board */ typedef struct wii_board_t { - short tl; /* Interpolated */ - short tr; - short bl; - short br; /* End interp */ - short rtl; /* RAW */ - short rtr; - short rbl; - short rbr; /* /RAW */ - short ltl; - short ltr; - short lbl; - short lbr; - short ctl[3]; /* Calibration */ - short ctr[3]; - short cbl[3]; - short cbr[3]; /* /Calibration */ + float tl; /* Interpolated */ + float tr; + float bl; + float br; /* End interp */ + uint16_t rtl; /* RAW */ + uint16_t rtr; + uint16_t rbl; + uint16_t rbr; /* /RAW */ + uint16_t ctl[3]; /* Calibration */ + uint16_t ctr[3]; + uint16_t cbl[3]; + uint16_t cbr[3]; /* /Calibration */ + uint8_t update_calib; } wii_board_t; @@ -511,19 +510,25 @@ typedef struct wiimote_state_t { float exp_rjs_ang; float exp_ljs_mag; float exp_rjs_mag; - unsigned short exp_btns; + uint16_t exp_btns; struct orient_t exp_orient; struct vec3b_t exp_accel; float exp_r_shoulder; float exp_l_shoulder; + /* wiiboard */ + uint16_t exp_wb_rtr; + uint16_t exp_wb_rtl; + uint16_t exp_wb_rbr; + uint16_t exp_wb_rbl; + /* ir_t */ int ir_ax; int ir_ay; float ir_distance; struct orient_t orient; - unsigned short btns; + uint16_t btns; struct vec3b_t accel; } wiimote_state_t; @@ -590,12 +595,12 @@ typedef struct wiimote_t { 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 uint16_t btns; /**< what buttons have just been pressed */ + WCONST uint16_t btns_held; /**< what buttons are being held down */ + WCONST uint16_t 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 int32_t accel_threshold; /**< threshold for accel to generate an event */ WCONST struct wiimote_state_t lstate; /**< last saved state */ @@ -638,7 +643,7 @@ 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_read_data(struct wiimote_t* wm, byte* buffer, unsigned int offset, uint16_t 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); diff --git a/src/wiiuse_internal.h b/src/wiiuse_internal.h index 86b3f40..64f3675 100644 --- a/src/wiiuse_internal.h +++ b/src/wiiuse_internal.h @@ -51,6 +51,8 @@ #include "definitions.h" +#include + /* wiiuse version */ #define WIIUSE_VERSION "0.12" @@ -218,7 +220,7 @@ extern "C" { 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); +int wiiuse_read_data_cb(struct wiimote_t* wm, wiiuse_read_cb read_cb, byte* buffer, unsigned int offset, uint16_t len); #ifdef __cplusplus }