Overhaul of OS X real Wiimote support.

Fixes a number of problems, including unreliable connection setup, 
frequent disconnections, busy-waiting and shutdown deadlocks.

Motion Plus and nunchuk hot swapping now work and Wiiuse does a small
amount of queueing to prevent occasional dropped packets. The OS X 
bluetooth stack has no internal input buffering and while a worker  
thread can easily keep up with data coming from the Wiimote, the rest
of Dolphin can easily get behind if it is blocked by disk I/O or 
similar. Mostly the Wiimote protocol recovers from dropped packets,   
but sometimes the Wiimote would get out of sync and send a disconnect.
I wonder if the other platforms might benefit from a bit of queueing
at this layer as well.
 
Still doesn't support multiple devices, as I kept changing my mind 
about how best to do it. I only have one Wiimote anyway..
 
One improvement to the Wiimote plugin that would be really nice would
be for the scan for new devices to operate continuously or periodically
like on a real Wii rather than just for 5 seconds at startup..   


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5640 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Soren Jorvang 2010-06-09 19:36:08 +00:00
parent 9d792d4673
commit e648c6d68b
9 changed files with 287 additions and 348 deletions

View File

@ -110,7 +110,7 @@ int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte
cc->rjs.center.y = data[11 + offset] / 8;
/* handshake done */
wm->exp.type = EXP_CLASSIC;
wm->expansion.type = EXP_CLASSIC;
wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;

View File

