diff --git a/src/os_mac/os_mac.h b/src/os_mac/os_mac.h index 15ceef1..7537f7b 100644 --- a/src/os_mac/os_mac.h +++ b/src/os_mac/os_mac.h @@ -51,7 +51,7 @@ IOBluetoothUserNotification* disconnectNotification; - NSMutableArray* receivedData; // a queue os NSData* + NSMutableArray* receivedData; // a queue of NSObject* NSLock* receivedDataLock; } @@ -66,4 +66,20 @@ @end +@protocol WiiuseReceivedMessage +- (int) applyToStruct: (wiimote*) wm; // <0: not copied, 0: copied empty, >0: copied +@end + +@interface WiiuseReceivedData : NSObject { + NSData* data; +} +- (id) initWithBytes: (void*) bytes length: (NSUInteger) length; +- (id) initWithData: (NSData*) data; +@end + +@interface WiiuseDisconnectionMessage : NSObject { +} +@end + + #endif // __APPLE__ diff --git a/src/os_mac/os_mac.m b/src/os_mac/os_mac.m index 337d4c0..c1d235a 100644 --- a/src/os_mac/os_mac.m +++ b/src/os_mac/os_mac.m @@ -142,32 +142,33 @@ - (void) disconnected:(IOBluetoothUserNotification*) notification fromDevice:(IOBluetoothDevice*) device { - wiiuse_disconnected(wm); + WiiuseDisconnectionMessage* message = [[WiiuseDisconnectionMessage alloc] init]; + [receivedDataLock lock]; + [receivedData addObject:message]; + [receivedDataLock unlock]; + [message release]; } #pragma mark read, write +// <0: nothing received, else: length of data received (can be 0 in case of disconnection message) - (int) checkForAvailableData { - unsigned int length = 0; + int result = -1; [receivedDataLock lock]; if([receivedData count]) { - // pop first item from queue - NSData* firstData = [receivedData objectAtIndex:0]; - [receivedData removeObjectAtIndex:0]; - - byte* data = (byte*) [firstData bytes]; - length = [firstData length]; - - // forward event data to C struct - memcpy(wm->event_buf, data, sizeof(wm->event_buf)); + // look at first item in queue + NSObject* firstMessage = [receivedData objectAtIndex:0]; + result = [firstMessage applyToStruct:wm]; + if(result >= 0) + [receivedData removeObjectAtIndex:0]; } [receivedDataLock unlock]; - return length; + return result; } -- (void) waitForInclomingData: (NSTimeInterval) duration { +- (void) waitForIncomingData: (NSTimeInterval) duration { NSDate* timeoutDate = [NSDate dateWithTimeIntervalSinceNow: duration]; NSRunLoop *theRL = [NSRunLoop currentRunLoop]; while (true) { @@ -193,18 +194,19 @@ } } +// result = length of data copied to event buffer - (int) read { // is there already some data to read? int result = [self checkForAvailableData]; - if(!result) { - // wait a short amount of time, until data becomes available - [self waitForInclomingData:1]; + if(result < 0) { + // wait a short amount of time, until data becomes available or a timeoutis reached + [self waitForIncomingData:1]; // check again result = [self checkForAvailableData]; } - return result; + return result >= 0 ? result : 0; } - (int) writeBuffer: (byte*) buffer length: (NSUInteger) length { @@ -266,7 +268,7 @@ } // copy the data into the buffer - NSData* newData = [[NSData alloc] initWithBytes:data length:length]; + WiiuseReceivedData* newData = [[WiiuseReceivedData alloc] initWithBytes: data length: length]; [receivedDataLock lock]; [receivedData addObject: newData]; [receivedDataLock unlock]; @@ -275,4 +277,52 @@ @end +#pragma mark - +#pragma mark WiiuseReceivedMessage + +@implementation WiiuseReceivedData + +- (id) initWithData:(NSData *)data_ { + self = [super init]; + if (self) { + data = [data_ retain]; + } + return self; +} +- (id) initWithBytes: (void*) bytes length: (NSUInteger) length { + NSData* data_ = [[NSData alloc] initWithBytes:bytes length:length]; + id result = [self initWithData: data_]; + [data_ release]; + return result; +} + +- (void) dealloc { + [data release]; + [super dealloc]; +} + +- (int) applyToStruct:(wiimote *)wm { + byte* bytes = (byte*) [data bytes]; + NSUInteger length = [data length]; + if(length > sizeof(wm->event_buf)) { + WIIUSE_WARNING("Received data was longer than event buffer. Dropping excess bytes."); + length = sizeof(wm->event_buf); + } + memcpy(wm->event_buf, bytes, length); + + return length; +} + +@end + +@implementation WiiuseDisconnectionMessage + +- (int) applyToStruct:(wiimote *)wm { + wiiuse_disconnected(wm); + return 0; +} + +@end + + #endif // __APPLE__ diff --git a/src/os_mac/os_mac_interface.m b/src/os_mac/os_mac_interface.m index c32568d..c6ce72f 100644 --- a/src/os_mac/os_mac_interface.m +++ b/src/os_mac/os_mac_interface.m @@ -149,13 +149,14 @@ int wiiuse_os_poll(struct wiimote_t** wm, int wiimotes) { if (wiiuse_os_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]); } + + evnt += (wm[i]->event != WIIUSE_NONE); } return evnt; diff --git a/src/wiiuse.c b/src/wiiuse.c index 80dbf10..f947a59 100644 --- a/src/wiiuse.c +++ b/src/wiiuse.c @@ -85,6 +85,7 @@ void wiiuse_cleanup(struct wiimote_t** wm, int wiimotes) { for (; i < wiimotes; ++i) { wiiuse_disconnect(wm[i]); + wiiuse_cleanup_platform_fields(wm[i]); free(wm[i]); } @@ -177,8 +178,6 @@ void wiiuse_disconnected(struct wiimote_t* wm) { WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_CONNECTED); /* reset a bunch of stuff */ - wiiuse_cleanup_platform_fields(wm); - wm->leds = 0; wm->state = WIIMOTE_INIT_STATES; wm->read_req = NULL;