implement wiiuse_os_connect for mac

This commit is contained in:
Lysann Schlegel
2012-11-10 18:31:00 +01:00
parent a154eb5536
commit 7d9c82f604
4 changed files with 188 additions and 9 deletions

View File

@@ -39,8 +39,6 @@
#import "events.h"
#import "os.h"
#define BLUETOOTH_VERSION_USE_CURRENT
#import <IOBluetooth/IOBluetoothUtilities.h>
#import <IOBluetooth/objc/IOBluetoothDevice.h>
#import <IOBluetooth/objc/IOBluetoothHostController.h>
@@ -51,8 +49,78 @@
#pragma mark -
#pragma mark connect, disconnect
/**
* @brief Connect to a wiimote with a known address.
*
* @param wm Pointer to a wiimote_t structure.
*
* @see wiimote_os_connect()
* @see wiimote_os_find()
*
* @return 1 on success, 0 on failure
*/
static short wiiuse_os_connect_single(struct wiimote_t* wm) {
// Skip if already connected or device not found
if(!wm) {
WIIUSE_ERROR("No Wiimote given.");
return 0;
} else if(wm && (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_DEV_FOUND) || wm->device == NULL)) {
WIIUSE_ERROR("Tried to connect Wiimote without an address.");
return 0;
} else if(WIIMOTE_IS_CONNECTED(wm)) {
WIIUSE_WARNING("Wiimote [id %i] is already connected.", wm->unid);
return 1;
}
WIIUSE_DEBUG("Connecting to Wiimote [id %i].", wm->unid);
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
short result = 0;
// connect
WiiuseWiimote* objc_wm = [[WiiuseWiimote alloc] initWithPtr: wm];
if([objc_wm connect] == kIOReturnSuccess) {
WIIUSE_INFO("Connected to Wiimote [id %i].", wm->unid);
// save the connect structure to retrieve data later on
wm->objc_wm = (void*)objc_wm;
// save the connection status
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_CONNECTED);
// Do the handshake
wiiuse_handshake(wm, NULL, 0);
wiiuse_set_report_type(wm);
result = 1;
} else {
[objc_wm release];
}
[pool drain];
return result;
}
int wiiuse_os_connect(struct wiimote_t** wm, int wiimotes) {
return 0;
int connected = 0;
int i;
for (i = 0; i < wiimotes; ++i) {
if(wm[i] == NULL) {
WIIUSE_ERROR("Trying to connect to non-initialized Wiimote.");
break;
}
if (!WIIMOTE_IS_SET(wm[i], WIIMOTE_STATE_DEV_FOUND) || !wm[i]->device) {
// If the device is not set, skip it
continue;
}
if (wiiuse_os_connect_single(wm[i]))
++connected;
}
return connected;
}
void wiiuse_os_disconnect(struct wiimote_t* wm) {
@@ -87,11 +155,80 @@ int wiiuse_os_write(struct wiimote_t* wm, byte* buf, int len) {
void wiiuse_init_platform_fields(struct wiimote_t* wm) {
wm->device = NULL;
wm->objc_wm = NULL;
wm->controlChannel = NULL;
wm->interruptChannel = NULL;
}
void wiiuse_cleanup_platform_fields(struct wiimote_t* wm) {
[WIIUSE_IOBluetoothDeviceRef_to_IOBluetoothDevice(wm->device) release];
wm->device = NULL;
[((WiiuseWiimote*) wm->objc_wm) release];
wm->objc_wm = NULL;
}
#pragma mark -
#pragma mark WiiuseWiimote
@implementation WiiuseWiimote
- (id) initWithPtr: (wiimote*) wm_ {
self = [super init];
if(self) {
wm = wm_;
disconnectNotification = nil;
}
return self;
}
- (void) dealloc {
wm = NULL;
[disconnectNotification release];
disconnectNotification = nil;
[super dealloc];
}
- (IOReturn) connect {
IOBluetoothDevice* device = WIIUSE_IOBluetoothDeviceRef_to_IOBluetoothDevice(wm->device);
if(!device) {
WIIUSE_ERROR("Missing device.");
return kIOReturnBadArgument;
}
// open channels
IOBluetoothL2CAPChannel* controlChannel = nil, *interruptChannel = nil;
if ([device openL2CAPChannelSync:&controlChannel withPSM:WM_OUTPUT_CHANNEL delegate:self] != kIOReturnSuccess) {
WIIUSE_ERROR("Unable to open L2CAP control channel [id %i].", wm->unid);
[device closeConnection];
return kIOReturnNotOpen;
} else if([device openL2CAPChannelSync:&interruptChannel withPSM:WM_INPUT_CHANNEL delegate:self] != kIOReturnSuccess) {
WIIUSE_ERROR("Unable to open L2CAP interrupt channel [id %i].", wm->unid);
[controlChannel closeChannel];
[device closeConnection];
return kIOReturnNotOpen;
}
// register for device disconnection
disconnectNotification = [device registerForDisconnectNotification:self selector:@selector(disconnected:fromDevice:)];
if(!disconnectNotification) {
WIIUSE_ERROR("Unable to register disconnection handler [id %i].", wm->unid);
[interruptChannel closeChannel];
[controlChannel closeChannel];
[device closeConnection];
return kIOReturnNotOpen;
}
// retain channels, and save them to the C struct
[controlChannel retain]; [interruptChannel retain];
wm->controlChannel = WIIUSE_IOBluetoothL2CAPChannel_to_IOBluetoothL2CAPChannelRef(controlChannel);
wm->interruptChannel = WIIUSE_IOBluetoothL2CAPChannel_to_IOBluetoothL2CAPChannelRef(interruptChannel);
return kIOReturnSuccess;
}
@end
#endif // __APPLE__

View File

@@ -34,7 +34,12 @@
#ifdef __APPLE__
#define BLUETOOTH_VERSION_USE_CURRENT
#import <IOBluetooth/objc/IOBluetoothDevice.h>
#import <IOBluetooth/objc/IOBluetoothL2CAPChannel.h>
#import "../wiiuse_internal.h"
#if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
@@ -62,5 +67,34 @@
[IOBluetoothDevice withDeviceRef: (ref)]
#endif
// WIIUSE_IOBluetoothL2CAPChannel_to_IOBluetoothL2CAPChannelRef
#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE
#define WIIUSE_IOBluetoothL2CAPChannel_to_IOBluetoothL2CAPChannelRef(channel) \
((IOBluetoothL2CAPChannelRef) (channel))
#else
#define WIIUSE_IOBluetoothL2CAPChannel_to_IOBluetoothL2CAPChannelRef(channel) \
[(channel) getL2CAPChannelRef]
#endif
// WIIUSE_IOBluetoothL2CAPChannelRef_to_IOBluetoothL2CAPChannel
#if WIIUSE_MAC_OS_X_VERSION_10_7_OR_ABOVE
#define WIIUSE_IOBluetoothL2CAPChannelRef_to_IOBluetoothL2CAPChannel(ref) \
((IOBluetoothL2CAPChannel*) (ref))
#else
#define WIIUSE_IOBluetoothL2CAPChannelRef_to_IOBluetoothL2CAPChannel(ref) \
[IOBluetoothL2CAPChannel withChanneleRef: (ref)]
#endif
@interface WiiuseWiimote : NSObject<IOBluetoothL2CAPChannelDelegate> {
wiimote* wm; // reference to the C wiimote struct
IOBluetoothUserNotification* disconnectNotification;
}
- (id) initWithPtr: (wiimote*) wm;
- (IOReturn) connect;
@end
#endif // __APPLE__

View File

@@ -39,8 +39,6 @@
#import "../events.h"
#import "../os.h"
#define BLUETOOTH_VERSION_USE_CURRENT
#import <IOBluetooth/IOBluetoothUtilities.h>
#import <IOBluetooth/objc/IOBluetoothDevice.h>
#import <IOBluetooth/objc/IOBluetoothHostController.h>
@@ -48,7 +46,7 @@
#pragma mark -
#pragma mark find
#pragma mark WiiuseDeviceInquiry
@interface WiiuseDeviceInquiry : NSObject<IOBluetoothDeviceInquiryDelegate> {
wiimote** wiimotes;
@@ -122,6 +120,10 @@
}
- (NSUInteger) collectResultsOf: (IOBluetoothDeviceInquiry*) inquiry {
// stop the inquiry
if(![inquiry stop])
WIIUSE_ERROR("Unable to stop bluetooth device inquiry.");
// read found device information
NSArray* devices = [inquiry foundDevices];
for(NSUInteger i = 0; i < [devices count]; i++) {
@@ -168,6 +170,8 @@
return result;
}
#pragma mark IOBluetoothDeviceInquiryDelegate
- (void) deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry *) inquiry device:(IOBluetoothDevice *) device {
WIIUSE_DEBUG("Found a wiimote");
@@ -175,8 +179,6 @@
_foundDevices++;
if(_foundDevices >= maxDevices) {
// reached maximum number of devices
if(![inquiry stop])
WIIUSE_ERROR("Unable to stop bluetooth device inquiry.");
_inquiryComplete = YES;
}
}
@@ -196,6 +198,9 @@
@end
#pragma mark -
#pragma mark public interface
int wiiuse_os_find(struct wiimote_t** wm, int max_wiimotes, int timeout) {
int result;

View File

@@ -723,7 +723,10 @@ typedef struct wiimote_t {
#ifdef WIIUSE_MAC
/** @name Mac OS X-specific members */
/** @{ */
WCONST IOBluetoothDeviceRef device; /** Device reference object */
WCONST IOBluetoothDeviceRef device; /** Device reference */
WCONST void* objc_wm; /** WiiuseWiimote* as opaque pointer */
WCONST IOBluetoothL2CAPChannelRef controlChannel; /** control channel reference */
WCONST IOBluetoothL2CAPChannelRef interruptChannel; /** interrupt channel reference */
/** @} */
#endif