@ -514,18 +514,18 @@ static void event_status(struct wiimote_t* wm, byte* msg) {
* @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) {
switch (wm->expansion.type) {
case EXP_NUNCHUK:
nunchuk_event(&wm->exp.nunchuk, msg);
nunchuk_event(&wm->expansion.nunchuk, msg);
break;
case EXP_CLASSIC:
classic_ctrl_event(&wm->exp.classic, msg);
classic_ctrl_event(&wm->expansion.classic, msg);
break;
case EXP_GUITAR_HERO_3:
guitar_hero_3_event(&wm->exp.gh3, msg);
guitar_hero_3_event(&wm->expansion.gh3, msg);
break;
case EXP_WII_BOARD:
wii_board_event(&wm->exp.wb, msg);
wii_board_event(&wm->expansion.wb, msg);
break;
default:
break;
@ -578,25 +578,25 @@ void handshake_expansion(struct wiimote_t* wm, byte* data, unsigned short len) {
switch (wid) {
case EXP_ID_CODE_NUNCHUK:
{
if (nunchuk_handshake(wm, &wm->exp.nunchuk, data, len))
if (nunchuk_handshake(wm, &wm->expansion.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))
if (classic_ctrl_handshake(wm, &wm->expansion.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))
if (guitar_hero_3_handshake(wm, &wm->expansion.gh3, data, len))
wm->event = WIIUSE_GUITAR_HERO_3_CTRL_INSERTED;
break;
}
case EXP_ID_CODE_WII_BOARD:
{
if (wii_board_handshake(wm, &wm->exp.wb, data, len))
if (wii_board_handshake(wm, &wm->expansion.wb, data, len))
wm->event = WIIUSE_WII_BOARD_CTRL_INSERTED;
break;
}
@ -627,21 +627,21 @@ void disable_expansion(struct wiimote_t* wm) {
return;
/* tell the assoicated module the expansion was removed */
switch (wm->exp.type) {
switch (wm->expansion.type) {
case EXP_NUNCHUK:
nunchuk_disconnected(&wm->exp.nunchuk);
nunchuk_disconnected(&wm->expansion.nunchuk);
wm->event = WIIUSE_NUNCHUK_REMOVED;
break;
case EXP_CLASSIC:
classic_ctrl_disconnected(&wm->exp.classic);
classic_ctrl_disconnected(&wm->expansion.classic);
wm->event = WIIUSE_CLASSIC_CTRL_REMOVED;
break;
case EXP_GUITAR_HERO_3:
guitar_hero_3_disconnected(&wm->exp.gh3);
guitar_hero_3_disconnected(&wm->expansion.gh3);
wm->event = WIIUSE_GUITAR_HERO_3_CTRL_REMOVED;
break;
case EXP_WII_BOARD:
wii_board_disconnected(&wm->exp.wb);
wii_board_disconnected(&wm->expansion.wb);
wm->event = WIIUSE_WII_BOARD_CTRL_REMOVED;
break;
default:
@ -649,7 +649,7 @@ void disable_expansion(struct wiimote_t* wm) {
}
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
wm->exp.type = EXP_NONE;
wm->expansion.type = EXP_NONE;
}
@ -671,29 +671,29 @@ static void save_state(struct wiimote_t* wm) {
}
/* expansion */
switch (wm->exp.type) {
switch (wm->expansion.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;
wm->lstate.exp_ljs_ang = wm->expansion.nunchuk.js.ang;
wm->lstate.exp_ljs_mag = wm->expansion.nunchuk.js.mag;
wm->lstate.exp_btns = wm->expansion.nunchuk.btns;
wm->lstate.exp_accel = wm->expansion.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;
wm->lstate.exp_ljs_ang = wm->expansion.classic.ljs.ang;
wm->lstate.exp_ljs_mag = wm->expansion.classic.ljs.mag;
wm->lstate.exp_rjs_ang = wm->expansion.classic.rjs.ang;
wm->lstate.exp_rjs_mag = wm->expansion.classic.rjs.mag;
wm->lstate.exp_r_shoulder = wm->expansion.classic.r_shoulder;
wm->lstate.exp_l_shoulder = wm->expansion.classic.l_shoulder;
wm->lstate.exp_btns = wm->expansion.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;
wm->lstate.exp_ljs_ang = wm->expansion.gh3.js.ang;
wm->lstate.exp_ljs_mag = wm->expansion.gh3.js.mag;
wm->lstate.exp_r_shoulder = wm->expansion.gh3.whammy_bar;
wm->lstate.exp_btns = wm->expansion.gh3.btns;
break;
case EXP_NONE:
break;
@ -760,42 +760,42 @@ static int state_changed(struct wiimote_t* wm) {
}
/* expansion */
switch (wm->exp.type) {
switch (wm->expansion.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);
STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->expansion.nunchuk.js.ang);
STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->expansion.nunchuk.js.mag);
STATE_CHANGED(wm->lstate.exp_btns, wm->expansion.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);
CROSS_THRESH(wm->lstate.exp_orient, wm->expansion.nunchuk.orient, wm->expansion.nunchuk.orient_threshold);
CROSS_THRESH_XYZ(wm->lstate.exp_accel, wm->expansion.nunchuk.accel, wm->expansion.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);
STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->expansion.classic.ljs.ang);
STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->expansion.classic.ljs.mag);
STATE_CHANGED(wm->lstate.exp_rjs_ang, wm->expansion.classic.rjs.ang);
STATE_CHANGED(wm->lstate.exp_rjs_mag, wm->expansion.classic.rjs.mag);
STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->expansion.classic.r_shoulder);
STATE_CHANGED(wm->lstate.exp_l_shoulder, wm->expansion.classic.l_shoulder);
STATE_CHANGED(wm->lstate.exp_btns, wm->expansion.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);
STATE_CHANGED(wm->lstate.exp_ljs_ang, wm->expansion.gh3.js.ang);
STATE_CHANGED(wm->lstate.exp_ljs_mag, wm->expansion.gh3.js.mag);
STATE_CHANGED(wm->lstate.exp_r_shoulder, wm->expansion.gh3.whammy_bar);
STATE_CHANGED(wm->lstate.exp_btns, wm->expansion.gh3.btns);
break;
}
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->expansion.wb.ltr,wm->expansion.wb.tr);
STATE_CHANGED(wm->expansion.wb.ltl,wm->expansion.wb.tl);
STATE_CHANGED(wm->expansion.wb.lbr,wm->expansion.wb.br);
STATE_CHANGED(wm->expansion.wb.lbl,wm->expansion.wb.bl);
break;
}
case EXP_NONE:

View File

@ -81,7 +81,7 @@ int guitar_hero_3_handshake(struct wiimote_t* wm, struct guitar_hero_3_t* gh3, b
/* handshake done */
wm->event = WIIUSE_GUITAR_HERO_3_CTRL_INSERTED;
wm->exp.type = EXP_GUITAR_HERO_3;
wm->expansion.type = EXP_GUITAR_HERO_3;
wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;

View File

@ -28,247 +28,177 @@
/**
* @file
* @brief Handles device I/O for *nix.
* @brief Handles device I/O for OS X.
*/
#define BLUETOOTH_VERSION_USE_CURRENT
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//osx inlcude
#import <Foundation/NSObject.h>
#import <IOBluetooth/objc/IOBluetoothDevice.h>
#import <IOBluetooth/objc/IOBluetoothDeviceInquiry.h>
#import <IOBluetooth/objc/IOBluetoothL2CAPChannel.h>
#import <IOBluetooth/objc/IOBluetoothHostController.h>
IOBluetoothDeviceInquiry *bti;
IOBluetoothDevice * btd;
IOBluetoothL2CAPChannel * _ichan;
IOBluetoothL2CAPChannel * _cchan;
#import <IOBluetooth/objc/IOBluetoothL2CAPChannel.h>
#include "definitions.h"
#include "wiiuse_internal.h"
#include "io.h"
byte DataFromWiimote[MAX_PAYLOAD];
NSUInteger g_length;
static int wiiuse_connect_single(struct wiimote_t *wm, char *address);
static int wiiuse_connect_single(struct wiimote_t* wm, char* address);
IOBluetoothDevice *btd;
IOBluetoothL2CAPChannel *ichan;
IOBluetoothL2CAPChannel *cchan;
@interface SearchBT: NSObject {}
-(void) deviceInquiryComplete: (IOBluetoothDeviceInquiry*) sender
error: (IOReturn) error
aborted: (BOOL) aborted;
-(void) deviceInquiryDeviceFound: (IOBluetoothDeviceInquiry*) sender
device: (IOBluetoothDevice*) device;
@end
@interface ConnectBT: NSObject {}
-(void) connectToWiimotes;
- (IOBluetoothL2CAPChannel *) openL2CAPChannelWithPSM:(BluetoothL2CAPPSM) psm delegate:(id) delegate;
@end
@implementation ConnectBT
-(void)writeToWiimote: (void *)data length:(UInt16)length
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[_cchan writeSync:data length:length];
usleep(10000);
[pool release];
#define QUEUE_SIZE 8
volatile struct buffer {
char data[MAX_PAYLOAD];
int len;
} queue[QUEUE_SIZE];
volatile int reader, writer, outstanding;
@interface SearchBT: NSObject {
@public
int maxDevices;
}
#pragma mark -
#pragma mark Bluetooth
- (void) l2capChannelOpenComplete:(IOBluetoothL2CAPChannel*) l2capChannel status:(IOReturn) error {
//channel opened
//something to do here ?
}
- (void)l2capChannelData:(IOBluetoothL2CAPChannel *) l2capChannel data:(byte *)BtData length:(NSUInteger)length {
//here we got data from wiimote
memcpy(DataFromWiimote, BtData, MAX_PAYLOAD);
g_length = length;
//stop the main loop after reading
CFRunLoopStop( CFRunLoopGetCurrent() );
}
- (void) l2capChannelClosed:(IOBluetoothL2CAPChannel*) l2capChannel {
//channel closed
printf("Bt channel closed\n");
if (l2capChannel == _cchan)
_cchan = nil;
if (l2capChannel == _ichan)
_ichan = nil;
}
#pragma mark -
- (IOBluetoothL2CAPChannel *) openL2CAPChannelWithPSM:(BluetoothL2CAPPSM) psm delegate:(id) delegate {
IOBluetoothL2CAPChannel * channel = nil;
IOReturn ret = kIOReturnSuccess;
WIIUSE_INFO("Open channel (PSM:%i) ...", psm);
if ((ret = (IOReturn)[btd openL2CAPChannelSync:&channel withPSM:psm delegate:delegate]) != kIOReturnSuccess) {
WIIUSE_INFO("Could not open L2CAP channel (psm:%i)", psm);
channel = nil;
//TODO : close the connection
}
return channel;
}
-(void) connectToWiimotes {
NSEnumerator * en = [[bti foundDevices] objectEnumerator];
id device = nil;
while ((device = [en nextObject]) != nil) {
btd = device;
[btd openL2CAPChannelSync:&_cchan withPSM:kBluetoothL2CAPPSMHIDControl delegate:self];
if (!_cchan)
WIIUSE_INFO("error when initialised cchan");
usleep (20000);
[btd openL2CAPChannelSync:&_ichan withPSM:kBluetoothL2CAPPSMHIDInterrupt delegate:self];
if (!_ichan)
WIIUSE_INFO("error when initialised ichan");
usleep (20000);
}
}
@end
@implementation SearchBT
-(void) deviceInquiryComplete: (IOBluetoothDeviceInquiry*) sender
error: (IOReturn) error
aborted: (BOOL) aborted
- (void) deviceInquiryComplete: (IOBluetoothDeviceInquiry *) sender
error: (IOReturn) error
aborted: (BOOL) aborted
{
//int founded = [[bti foundDevices] count];
CFRunLoopStop( CFRunLoopGetCurrent() );
}
-(void) deviceInquiryDeviceFound: (IOBluetoothDeviceInquiry*) sender
device: (IOBluetoothDevice*) device
{
WIIUSE_INFO("discovered one wiimote: %s", [[device getAddressString] UTF8String]);
[bti stop];
CFRunLoopStop(CFRunLoopGetCurrent());
}
- (void) deviceInquiryDeviceFound: (IOBluetoothDeviceInquiry *) sender
device: (IOBluetoothDevice *) device
{
WIIUSE_INFO("Discovered bluetooth device at %s: %s",
[[device getAddressString] UTF8String],
[[device getName] UTF8String]);
if ([[sender foundDevices] count] == maxDevices)
[sender stop];
}
@end
SearchBT *sbt;
ConnectBT *cbt;
@interface ConnectBT: NSObject {}
@end
void detectWiimote(int timeout) {
@implementation ConnectBT
- (void) l2capChannelData: (IOBluetoothL2CAPChannel *) l2capChannel
data: (byte *) data
length: (NSUInteger) length
{
// IOBluetoothDevice *device = [l2capChannel getDevice];
[bti setDelegate: sbt];
[bti setInquiryLength:timeout];
[bti setSearchCriteria:kBluetoothServiceClassMajorAny majorDeviceClass:0x05 minorDeviceClass:0x01];
[bti setUpdateNewDeviceNames:NO];
if (length > MAX_PAYLOAD) {
WIIUSE_WARNING("Dropping wiimote packet - too large");
return;
}
IOReturn ret = [bti start];
if (ret == kIOReturnSuccess)
[bti retain];
else
{
WIIUSE_INFO("error when detecting wiimote");
[bti setDelegate: nil];
bti = nil;
}
if (queue[writer].len != 0) {
WIIUSE_WARNING("Dropping wiimote packet - queue full");
return;
}
memcpy(queue[writer].data, data, length);
queue[writer].len = length;
writer++;
outstanding++;
if (writer == QUEUE_SIZE)
writer = 0;
CFRunLoopStop(CFRunLoopGetCurrent());
}
- (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel
{
// IOBluetoothDevice *device = [l2capChannel getDevice];
WIIUSE_WARNING("L2CAP channel was closed");
if (l2capChannel == cchan)
cchan = nil;
if (l2capChannel == ichan)
ichan = nil;
}
@end
/**
* @brief Find a wiimote or wiimotes.
*
* @param wm An array of wiimote_t structures.
* @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.
* @param timeout The number of seconds before timing out.
*
* @return The number of wiimotes found.
*
* @see wiimote_connect()
* @see wiiuse_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
* This function will only look for wiimote devices.
* When a device is found the address in the structures will be set.
* You can then call wiiuse_connect() to connect to the found
* devices.
*/
int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) {
int found_wiimotes = 0;
int wiiuse_find(struct wiimote_t **wm, int max_wiimotes, int timeout)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
IOBluetoothHostController *bth;
IOBluetoothDeviceInquiry *bti;
SearchBT *sbt;
NSEnumerator *en;
int i, found_devices = 0;
IOBluetoothHostController *bth = [[IOBluetoothHostController alloc] init];
if([bth addressAsString] == nil)
bth = [[IOBluetoothHostController alloc] init];
if ([bth addressAsString] == nil)
{
// Method addressAsString will return nil since it can't find a device
WIIUSE_INFO("No BT device");
WIIUSE_WARNING("No bluetooth host controller");
[bth release];
[pool release];
return 0; // 0 Wiimotes found
return 0;
}
sbt = [[SearchBT alloc] init];
cbt = [[ConnectBT alloc] init];
bti = [[IOBluetoothDeviceInquiry alloc] init];
detectWiimote(timeout);
sbt = [[SearchBT alloc] init];
sbt->maxDevices = max_wiimotes;
/*XXX*/ sbt->maxDevices = 1;
bti = [[IOBluetoothDeviceInquiry alloc] init];
[bti setDelegate: sbt];
[bti setInquiryLength: timeout];
[bti setSearchCriteria: kBluetoothServiceClassMajorAny
majorDeviceClass: 0x05 minorDeviceClass: 0x01];
[bti setUpdateNewDeviceNames: FALSE];
IOReturn ret = [bti start];
if (ret == kIOReturnSuccess)
[bti retain];
else
WIIUSE_ERROR("Unable to do bluetooth discovery");
CFRunLoopRun();
#if 0 /* XXX */
WIIUSE_INFO("Found %i bluetooth device(s).", found_devices);
#endif
[bti stop];
found_devices = [[bti foundDevices] count];
WIIMOTE_ENABLE_STATE(wm[found_wiimotes], WIIMOTE_STATE_DEV_FOUND);
WIIUSE_INFO("Found %i bluetooth device(s).", found_devices);
en = [[bti foundDevices] objectEnumerator];
for (i = 0; i < found_devices; i++) {
btd = [en nextObject];
WIIMOTE_ENABLE_STATE(wm[i], WIIMOTE_STATE_DEV_FOUND);
}
[bth release];
[bti release];
[sbt release];
[cbt release];
[pool release];
return 1;
return found_devices;
}
/**
* @brief Connect to a wiimote or wiimotes once an address is known.
*
* @param wm An array of wiimote_t structures.
* @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.
@ -281,62 +211,60 @@ int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) {
* 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 i = 0;
int wiiuse_connect(struct wiimote_t **wm, int wiimotes)
{
int i, connected = 0;
/*for (; i < wiimotes; ++i) {
for (i = 0; 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;
}*/
wiiuse_connect_single(wm[i], NULL);
connected++;
}
//return connected;
return 1;
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().
* @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) {
static int wiiuse_connect_single(struct wiimote_t *wm, char *address)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
ConnectBT *cbt = [[ConnectBT alloc] init];
if (!wm || WIIMOTE_IS_CONNECTED(wm))
if (wm == NULL || WIIMOTE_IS_CONNECTED(wm))
return 0;
//connect to the wiimote
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[btd openL2CAPChannelSync: &cchan
withPSM: kBluetoothL2CAPPSMHIDControl delegate: cbt];
[btd openL2CAPChannelSync: &ichan
withPSM: kBluetoothL2CAPPSMHIDInterrupt delegate: cbt];
if (ichan == NULL || cchan == NULL) {
WIIUSE_ERROR("Unable to open L2CAP channels");
wiiuse_disconnect(wm);
}
cbt = [[ConnectBT alloc] init];
//start to connect to the wiimotes
[cbt connectToWiimotes];
usleep (200000); // Little delay, or else the device isn't ready!
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);
[cbt release];
[pool release];
return 1;
}
/**
* @brief Disconnect a wiimote.
*
@ -346,42 +274,55 @@ static int wiiuse_connect_single(struct wiimote_t* wm, char* address) {
*
* Note that this will not free the wiimote structure.
*/
void wiiuse_disconnect(struct wiimote_t* wm) {
if (!wm || WIIMOTE_IS_CONNECTED(wm))
void wiiuse_disconnect(struct wiimote_t *wm)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if (wm == NULL)
return;
//TODO
WIIUSE_INFO("Disconnecting wiimote [id %i]", wm->unid);
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
[cchan closeChannel];
[ichan closeChannel];
[btd closeConnection];
[pool release];
}
int wiiuse_io_read(struct wiimote_t* wm) {
int wiiuse_io_read(struct wiimote_t *wm)
{
int bytes;
if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED))
return 0;
/* if this wiimote is not connected, skip it */
if (!WIIMOTE_IS_CONNECTED(wm))
return 0;
//run the main loop to get bt data
CFRunLoopRun();
memcpy(wm->event_buf,DataFromWiimote, g_length);
if(!g_length || !wm->event_buf[0]) // no packet
return 0;
wm->event_buf[0] = 0xa2; // Make sure it's 0xa2, just in case
return 1;
if (outstanding == 0)
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, true);
if (queue[reader].len == 0)
return 0;
bytes = queue[reader].len;
memcpy(wm->event_buf, queue[reader].data, bytes);
queue[reader].len = 0;
reader++;
outstanding--;
if (reader == QUEUE_SIZE)
reader = 0;
if (wm->event_buf[0] == '\0')
bytes = 0;
return bytes;
}
int wiiuse_io_write(struct wiimote_t *wm, byte *buf, int len)
{
[cchan writeSync: buf length: len];
int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) {
[cbt writeToWiimote:buf length:len];
return 1;
return len;
}

