From f1c7a7712b68cc2bd433f36d7757ed550791b486 Mon Sep 17 00:00:00 2001 From: Lysann Schlegel Date: Sat, 10 Nov 2012 13:03:51 +0100 Subject: [PATCH] delete mac implementation, replace by stub; reorganize platform-specific code --- src/CMakeLists.txt | 2 +- src/events.c | 13 +- src/io.c | 71 ++++ src/io.h | 21 +- src/io_mac.h | 107 ------ src/io_mac.m | 885 ++------------------------------------------- src/io_nix.c | 52 +-- src/io_platform.h | 62 ++++ src/io_win.c | 6 +- src/wiiuse.h | 12 +- 10 files changed, 188 insertions(+), 1043 deletions(-) delete mode 100755 src/io_mac.h mode change 100755 => 100644 src/io_mac.m create mode 100644 src/io_platform.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a0b4ad..aaa9e17 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,6 +16,7 @@ set(SOURCES motion_plus.h motion_plus.c io.h + io_platform.h ir.h nunchuk.h os.h @@ -29,7 +30,6 @@ if(WIN32) list(APPEND SOURCES io_win.c) set(CMAKE_DEBUG_POSTFIX _debug) elseif(APPLE) - list(APPEND SOURCES io_mac.h) list(APPEND SOURCES io_mac.m) # make sure we use the gcc for Objective-C files as well so that the # sysroot and deployment target arguments are correctly passed to the compiler diff --git a/src/events.c b/src/events.c index a6e82ec..434b453 100644 --- a/src/events.c +++ b/src/events.c @@ -199,19 +199,8 @@ int wiiuse_poll(struct wiimote_t** wm, int wiimotes) { for (i = 0; i < wiimotes; ++i) { wm[i]->event = WIIUSE_NONE; - - if (wiiuse_io_read(wm[i])) { - /* propagate the event, messages should be read as in linux, starting from the second element */ - propagate_event(wm[i], wm[i]->event_buf[1], wm[i]->event_buf+2); - 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]); - } + idle_cycle(wm[i]); } - #endif return evnt; diff --git a/src/io.c b/src/io.c index 168ff9f..9871c8f 100644 --- a/src/io.c +++ b/src/io.c @@ -30,11 +30,82 @@ * @file * @brief Handles device I/O (non-OS specific). */ + #include "io.h" #include "ir.h" /* for wiiuse_set_ir_mode */ #include /* for free, malloc */ +/** + * @brief Find a wiimote or wiimotes. + * + * @param wm An array of wiimote_t structures. + * @param max_wiimotes The number of wiimote structures in \a wm. + * @param timeout The number of seconds before the search times out. + * + * @return The number of wiimotes found. + * + * @see wiiuse_connect() + * @see wiiuse_io_find() + * + * This function will only look for wiimote devices. \n + * When a device is found the address in the structures will be set. \n + * You can then call wiiuse_connect() to connect to the found \n + * devices. + * + * This function only delegates to the platform-specific implementation + * wiiuse_io_find. + * + * This function is declared in wiiuse.h + */ +int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { + return wiiuse_io_find(wm, max_wiimotes, timeout); +} + +/** + * @brief Connect to a wiimote or wiimotes once an address is known. + * + * @param wm An array of wiimote_t structures. + * @param wiimotes The number of wiimote structures in \a wm. + * + * @return The number of wiimotes that successfully connected. + * + * @see wiiuse_find() + * @see wiiuse_disconnect() + * @see wiiuse_io_connect() + * + * Connect to a number of wiimotes when the address is already set + * in the wiimote_t structures. These addresses are normally set + * by the wiiuse_find() function, but can also be set manually. + * + * This function only delegates to the platform-specific implementation + * wiiuse_io_connect. + * + * This function is declared in wiiuse.h + */ +int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { + return wiiuse_io_connect(wm, wiimotes); +} + +/** + * @brief Disconnect a wiimote. + * + * @param wm Pointer to a wiimote_t structure. + * + * @see wiiuse_connect() + * @see wiiuse_io_disconnect() + * + * Note that this will not free the wiimote structure. + * + * This function only delegates to the platform-specific implementation + * wiiuse_io_disconnect. + * + * This function is declared in wiiuse.h + */ +void wiiuse_disconnect(struct wiimote_t* wm) { + wiiuse_io_disconnect(wm); +} + static void wiiuse_disable_motion_plus2(struct wiimote_t *wm,byte *data,unsigned short len) { diff --git a/src/io.h b/src/io.h index 246774f..ddf634c 100644 --- a/src/io.h +++ b/src/io.h @@ -31,33 +31,24 @@ * @brief Handles device I/O. */ -#ifndef CONNECT_H_INCLUDED -#define CONNECT_H_INCLUDED - -#ifdef WIIUSE_BLUEZ - #include -#endif +#ifndef IO_H_INCLUDED +#define IO_H_INCLUDED #include "wiiuse_internal.h" +#include "io_platform.h" // declare functions implemented per platform + #ifdef __cplusplus extern "C" { #endif - -/** @defgroup internal_io Internal: Device IO */ +/** @defgroup internal_io Internal: Device I/O */ /** @{ */ void wiiuse_handshake(struct wiimote_t* wm, byte* data, uint16_t len); - -void wiiuse_init_platform_fields(struct wiimote_t* wm); -void wiiuse_cleanup_platform_fields(struct wiimote_t* wm); - -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 */ +#endif /* IO_H_INCLUDED */ diff --git a/src/io_mac.h b/src/io_mac.h deleted file mode 100755 index d5e2c6b..0000000 --- a/src/io_mac.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * io_mac.h - * - * This file is based on io_mac.h from WiiC, written By: - * Gabriele Randelli - * Email: < randelli (--AT--) dis [--DOT--] uniroma1 [--DOT--] it > - * - * Copyright 2010 - * - * 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 I/O header file for MacOS. - */ -#ifndef IO_MAC_H -#define IO_MAC_H - -#import -#import -#import - -#define BLUETOOTH_VERSION_USE_CURRENT - -#import /* htons() */ -#import -#import -#import -#import -#import - -#import "wiiuse_internal.h" -#import "io.h" - -@interface WiiSearch : NSObject -{ - IOBluetoothDeviceInquiry* inquiry; - BOOL isDiscovering; - // Number of found wiimotes - int foundWiimotes; - // Maximum number of wiimotes to be searched - int maxWiimotes; - // The Wiimotes structure - wiimote** wiimotes; -} - -- (BOOL) isDiscovering; -- (void) setDiscovering:(BOOL) flag; -- (void) setWiimoteStruct:(wiimote**) wiimote_struct; -- (int) getFoundWiimotes; -- (IOReturn) start:(unsigned int) timeout maxWiimotes:(unsigned int) wiimotesNum; -- (IOReturn) stop; -- (IOReturn) close; -- (void) retrieveWiimoteInfo:(IOBluetoothDevice*) device; -- (void) deviceInquiryStarted:(IOBluetoothDeviceInquiry*) sender; -- (void) deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry *) sender device:(IOBluetoothDevice *) device; -- (void) deviceInquiryComplete:(IOBluetoothDeviceInquiry*) sender error:(IOReturn) error aborted:(BOOL) aborted; - -@end - -@interface WiiConnect : NSObject -{ - // Buffer to store incoming data from the Wiimote - NSData* receivedMsg; - unsigned int msgLength; - - // Reference to the relative wiimote struct (used only to complete handshaking) - wiimote* _wm; - BOOL isReading; - BOOL timeout; - BOOL disconnecting; -} - -- (IOBluetoothL2CAPChannel *) openL2CAPChannelWithPSM:(BluetoothL2CAPPSM) psm device:(IOBluetoothDevice*) device delegate:(id) delegate; -- (IOReturn) connectToWiimote:(wiimote*) wm; -- (void) l2capChannelData:(IOBluetoothL2CAPChannel*) channel data:(byte *) data length:(NSUInteger) length; -- (byte*) getNextMsg; -- (unsigned int) getMsgLength; -- (void) deleteMsg; -- (void) disconnected:(IOBluetoothUserNotification*) notification fromDevice:(IOBluetoothDevice*) device; -- (BOOL) isReading; -- (void) setReading:(BOOL) flag; -- (BOOL) isTimeout; -- (void) setTimeout:(BOOL) flag; -- (void) startTimerThread; -- (void) wakeUpMainThreadRunloop:(id)arg; -- (BOOL) isDisconnecting; -@end - -#endif /* IO_MAC_H */ diff --git a/src/io_mac.m b/src/io_mac.m old mode 100755 new mode 100644 index 652cc4a..50d6517 --- a/src/io_mac.m +++ b/src/io_mac.m @@ -1,39 +1,39 @@ /* - * io_mac.m + * wiiuse * - * This file is based on io_mac.m from WiiC, written By: - * Gabriele Randelli - * Email: < randelli (--AT--) dis [--DOT--] uniroma1 [--DOT--] it > + * Written By: + * Michael Laforest < para > + * Email: < thepara (--AT--) g m a i l [--DOT--] com > * - * Copyright 2010 + * Copyright 2006-2007 * - * This file is part of wiiuse. + * 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 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. + * 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 . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * - * $Header$ + * $Header$ * */ /** - * @file - * @brief Handles device I/O for Mac. + * @file + * @brief Handles device I/O for Mac OS X. */ + #ifdef __APPLE__ -#import "io_mac.h" -#import "events.h" +#include "io.h" #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7 #define WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE 1 @@ -41,848 +41,33 @@ #define WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE 0 #endif -@implementation WiiSearch -#pragma mark - -#pragma mark WiiSearch -- (id) init -{ +void wiiuse_init_platform_fields(struct wiimote_t* wm) { - self = [super init]; - foundWiimotes = 0; - isDiscovering = NO; - if (self != nil) { - /* - * Calling IOBluetoothLocalDeviceAvailable has two advantages: - * 1. it sets up a event source in the run loop (bug for C version of the bluetooth api) - * 2. it checks for the availability of the BT hardware - */ - if (![IOBluetoothHostController defaultController]) - { - [self release]; - self = nil; - } - } - - return self; } -- (void) dealloc -{ - inquiry = 0; - WIIUSE_DEBUG("Wiimote Discovery released"); - [super dealloc]; +void wiiuse_cleanup_platform_fields(struct wiimote_t* wm) { + } -- (BOOL) isDiscovering -{ - return isDiscovering; +int wiiuse_io_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { + return 0; } -- (void) setDiscovering:(BOOL) flag -{ - isDiscovering = flag; +int wiiuse_io_connect(struct wiimote_t** wm, int wiimotes) { + return 0; } -- (void) setWiimoteStruct:(wiimote**) wiimote_struct -{ - wiimotes = wiimote_struct; +void wiiuse_io_disconnect(struct wiimote_t* wm) { + } -- (int) getFoundWiimotes -{ - return foundWiimotes; +int wiiuse_io_read(struct wiimote_t* wm) { + return 0; } -- (IOReturn) start:(unsigned int) timeout maxWiimotes:(unsigned int) wiimotesNum -{ - if (![IOBluetoothHostController defaultController]) { - WIIUSE_ERROR("Unable to find any bluetooth receiver on your host."); - return kIOReturnNotAttached; - } - - // If we are currently discovering, we can't start a new discovery right now. - if ([self isDiscovering]) { - WIIUSE_INFO("Wiimote search is already in progress..."); - return kIOReturnSuccess; - } - - [self close]; - maxWiimotes = wiimotesNum; - foundWiimotes = 0; - - inquiry = [IOBluetoothDeviceInquiry inquiryWithDelegate:self]; - // We set the search timeout - if(timeout == 0) - [inquiry setInquiryLength:5]; - else if(timeout < 20) - [inquiry setInquiryLength:timeout]; - else - [inquiry setInquiryLength:20]; - [inquiry setSearchCriteria:kBluetoothServiceClassMajorAny majorDeviceClass:WM_DEV_MAJOR_CLASS minorDeviceClass:WM_DEV_MINOR_CLASS]; - [inquiry setUpdateNewDeviceNames:NO]; - - IOReturn status = [inquiry start]; - if (status == kIOReturnSuccess) { - [inquiry retain]; - } else { - [self close]; - WIIUSE_ERROR("Unable to search for bluetooth devices."); - } - - return status; +int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) { + return 0; } -- (IOReturn) stop -{ - return [inquiry stop]; -} - -- (IOReturn) close -{ - IOReturn ret = kIOReturnSuccess; - - ret = [inquiry stop]; - [inquiry release]; - inquiry = nil; - - WIIUSE_DEBUG("Discovery closed"); - return ret; -} - -#pragma mark - -#pragma mark IOBluetoothDeviceInquiry delegates -//*************** HANDLERS FOR WIIUSE_FIND FOR MACOSX *******************/ -- (void) retrieveWiimoteInfo:(IOBluetoothDevice*) device -{ - // We set the device reference (we must retain it to use it after the search) -#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE - wiimotes[foundWiimotes]->device = (IOBluetoothDeviceRef) [device retain]; -#else - wiimotes[foundWiimotes]->device = [[device retain] getDeviceRef]; -#endif - wiimotes[foundWiimotes]->address = (CFStringRef) [IOBluetoothNSStringFromDeviceAddress([device getAddress]) retain]; - - // C String (common for Mac and Linux) - CFStringGetCString(wiimotes[foundWiimotes]->address,wiimotes[foundWiimotes]->bdaddr_str,18,kCFStringEncodingMacRoman); - - WIIMOTE_ENABLE_STATE(wiimotes[foundWiimotes], WIIMOTE_STATE_DEV_FOUND); - WIIUSE_INFO("Found Wiimote (%s) [id %i].",CFStringGetCStringPtr(wiimotes[foundWiimotes]->address, kCFStringEncodingMacRoman),wiimotes[foundWiimotes]->unid); - ++foundWiimotes; -} - -- (void) deviceInquiryStarted:(IOBluetoothDeviceInquiry*) sender -{ - [self setDiscovering:YES]; -} - -- (void) deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry *) sender device:(IOBluetoothDevice *) device -{ - if(foundWiimotes < maxWiimotes) - [self retrieveWiimoteInfo:device]; - else - [inquiry stop]; -} - -- (void) deviceInquiryComplete:(IOBluetoothDeviceInquiry*) sender error:(IOReturn) error aborted:(BOOL) aborted -{ - // The inquiry has completed, we can now process what we have found - [self setDiscovering:NO]; - - // We stop the search because of errors - if ((error != kIOReturnSuccess) && !aborted) { - foundWiimotes = 0; - [self close]; - WIIUSE_ERROR("Search not completed, because of unexpected errors. This error can be due to a short search timeout."); - return; - } - - foundWiimotes = [[inquiry foundDevices] count]; -} - -@end - -@implementation WiiConnect -#pragma mark - -#pragma mark WiiConnect -- (id) init -{ - self = [super init]; - receivedMsg = [[NSData alloc] init]; - msgLength = 0; - _wm = 0; - isReading = NO; - timeout = NO; - disconnecting = NO; - return self; -} - -- (void) dealloc -{ - WIIUSE_DEBUG("Wiimote released"); - if(receivedMsg) - [receivedMsg release]; - receivedMsg = 0; - _wm = 0; - [super dealloc]; -} - -- (byte*) getNextMsg -{ - if(!receivedMsg) - return 0; - - return (byte*)[receivedMsg bytes]; -} - -- (void) deleteMsg -{ - if(receivedMsg) { - [receivedMsg release]; - msgLength = 0; - } -} - -- (BOOL) isDisconnecting -{ - return disconnecting; -} - -- (BOOL) isReading -{ - return isReading; -} - -- (void) setReading:(BOOL) flag -{ - isReading = flag; -} - -- (BOOL) isTimeout -{ - return timeout; -} - -- (void) setTimeout:(BOOL) flag -{ - timeout = flag; -} - -- (void) startTimerThread -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - // Timer - sleep(1); - - [pool drain]; -} - -- (void) wakeUpMainThreadRunloop:(id)arg -{ - // This method is executed on main thread! - // It doesn't need to do anything actually, just having it run will - // make sure the main thread stops running the runloop -} - - -- (IOBluetoothL2CAPChannel*) openL2CAPChannelWithPSM:(BluetoothL2CAPPSM) psm device:(IOBluetoothDevice*) device delegate:(id) delegate -{ - IOBluetoothL2CAPChannel* channel = nil; - - if ([device openL2CAPChannelSync:&channel withPSM:psm delegate:delegate] != kIOReturnSuccess) - channel = nil; - - return channel; -} - -- (IOReturn) connectToWiimote:(wiimote*) wm -{ -#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE - IOBluetoothDevice* device = (IOBluetoothDevice*) wm->device; -#else - IOBluetoothDevice* device = [IOBluetoothDevice withDeviceRef:wm->device]; -#endif - IOBluetoothL2CAPChannel* outCh = nil; - IOBluetoothL2CAPChannel* inCh = nil; - - if(!device) { - WIIUSE_ERROR("Non existent device or already connected."); - return kIOReturnBadArgument; - } - - outCh = [self openL2CAPChannelWithPSM:WM_OUTPUT_CHANNEL device:device delegate:self]; - if (!outCh) { - WIIUSE_ERROR("Unable to open L2CAP output channel (id %i).", wm->unid); - [device closeConnection]; - return kIOReturnNotOpen; - } -#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE - wm->outputCh = (IOBluetoothL2CAPChannelRef) [outCh retain]; -#else - wm->outputCh = [[outCh retain] getL2CAPChannelRef]; -#endif - usleep(20000); - - inCh = [self openL2CAPChannelWithPSM:WM_INPUT_CHANNEL device:device delegate:self]; - if (!inCh) { - WIIUSE_ERROR("Unable to open L2CAP input channel (id %i).", wm->unid); - [device closeConnection]; - return kIOReturnNotOpen; - } -#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE - wm->inputCh = (IOBluetoothL2CAPChannelRef) [inCh retain]; -#else - wm->inputCh = [[inCh retain] getL2CAPChannelRef]; -#endif - usleep(20000); - - IOBluetoothUserNotification* disconnectNotification = [device registerForDisconnectNotification:self selector:@selector(disconnected:fromDevice:)]; - if(!disconnectNotification) { - WIIUSE_ERROR("Unable to register disconnection handler (id %i).", wm->unid); - [device closeConnection]; - return kIOReturnNotOpen; - } - - // We store the reference to its relative structure (Used for completing the handshake step) - _wm = wm; - - return kIOReturnSuccess; -} - -#pragma mark - -#pragma mark IOBluetoothL2CAPChannel delegates -- (void) disconnected:(IOBluetoothUserNotification*) notification fromDevice:(IOBluetoothDevice*) device -{ - [self deleteMsg]; - [self setReading:NO]; - disconnecting = YES; - - // The wiimote_t struct must be re-initialized due to the disconnection - wiiuse_disconnected(_wm) ; -} - -//*************** HANDLERS FOR WIIUSE_IO_READ FOR MACOSX *******************/ -- (void) l2capChannelData:(IOBluetoothL2CAPChannel*) channel data:(byte *) data length:(NSUInteger) length -{ - // This is done in case the output channel woke up this handler - if(!data || ([channel PSM] == WM_OUTPUT_CHANNEL)) { - return; - } - - // log the received data - #ifdef WITH_WIIUSE_DEBUG - { - printf("[DEBUG] (id %i) RECV: (%x) ", _wm->unid, data[0]); - int x; - for (x = 1; x < length; ++x) - printf("%.2x ", data[x]); - printf("\n"); - } - #endif - - /* - * This is called if we are receiving data before completing - * the handshaking, hence before calling wiiuse_poll - */ - // wiimote handshake - if(WIIMOTE_IS_SET(_wm, WIIMOTE_STATE_HANDSHAKE)) - propagate_event(_wm, data[1], data+2); - - // expansion handshake - if(_wm->expansion_state != 0) - propagate_event(_wm, data[1], data+2); - - receivedMsg = [[NSData dataWithBytes:data length:length] retain]; - msgLength = length; - - // This is done when a message is successfully received. Stop the main loop after reading - [self setReading:NO]; -} - -- (unsigned int) getMsgLength -{ - return msgLength; -} - -- (void) l2capChannelReconfigured:(IOBluetoothL2CAPChannel*) l2capChannel -{ - //NSLog(@"l2capChannelReconfigured"); -} - -- (void) l2capChannelWriteComplete:(IOBluetoothL2CAPChannel*) l2capChannel refcon:(void*) refcon status:(IOReturn) error -{ - //NSLog(@"l2capChannelWriteComplete"); -} - -- (void) l2capChannelQueueSpaceAvailable:(IOBluetoothL2CAPChannel*) l2capChannel -{ - //NSLog(@"l2capChannelQueueSpaceAvailable"); -} - -- (void) l2capChannelOpenComplete:(IOBluetoothL2CAPChannel*) l2capChannel status:(IOReturn) error -{ - //NSLog(@"l2capChannelOpenComplete (PSM:0x%x)", [l2capChannel getPSM]); -} - - -@end - -#pragma mark - -#pragma mark Wiiuse -/** - * @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. - * - * This function is defined in wiiuse.h - */ -int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) -{ - int found_wiimotes = 0; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - WiiSearch* search = [[WiiSearch alloc] init]; - [search setWiimoteStruct:wm]; - - if(timeout) { // Single search - [search start:timeout maxWiimotes:max_wiimotes]; - - NSRunLoop *theRL = [NSRunLoop currentRunLoop]; - while ([search isDiscovering] && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); - - found_wiimotes = [search getFoundWiimotes]; - } - else { // Unlimited search - found_wiimotes = 0; - while(!found_wiimotes) { - [search start:timeout maxWiimotes:max_wiimotes]; - - NSRunLoop *theRL = [NSRunLoop currentRunLoop]; - while ([search isDiscovering] && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); - - found_wiimotes = [search getFoundWiimotes]; - } - } - - WIIUSE_INFO("Found %i Wiimote device(s).", found_wiimotes); - - [search release]; - [pool drain]; - - return found_wiimotes; -} - - -//*************** HANDLERS FOR WIIUSE_DISCONNECT FOR MACOSX *******************/ -/** - * @brief Disconnect a wiimote. - * - * @param wm Pointer to a wiimote_t structure. - * - * @see wiic_connect() - * - * Note that this will not free the wiimote structure. - * - * This function is defined in wiiuse.h - */ -void wiiuse_disconnect(struct wiimote_t* wm) -{ - IOReturn error; - - if (!wm || !WIIMOTE_IS_CONNECTED(wm)) - return; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // Input Channel - if(wm->inputCh) { -#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE - IOBluetoothL2CAPChannel* inCh = (IOBluetoothL2CAPChannel*) wm->inputCh; -#else - IOBluetoothL2CAPChannel* inCh = [IOBluetoothL2CAPChannel withL2CAPChannelRef:wm->inputCh]; -#endif - error = [inCh closeChannel]; - [inCh setDelegate:nil]; - if(error != kIOReturnSuccess) - WIIUSE_ERROR("Unable to close input channel (id %i).", wm->unid); - usleep(10000); - [inCh release]; - inCh = nil; - wm->inputCh = 0; - } - - // Output Channel - if(wm->outputCh) { -#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE - IOBluetoothL2CAPChannel* outCh = (IOBluetoothL2CAPChannel*) wm->outputCh; -#else - IOBluetoothL2CAPChannel* outCh = [IOBluetoothL2CAPChannel withL2CAPChannelRef:wm->outputCh]; -#endif - error = [outCh closeChannel]; - [outCh setDelegate:nil]; - if(error != kIOReturnSuccess) - WIIUSE_ERROR("Unable to close output channel (id %i).", wm->unid); - usleep(10000); - [outCh release]; - outCh = nil; - wm->outputCh = 0; - } - - // Device - if(wm->device) { -#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE - IOBluetoothDevice* device = (IOBluetoothDevice*) wm->device; -#else - IOBluetoothDevice* device = [IOBluetoothDevice withDeviceRef:wm->device]; -#endif - error = [device closeConnection]; - - if(error != kIOReturnSuccess) - WIIUSE_ERROR("Unable to close the device connection (id %i).", wm->unid); - usleep(10000); - [device release]; - device = nil; - wm->device = 0; - } - - [pool drain]; - - wm->event = WIIUSE_NONE; - - WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); - WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE); -} - -/** - * @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 wiic_find(). - * - * @return 1 on success, 0 on failure - * This function is defined in io_mac.h - */ -static int wiiuse_connect_single(struct wiimote_t* wm, char* address) -{ - // Skip if already connected or device not found - if(!wm || WIIMOTE_IS_CONNECTED(wm) || wm->device == 0) { - WIIUSE_ERROR("Non existent device or already connected."); - return 0; - } - - // Convert the IP address - // FIXME - see if it is possible - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - WiiConnect* connect = [[[WiiConnect alloc] init] autorelease]; - if([connect connectToWiimote:wm] == kIOReturnSuccess) { - WIIUSE_INFO("Connected to wiimote [id %i].", wm->unid); - // This is stored to retrieve incoming data - wm->connectionHandler = (void*)([connect retain]); - - // Do the handshake - WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); - wiiuse_handshake(wm, NULL, 0); - wiiuse_set_report_type(wm); - - [pool drain]; - } - else { - [pool drain]; - return 0; - } - - return 1; -} - -/** - * @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 wiic_find() - * @see wiic_connect_single() - * @see wiic_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 wiic_find() function, but can also be set manually. - * This function is defined in wiiuse.h - */ -int wiiuse_connect(struct wiimote_t** wm, int wiimotes) -{ - int connected = 0; - int i = 0; - - for (; i < wiimotes; ++i) { - if(!(wm[i])) { - WIIUSE_ERROR("Trying to connect more Wiimotes than initialized"); - return 0; - } - - 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 Load Wii devices registered in the wiimotes.config file. - * - * @param wm An array of wiimote_t structures. - * - * @return The number of wiimotes successfully loaded. - * - * @see wiic_find() - * @see wiic_connect() - * @see wiic_connect_single() - * @see wiic_disconnect() - * - * From version 0.53, it is possible to register the MAC address of your - * Wii devices. This allows to automatically load them, without waiting for any - * search timeout. To register a new device, go to: /.wiic/ and - * edit the file wiimotes.config, by adding the MAC address of the device - * you want to register (one line per MAC address). - * This function seems useful but it's not implemented in wiiuse - * TODO: Erase or implement elsewhere - */ -int wiiuse_load(struct wiimote_t** wm) -{ - int loaded = 0; - int i = 0; - char str[200]; - char configPath[100]; - char* tmp = 0; - - // Retrieve the HOME environment variable - tmp = getenv("HOME"); - strcpy(configPath,tmp); - strncat(configPath,"/.wiic/wiimotes.config",22); - - // Open the config file - FILE* fd = 0; - fd = fopen(configPath,"r"); - if(!fd) - return loaded; - - // Read line by line - while(fgets(str,sizeof(str),fd) != NULL && loaded < 1) { - int len = strlen(str)-1; - if(str[len] == '\n') - str[len] = 0; - loaded++; - } - - // We initialize the device structure - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - for (; i < loaded; ++i) { - NSString* string = [NSString stringWithCString:str encoding:[NSString defaultCStringEncoding]]; - BluetoothDeviceAddress deviceAddr; - IOBluetoothNSStringToDeviceAddress(string, &deviceAddr); -#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE - IOBluetoothDevice* device = [IOBluetoothDevice deviceWithAddress:&deviceAddr]; - wm[i]->device = (IOBluetoothDeviceRef) [device retain]; -#else - IOBluetoothDevice* device = [IOBluetoothDevice withAddress:&deviceAddr]; - wm[i]->device = [[device retain] getDeviceRef]; -#endif - wm[i]->address = (CFStringRef) [IOBluetoothNSStringFromDeviceAddress([device getAddress]) retain]; - WIIMOTE_ENABLE_STATE(wm[i], WIIMOTE_STATE_DEV_FOUND); - WIIUSE_INFO("Loaded Wiimote (%s) [id %i].",CFStringGetCStringPtr(wm[i]->address, kCFStringEncodingMacRoman),wm[i]->unid); - } - [pool drain]; - - return loaded; -} - -// Defined in io.h -int wiiuse_io_read(struct wiimote_t* wm) -{ - 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; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - WiiConnect* deviceHandler = 0; - deviceHandler = (WiiConnect*)(wm->connectionHandler); - - /* If this wiimote is disconnecting, skip it */ - if (!deviceHandler || [deviceHandler isDisconnecting]) { - [pool drain]; - return 0; - } - - // Run the main loop to get bt data - [deviceHandler setReading:YES]; - [deviceHandler setTimeout:NO]; - - // We start the thread which manages the timeout to implement a non-blocking read - [NSThread detachNewThreadSelector:@selector(startTimerThread) toTarget:deviceHandler withObject:nil]; - - NSRunLoop *theRL = [NSRunLoop currentRunLoop]; - // Two possible events: we receive and incoming message or there is a timeout - while([deviceHandler isReading] && ![deviceHandler isTimeout]) { - NSAutoreleasePool *pool_loop = [[NSAutoreleasePool alloc] init]; // This is used for fast release of NSDate, otherwise it leaks - [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; - [pool_loop drain]; - } - - // In this case we have no incoming data (TIMEOUT) - if([deviceHandler isTimeout]) { - [pool drain]; - return 0; - } - - if(!(wm->connectionHandler)) { - WIIUSE_ERROR("Unable to find the connection handler (id %i).", wm->unid); - [pool drain]; - return 0; - } - - // Read next message - byte* buffer = 0; - unsigned int length = 0; - if(![deviceHandler isDisconnecting]) { - buffer = [deviceHandler getNextMsg]; - length = [deviceHandler getMsgLength]; - } - - if(!buffer || !length) { - [pool drain]; - return 0; - } - - // Forward to WiiC - if(length < sizeof(wm->event_buf)) - memcpy(wm->event_buf,buffer,length); - else { - WIIUSE_DEBUG("Received data are more than the buffer.... strange! (id %i)", wm->unid); - memcpy(wm->event_buf,buffer,sizeof(wm->event_buf)); - } - - // Release the consumed message - [deviceHandler deleteMsg]; - - [pool drain]; - - return 1; -} - -// Defined in io.h -int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) -{ - unsigned int length = (unsigned int)len; - - // Small check before writing - if(!wm || !(wm->outputCh)) { - WIIUSE_ERROR("Attempt to write over non-existent channel (id %i).", wm->unid); - perror("Error Details"); - return 0; - } - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - -#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE - IOBluetoothL2CAPChannel* channel = (IOBluetoothL2CAPChannel*) wm->outputCh; -#else - IOBluetoothL2CAPChannel* channel = [IOBluetoothL2CAPChannel withL2CAPChannelRef:wm->outputCh]; -#endif - IOReturn error = [channel writeSync:buf length:length]; - - if (error != kIOReturnSuccess) - { - WIIUSE_ERROR("Unable to write over the output channel (id %i).", wm->unid); - WIIUSE_INFO("Attempting to reopen the output channel (id %i).", wm->unid); - - IOReturn error = [channel closeChannel]; - if (error != kIOReturnSuccess) - WIIUSE_ERROR("Unable to close the output channel (id %i).", wm->unid); - [channel setDelegate:nil]; - usleep(10000); - [channel release]; - wm->outputCh = 0; - - WiiConnect* connect = (WiiConnect*)(wm->connectionHandler); - -#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE - IOBluetoothDevice* device = (IOBluetoothDevice*) wm->device; -#else - IOBluetoothDevice* device = [IOBluetoothDevice withDeviceRef:wm->device]; -#endif - channel = [connect openL2CAPChannelWithPSM:WM_OUTPUT_CHANNEL device:device delegate:connect]; - if (!channel) { - WIIUSE_ERROR("Unable to open L2CAP output channel (id %i).", wm->unid); - [device closeConnection]; - return kIOReturnNotOpen; - } -#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE - wm->outputCh = (IOBluetoothL2CAPChannelRef) [channel retain]; -#else - wm->outputCh = [[channel retain] getL2CAPChannelRef]; -#endif - usleep(20000); - - WIIUSE_INFO("Attempting to write again through the output channel (id %i).", wm->unid); - error = [channel writeSync:buf length:length]; - if (error != kIOReturnSuccess) - { - WIIUSE_ERROR("Unable to write again over the output channel (id %i).", wm->unid); - } - } - - usleep(10000); - - [pool drain]; - - return (error == kIOReturnSuccess ? len : 0); -} - -void wiiuse_init_platform_fields(struct wiimote_t* wm) -{ - wm->device = nil; - wm->address = nil; - wm->inputCh = nil; - wm->outputCh = 0; - wm->disconnectionRef = nil; - wm->connectionHandler = NULL; - memset (wm->bdaddr_str,'\0',18); -} - -void wiiuse_cleanup_platform_fields(struct wiimote_t* wm) -{ - /* TODO isn't this already done in wiiuse_disconnect ? */ - wm->device = nil; - wm->address = nil; - wm->inputCh = nil; - wm->outputCh = 0; - wm->disconnectionRef = nil; - wm->connectionHandler = NULL; - memset (wm->bdaddr_str,'\0',18); -} - -#endif +#endif // __APPLE__ diff --git a/src/io_nix.c b/src/io_nix.c index fb14735..e10602a 100644 --- a/src/io_nix.c +++ b/src/io_nix.c @@ -47,25 +47,9 @@ #include /* for close, write */ #include -static int wiiuse_connect_single(struct wiimote_t* wm, char* address); +static int wiiuse_io_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 wiiuse_io_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { int device_id; int device_sock; inquiry_info scan_info_arr[128]; @@ -133,22 +117,10 @@ int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { /** - * @brief Connect to a wiimote or wiimotes once an address is known. - * - * @param wm An array of wiimote_t structures. - * @param wiimotes The number of wiimote structures in \a wm. - * - * @return The number of wiimotes that successfully connected. - * - * @see wiiuse_find() - * @see wiiuse_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. + * @see wiiuse_connect() + * @see wiiuse_io_connect_single() */ -int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { +int wiiuse_io_connect(struct wiimote_t** wm, int wiimotes) { int connected = 0; int i = 0; @@ -174,7 +146,7 @@ int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { * * @return 1 on success, 0 on failure */ -static int wiiuse_connect_single(struct wiimote_t* wm, char* address) { +static int wiiuse_io_connect_single(struct wiimote_t* wm, char* address) { struct sockaddr_l2 addr; memset(&addr, 0, sizeof (addr)); @@ -241,17 +213,7 @@ static int wiiuse_connect_single(struct wiimote_t* wm, char* address) { 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) { +void wiiuse_io_disconnect(struct wiimote_t* wm) { if (!wm || WIIMOTE_IS_CONNECTED(wm)) return; diff --git a/src/io_platform.h b/src/io_platform.h new file mode 100644 index 0000000..167a64c --- /dev/null +++ b/src/io_platform.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 Handles device I/O. + */ + +#ifndef IO_PLATFORM_H_INCLUDED +#define IO_PLATFORM_H_INCLUDED + +#include "wiiuse_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @defgroup internal_io Internal: Platform-specific Device I/O */ +/** @{ */ +void wiiuse_init_platform_fields(struct wiimote_t* wm); +void wiiuse_cleanup_platform_fields(struct wiimote_t* wm); + +int wiiuse_io_find(struct wiimote_t** wm, int max_wiimotes, int timeout); + +int wiiuse_io_connect(struct wiimote_t** wm, int wiimotes); +void wiiuse_io_disconnect(struct wiimote_t* wm); + +int wiiuse_io_read(struct wiimote_t* wm); +int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len); +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* IO_PLATFORM_H_INCLUDED */ diff --git a/src/io_win.c b/src/io_win.c index 0ad88e3..1892b29 100644 --- a/src/io_win.c +++ b/src/io_win.c @@ -52,7 +52,7 @@ extern "C" { # endif #endif -int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { +int wiiuse_io_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { GUID device_id; HANDLE dev; HDEVINFO device_info; @@ -146,7 +146,7 @@ int wiiuse_find(struct wiimote_t** wm, int max_wiimotes, int timeout) { } -int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { +int wiiuse_io_connect(struct wiimote_t** wm, int wiimotes) { int connected = 0; int i = 0; @@ -161,7 +161,7 @@ int wiiuse_connect(struct wiimote_t** wm, int wiimotes) { } -void wiiuse_disconnect(struct wiimote_t* wm) { +void wiiuse_io_disconnect(struct wiimote_t* wm) { if (!wm || WIIMOTE_IS_CONNECTED(wm)) return; diff --git a/src/wiiuse.h b/src/wiiuse.h index 0c5e79f..85af147 100644 --- a/src/wiiuse.h +++ b/src/wiiuse.h @@ -101,8 +101,6 @@ #endif #ifdef WIIUSE_MAC /* mac */ - #include /*CFRunLoops and CFNumberRef in Bluetooth classes*/ - #include /*IOBluetoothDeviceRef and IOBluetoothL2CAPChannelRef*/ #endif #ifndef WCONST @@ -722,13 +720,7 @@ typedef struct wiimote_t { #ifdef WIIUSE_MAC /** @name Mac OS X-specific members */ - /** @{ */ - WCONST IOBluetoothDeviceRef device; /** Device reference object */ - WCONST CFStringRef address; /** MacOS-like device address string */ - WCONST IOBluetoothL2CAPChannelRef inputCh; /** Input L2CAP channel */ - WCONST IOBluetoothL2CAPChannelRef outputCh; /** Output L2CAP channel */ - WCONST IOBluetoothUserNotificationRef disconnectionRef; /** Disconnection Notification Reference **/ - WCONST void* connectionHandler; /** Wiimote connection handler for MACOSX **/ + /** @{ */ /** @} */ #endif @@ -896,7 +888,7 @@ 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 */ +/* io.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);