View File

@ -109,7 +109,7 @@ int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, byte* data, un
nc->accel_threshold = wm->accel_threshold;
/* handshake done */
wm->exp.type = EXP_NUNCHUK;
wm->expansion.type = EXP_NUNCHUK;
/* if min and max are reported as 0, initialize them to usable values based on center, and fine tune in nunchuck_event() */
if (nc->js.center.x) {
@ -212,7 +212,7 @@ static void nunchuk_pressed_buttons(struct nunchuk_t* nc, byte now) {
void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold) {
if (!wm) return;
wm->exp.nunchuk.orient_threshold = threshold;
wm->expansion.nunchuk.orient_threshold = threshold;
}
@ -227,5 +227,5 @@ void wiiuse_set_nunchuk_orient_threshold(struct wiimote_t* wm, float threshold)
void wiiuse_set_nunchuk_accel_threshold(struct wiimote_t* wm, int threshold) {
if (!wm) return;
wm->exp.nunchuk.accel_threshold = threshold;
wm->expansion.nunchuk.accel_threshold = threshold;
}

View File

@ -84,7 +84,7 @@ int wii_board_handshake(struct wiimote_t* wm, struct wii_board_t* wb, byte* data
/* handshake done */
wm->event = WIIUSE_WII_BOARD_CTRL_INSERTED;
wm->exp.type = EXP_WII_BOARD;
wm->expansion.type = EXP_WII_BOARD;
return 1;
}

View File

@ -127,12 +127,10 @@ struct wiimote_t** wiiuse_init(int wiimotes) {
wm[i]->bdaddr = *BDADDR_ANY;
wm[i]->out_sock = -1;
wm[i]->in_sock = -1;
#else
#if !defined(__APPLE__)
#elif defined(_WIN32)
wm[i]->dev_handle = 0;
wm[i]->stack = WIIUSE_STACK_UNKNOWN;
#endif
#endif
wm[i]->normal_timeout = WIIMOTE_DEFAULT_TIMEOUT;
wm[i]->exp_timeout = WIIMOTE_EXP_TIMEOUT;
@ -143,7 +141,7 @@ struct wiimote_t** wiiuse_init(int wiimotes) {
wm[i]->event = WIIUSE_NONE;
wm[i]->exp.type = EXP_NONE;
wm[i]->expansion.type = EXP_NONE;
wiiuse_set_aspect_ratio(wm[i], WIIUSE_ASPECT_4_3);
wiiuse_set_ir_position(wm[i], WIIUSE_IR_ABOVE);
@ -181,10 +179,10 @@ void wiiuse_disconnected(struct wiimote_t* wm) {
wm->btns_released = 0;
memset(wm->event_buf, 0, sizeof(wm->event_buf));
#ifndef WIN32
#ifdef __linux__
wm->out_sock = -1;
wm->in_sock = -1;
#else
#elif defined(_WIN32)
CloseHandle(wm->dev_handle);
wm->dev_handle = 0;
#endif
@ -298,7 +296,7 @@ void wiiuse_motion_sensing(struct wiimote_t* wm, int status) {
*/
int wiiuse_set_report_type(struct wiimote_t* wm) {
byte buf[2];
int motion, exp, ir;
int motion, expansion, ir;
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
return 0;
@ -311,23 +309,23 @@ int wiiuse_set_report_type(struct wiimote_t* wm) {
buf[0] |= 0x01;
motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC);
exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP);
expansion = 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;
if (motion && ir && expansion) buf[1] = WM_RPT_BTN_ACC_IR_EXP;
else if (motion && expansion) buf[1] = WM_RPT_BTN_ACC_EXP;
else if (motion && ir) buf[1] = WM_RPT_BTN_ACC_IR;
else if (ir && expansion) 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 (expansion) buf[1] = WM_RPT_BTN_EXP;
else if (motion) buf[1] = WM_RPT_BTN_ACC;
else buf[1] = WM_RPT_BTN;
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;
expansion = wiiuse_send(wm, WM_CMD_REPORT_TYPE, buf, 2);
if (expansion <= 0)
return expansion;
return buf[1];
}
@ -663,8 +661,8 @@ float wiiuse_set_smooth_alpha(struct wiimote_t* wm, float 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;
if (wm->expansion.type == EXP_NUNCHUK)
wm->expansion.nunchuk.accel_calib.st_alpha = alpha;
return old;
}

View File

@ -42,12 +42,12 @@
//#define WITH_WIIUSE_DEBUG
#ifdef _WIN32
/* windows */
#include <windows.h>
#elif defined(__APPLE__)
#include <CoreFoundation/CoreFoundation.h>
#include <IOBluetooth/IOBluetoothUserLib.h>
#include <string.h>
#else
/* nix */
#elif defined(__linux__)
#include <bluetooth/bluetooth.h>
#endif
@ -575,55 +575,55 @@ typedef enum WIIUSE_EVENT_TYPE {
* @brief Wiimote structure.
*/
typedef struct wiimote_t {
WCONST int unid; /**< user specified id */
WCONST int unid; /**< user specified id */
#ifndef WIN32
#if defined(__APPLE__)
WCONST char bdaddr[10]; /**< bt address on osx addr are string */
#else
WCONST bdaddr_t bdaddr; /**< bt address (linux) */
WCONST IOBluetoothDeviceRef *device;
WCONST char bdaddr_str[18];
#elif defined(__linux__)
WCONST bdaddr_t bdaddr; /**< bt address (linux) */
WCONST char bdaddr_str[18]; /**< readable bt address */
WCONST int out_sock; /**< output socket */
WCONST int in_sock; /**< input socket */
#elif defined(_WIN32)
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 */
#endif
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 */
#endif
WCONST int timeout; /**< read timeout */
WCONST byte normal_timeout; /**< normal timeout */
WCONST byte exp_timeout; /**< timeout for expansion handshake */
WCONST int state; /**< various state flags */
WCONST byte leds; /**< currently lit leds */
WCONST float battery_level; /**< battery level */
WCONST int timeout; /**< read timeout */
WCONST byte normal_timeout; /**< normal timeout */
WCONST byte exp_timeout; /**< timeout for expansion handshake */
WCONST int flags; /**< options flag */
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 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 expansion_t expansion; /**< wiimote expansion device */
WCONST struct vec3b_t accel; /**< current raw acceleration data */
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 struct ir_t ir; /**< IR data */
WCONST unsigned short btns; /**< what buttons have just been pressed */
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 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 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 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 */
WCONST WIIUSE_EVENT_TYPE event; /**< type of event that occured */
WCONST byte event_buf[MAX_PAYLOAD]; /**< event buffer */
} wiimote;

View File

@ -49,7 +49,7 @@ void handle_ctrl_status(struct wiimote_t* wm)
{
DEBUG_LOG(WIIMOTE, "--- CONTROLLER STATUS [wiimote id %i] ---", wm->unid);
DEBUG_LOG(WIIMOTE, "attachment: %i", wm->exp.type);
DEBUG_LOG(WIIMOTE, "attachment: %i", wm->expansion.type);
DEBUG_LOG(WIIMOTE, "speaker: %i", WIIUSE_USING_SPEAKER(wm));
DEBUG_LOG(WIIMOTE, "ir: %i", WIIUSE_USING_IR(wm));
DEBUG_LOG(WIIMOTE, "leds: %i %i %i %i", WIIUSE_IS_LED_SET(wm, 1), WIIUSE_IS_LED_SET(wm, 2), WIIUSE_IS_LED_SET(wm, 3), WIIUSE_IS_LED_SET(wm, 4));
@ -89,9 +89,9 @@ void handle_event(struct wiimote_t* wm)
struct nunchuk_t* nc = NULL;
if (wm->exp.type == EXP_NUNCHUK) {
if (wm->expansion.type == EXP_NUNCHUK) {
nc = (nunchuk_t*)&wm->exp.nunchuk;
nc = (nunchuk_t*)&wm->expansion.nunchuk;
if (IS_PRESSED(nc, NUNCHUK_BUTTON_C))
DEBUG_LOG(WIIMOTE, "C pressed");
if (IS_PRESSED(nc, NUNCHUK_BUTTON_Z))
@ -160,7 +160,7 @@ void handle_event(struct wiimote_t* wm)
Tmp += StringFromFormat("IR cursor: (%u, %u)\n", wm->ir.x, wm->ir.y);
Tmp += StringFromFormat("IR z distance: %f\n", wm->ir.z);
if(wm->exp.type == EXP_NUNCHUK)
if(wm->expansion.type == EXP_NUNCHUK)
{
Tmp += "\n";
Tmp += StringFromFormat("Nunchuck accel x, y, z: %03i %03i %03i\n", nc->accel.x, nc->accel.y, nc->accel.z);
@ -202,7 +202,7 @@ void handle_event(struct wiimote_t* wm)
int GNCx, GNCy, GNCz;
if(wm->exp.type == EXP_NUNCHUK) // Updating Nunchuck Gauges
if(wm->expansion.type == EXP_NUNCHUK) // Updating Nunchuck Gauges
{
m_RecordingConfigFrame->m_GaugeGForceNunchuk[0]->SetValue((int)floor((nc->gforce.x * 300) + 100.5));
m_RecordingConfigFrame->m_GaugeGForceNunchuk[1]->SetValue((int)floor((nc->gforce.y * 300) + 100.5));
@ -231,7 +231,7 @@ void handle_event(struct wiimote_t* wm)
// wxT("Current: %03u %03u %03u"), Gx, Gy, Gz));
if(m_RecordingConfigFrame->m_bRecording) {
if(wm->exp.type != EXP_NUNCHUK) {
if(wm->expansion.type != EXP_NUNCHUK) {
DEBUG_LOG(WIIMOTE, "Wiiuse Recorded accel x, y, z: %03i %03i %03i", Gx, Gy, Gz);
}
else {