ios: First revision of WiiMote support (code borrowed from imame4all)

This commit is contained in:
meancoot 2013-02-26 23:14:27 -05:00
parent d2119b75b1
commit c941caa2ec
19 changed files with 3474 additions and 2 deletions

View File

@ -8,6 +8,11 @@
/* Begin PBXBuildFile section */
96096DD816D1ABAF00BF4499 /* RAModuleInfoList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */; };
9614C6BB16DD7C00000B36EF /* BTDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 9614C6AE16DD7C00000B36EF /* BTDevice.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
9614C6BC16DD7C00000B36EF /* BTInquiryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9614C6B016DD7C00000B36EF /* BTInquiryViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
9614C6BD16DD7C00000B36EF /* libBTstack.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9614C6B816DD7C00000B36EF /* libBTstack.dylib */; };
9614C6BE16DD7C00000B36EF /* WiiMoteHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 9614C6BA16DD7C00000B36EF /* WiiMoteHelper.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
9614C6C116DD7D54000B36EF /* wiimote.c in Sources */ = {isa = PBXBuildFile; fileRef = 9614C6BF16DD7D54000B36EF /* wiimote.c */; };
962979EF16C3EA3E00E6DCE0 /* ioseagl_ctx.c in Sources */ = {isa = PBXBuildFile; fileRef = 962979EE16C3EA3E00E6DCE0 /* ioseagl_ctx.c */; };
962979F616C43B9500E6DCE0 /* ic_dir.png in Resources */ = {isa = PBXBuildFile; fileRef = 962979F416C43B9500E6DCE0 /* ic_dir.png */; };
962979F716C43B9500E6DCE0 /* ic_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 962979F516C43B9500E6DCE0 /* ic_file.png */; };
@ -91,6 +96,21 @@
/* Begin PBXFileReference section */
96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAModuleInfoList.m; sourceTree = "<group>"; };
9614C6AD16DD7C00000B36EF /* BTDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTDevice.h; sourceTree = "<group>"; };
9614C6AE16DD7C00000B36EF /* BTDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTDevice.m; sourceTree = "<group>"; };
9614C6AF16DD7C00000B36EF /* BTInquiryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTInquiryViewController.h; sourceTree = "<group>"; };
9614C6B016DD7C00000B36EF /* BTInquiryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTInquiryViewController.m; sourceTree = "<group>"; };
9614C6B216DD7C00000B36EF /* btstack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = btstack.h; sourceTree = "<group>"; };
9614C6B316DD7C00000B36EF /* hci_cmds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hci_cmds.h; sourceTree = "<group>"; };
9614C6B416DD7C00000B36EF /* linked_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = linked_list.h; sourceTree = "<group>"; };
9614C6B516DD7C00000B36EF /* run_loop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = run_loop.h; sourceTree = "<group>"; };
9614C6B616DD7C00000B36EF /* sdp_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sdp_util.h; sourceTree = "<group>"; };
9614C6B716DD7C00000B36EF /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
9614C6B816DD7C00000B36EF /* libBTstack.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libBTstack.dylib; sourceTree = "<group>"; };
9614C6B916DD7C00000B36EF /* WiiMoteHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WiiMoteHelper.h; sourceTree = "<group>"; };
9614C6BA16DD7C00000B36EF /* WiiMoteHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WiiMoteHelper.m; sourceTree = "<group>"; };
9614C6BF16DD7D54000B36EF /* wiimote.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wiimote.c; sourceTree = "<group>"; };
9614C6C016DD7D54000B36EF /* wiimote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wiimote.h; sourceTree = "<group>"; };
962979EE16C3EA3E00E6DCE0 /* ioseagl_ctx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioseagl_ctx.c; sourceTree = "<group>"; };
962979F416C43B9500E6DCE0 /* ic_dir.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_dir.png; path = "../android/phoenix/res/drawable-xhdpi/ic_dir.png"; sourceTree = "<group>"; };
962979F516C43B9500E6DCE0 /* ic_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_file.png; path = "../android/phoenix/res/drawable-xhdpi/ic_file.png"; sourceTree = "<group>"; };
@ -252,12 +272,43 @@
96AFAE2E16C1D4EA009DE44C /* CoreGraphics.framework in Frameworks */,
96AFAE3016C1D4EA009DE44C /* GLKit.framework in Frameworks */,
96AFAE3216C1D4EA009DE44C /* OpenGLES.framework in Frameworks */,
9614C6BD16DD7C00000B36EF /* libBTstack.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9614C6AC16DD7C00000B36EF /* BTStack */ = {
isa = PBXGroup;
children = (
9614C6B116DD7C00000B36EF /* btstack */,
9614C6AD16DD7C00000B36EF /* BTDevice.h */,
9614C6AE16DD7C00000B36EF /* BTDevice.m */,
9614C6AF16DD7C00000B36EF /* BTInquiryViewController.h */,
9614C6B016DD7C00000B36EF /* BTInquiryViewController.m */,
9614C6B816DD7C00000B36EF /* libBTstack.dylib */,
9614C6B916DD7C00000B36EF /* WiiMoteHelper.h */,
9614C6BA16DD7C00000B36EF /* WiiMoteHelper.m */,
9614C6BF16DD7D54000B36EF /* wiimote.c */,
9614C6C016DD7D54000B36EF /* wiimote.h */,
);
path = BTStack;
sourceTree = "<group>";
};
9614C6B116DD7C00000B36EF /* btstack */ = {
isa = PBXGroup;
children = (
9614C6B216DD7C00000B36EF /* btstack.h */,
9614C6B316DD7C00000B36EF /* hci_cmds.h */,
9614C6B416DD7C00000B36EF /* linked_list.h */,
9614C6B516DD7C00000B36EF /* run_loop.h */,
9614C6B616DD7C00000B36EF /* sdp_util.h */,
9614C6B716DD7C00000B36EF /* utils.h */,
);
path = btstack;
sourceTree = "<group>";
};
96366C6F16CAF62200D64A22 /* settings */ = {
isa = PBXGroup;
children = (
@ -311,6 +362,7 @@
96AFAE3316C1D4EA009DE44C /* RetroArch */ = {
isa = PBXGroup;
children = (
9614C6AC16DD7C00000B36EF /* BTStack */,
96C19C2716D455C600FE8D5A /* Browser */,
96366C6F16CAF62200D64A22 /* settings */,
96AFAE3416C1D4EA009DE44C /* Supporting Files */,
@ -701,6 +753,10 @@
96C19C2916D5A56500FE8D5A /* browser.m in Sources */,
96C19C3016D7045700FE8D5A /* RAConfig.m in Sources */,
965AE29E16D9BF94001D7667 /* ios_input.m in Sources */,
9614C6BB16DD7C00000B36EF /* BTDevice.m in Sources */,
9614C6BC16DD7C00000B36EF /* BTInquiryViewController.m in Sources */,
9614C6BE16DD7C00000B36EF /* WiiMoteHelper.m in Sources */,
9614C6C116DD7D54000B36EF /* wiimote.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -822,6 +878,7 @@
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)\"",
"\"$(SRCROOT)/RetroArch/BTStack\"",
);
OTHER_CFLAGS = (
"-DHAVE_RARCH_MAIN_WRAP",
@ -858,6 +915,7 @@
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SRCROOT)\"",
"\"$(SRCROOT)/RetroArch/BTStack\"",
);
OTHER_CFLAGS = (
"-DNS_BLOCK_ASSERTIONS=1",

View File

@ -0,0 +1,83 @@
/*
* Copyright (C) 2009 by Matthias Ringwald
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
//
// BTDevice.h
// BT-Keyboard
//
// Created by Matthias Ringwald on 3/30/09.
//
#import <Foundation/Foundation.h>
#include "btstack/utils.h"
#define kCODHID 0x2540
#define kCODZeeMote 0x584
#define kCODInvalid 0xffff
typedef enum {
kBluetoothDeviceTypeGeneric = 0,
kBluetoothDeviceTypeHID,
kBluetoothDeviceTypeMobilePhone,
kBluetoothDeviceTypeSmartPhone,
kBluetoothDeviceTypeZeeMote,
} BluetoothDeviceType;
typedef enum {
kBluetoothConnectionNotConnected = 0,
kBluetoothConnectionRemoteName,
kBluetoothConnectionConnecting,
kBluetoothConnectionConnected
} BluetoothConnectionState;
@interface BTDevice : NSObject {
bd_addr_t address;
NSString * name;
uint8_t pageScanRepetitionMode;
uint16_t clockOffset;
uint32_t classOfDevice;
BluetoothConnectionState connectionState;
}
- (void) setAddress:(bd_addr_t *)addr;
- (bd_addr_t *) address;
- (NSString *) toString;
+ (NSString *) stringForAddress:(bd_addr_t *) address;
@property (readonly) BluetoothDeviceType deviceType;
@property (readonly) NSString * nameOrAddress;
@property (nonatomic, copy) NSString * name;
@property (nonatomic, assign) uint32_t classOfDevice;
@property (nonatomic, assign) uint16_t clockOffset;
@property (nonatomic, assign) uint8_t pageScanRepetitionMode;
@property (nonatomic, assign) BluetoothConnectionState connectionState;
@end

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2009 by Matthias Ringwald
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
//
// BTDevice.m
//
// Created by Matthias Ringwald on 3/30/09.
//
#import "BTDevice.h"
@implementation BTDevice
@synthesize name;
@synthesize classOfDevice;
@synthesize connectionState;
@synthesize pageScanRepetitionMode;
@synthesize clockOffset;
- (BTDevice *)init {
name = NULL;
bzero(&address, 6);
classOfDevice = kCODInvalid;
connectionState = kBluetoothConnectionNotConnected;
return self;
}
- (void) setAddress:(bd_addr_t *)newAddr{
BD_ADDR_COPY( &address, newAddr);
}
- (bd_addr_t *) address{
return &address;
}
+ (NSString *) stringForAddress:(bd_addr_t *) address {
uint8_t * addr = (uint8_t*) address;
return [NSString stringWithFormat:@"%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2],
addr[3], addr[4], addr[5]];
}
- (NSString *) nameOrAddress{
if (name) return name;
return [BTDevice stringForAddress:&address];
}
- (BluetoothDeviceType) deviceType{
switch (classOfDevice) {
case kCODHID:
return kBluetoothDeviceTypeHID;
case kCODZeeMote:
return kBluetoothDeviceTypeZeeMote;
default:
return kBluetoothDeviceTypeGeneric;
}
}
- (NSString *) toString{
return [NSString stringWithFormat:@"Device addr %@ name %@ COD %x", [BTDevice stringForAddress:&address], name, classOfDevice];
}
- (void)dealloc {
[name release];
[super dealloc];
}
@end

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2009 by Matthias Ringwald
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
//
// BTInquiryViewController.h
//
// Created by Matthias Ringwald on 10/8/09.
//
#import <UIKit/UIKit.h>
#include "btstack/hci_cmds.h" // for HCI_STATE
#include "btstack/utils.h"
@class BTDevice;
@protocol BTInquiryDelegate;
typedef enum {
kInquiryInactive,
kInquiryActive,
kInquiryRemoteName
} InquiryState;
@interface BTInquiryViewController : UITableViewController
{
NSMutableArray *devices;
HCI_STATE bluetoothState;
InquiryState inquiryState;
UIActivityIndicatorView *deviceActivity;
UIActivityIndicatorView *bluetoothActivity;
UIFont * deviceNameFont;
UIFont * macAddressFont;
id<BTInquiryDelegate> delegate;
bool allowSelection;
bool showIcons;
// hacks
bool stopRemoteNameGathering;
bool restartInquiry;
BTDevice *remoteNameDevice; // device for which remote name request is pending
BTDevice *remoteDevice; // device for which connection is pending
BTDevice *connectedDevice; // device to which we're connected
bool notifyDelegateOnInquiryStopped;
}
- (void) startInquiry;
- (void) stopInquiry;
- (void) showConnecting:(BTDevice *) device;
- (void) showConnected:(BTDevice *) device;
- (void) removeDeviceForAddress:(bd_addr_t *)addr;
@property (nonatomic, assign) bool allowSelection;
@property (nonatomic, assign) bool showIcons;
@property (nonatomic, retain) NSMutableArray *devices;
@property (nonatomic, retain) id<BTInquiryDelegate> delegate;
@end
@protocol BTInquiryDelegate
+ (void) deviceChoosen:(BTInquiryViewController *) inqView device:(BTDevice*) device;
+ (void) deviceDetected:(BTInquiryViewController *) inqView device:(BTDevice*) device;
+ (void) disconnectDevice:(BTInquiryViewController *) inqView device:(BTDevice*) device;
+ (void) inquiryStopped;
@end

View File

@ -0,0 +1,592 @@
/*
* Copyright (C) 2009 by Matthias Ringwald
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
//
// BTInquiryViewController.m
//
// Created by Matthias Ringwald on 10/8/09.
//
#import "BTInquiryViewController.h"
#import "BTDevice.h"
#import <UIKit/UIToolbar.h>
#include "btstack/btstack.h"
//#include "wiimote.h"
#define INQUIRY_INTERVAL 3
unsigned myosd_num_of_joys = 0;
static BTInquiryViewController *inqView;
static btstack_packet_handler_t clientHandler;
static uint8_t remoteNameIndex;
@interface BTInquiryViewController (Private)
- (void) handlePacket:(uint8_t) packet_type channel:(uint16_t) channel packet:(uint8_t*) packet size:(uint16_t) size;
- (BTDevice *) getDeviceForAddress:(bd_addr_t *)addr;
- (void) getNextRemoteName;
- (void) startInquiry;
@end
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
if (inqView) {
[inqView handlePacket:packet_type channel:channel packet:packet size:size];
}
}
@implementation BTInquiryViewController
@synthesize devices;
@synthesize delegate;
@synthesize allowSelection;
@synthesize showIcons;
- (id) init {
self = [super initWithStyle:UITableViewStyleGrouped];
bluetoothState = HCI_STATE_OFF;
inquiryState = kInquiryInactive;
allowSelection = false;
showIcons = false;
remoteDevice = nil;
restartInquiry = true;
notifyDelegateOnInquiryStopped = false;
macAddressFont = [UIFont fontWithName:@"Courier New" size:[UIFont labelFontSize]];
deviceNameFont = [UIFont boldSystemFontOfSize:[UIFont labelFontSize]];
deviceActivity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[deviceActivity startAnimating];
bluetoothActivity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[bluetoothActivity startAnimating];
devices = [[NSMutableArray alloc] init];
inqView = self;
return self;
}
- (void) myStartInquiry{
if (inquiryState != kInquiryInactive) {
NSLog(@"Inquiry already active");
return;
}
NSLog(@"Inquiry started");
stopRemoteNameGathering = false;
restartInquiry = true;
inquiryState = kInquiryActive;
[[self tableView] reloadData];
bt_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
}
- (void) handlePacket:(uint8_t) packet_type channel:(uint16_t) channel packet:(uint8_t*) packet size:(uint16_t) size {
bd_addr_t event_addr;
switch (packet_type) {
case HCI_EVENT_PACKET:
switch (packet[0]){
case BTSTACK_EVENT_STATE:
{
// bt stack activated
bluetoothState = (HCI_STATE)packet[2];
[[self tableView] reloadData];
// set BT state
/*
if (bluetoothState == HCI_STATE_WORKING) {
[self myStartInquiry];
}
*/
break;
}
case BTSTACK_EVENT_POWERON_FAILED:
{
bluetoothState = HCI_STATE_OFF;
[[self tableView] reloadData];
UIAlertView* alertView = [[UIAlertView alloc] init];
alertView.title = @"Bluetooth not accessible!";
alertView.message = @"Hardware initialization failed!\n"
"Make sure you have turned off Bluetooth in the System Settings.";
NSLog(@"Alert: %@ - %@", alertView.title, alertView.message);
[alertView addButtonWithTitle:@"Dismiss"];
[alertView show];
break;
}
case HCI_EVENT_INQUIRY_RESULT:
case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:
{
int numResponses = packet[2];
int i;
for (i=0; i<numResponses;i++){
bd_addr_t addr;
bt_flip_addr(addr, &packet[3+i*6]);
if ([inqView getDeviceForAddress:&addr]) {
NSLog(@"Device %@ already in list", [BTDevice stringForAddress:&addr]);
continue;
}
BTDevice *dev = [[BTDevice alloc] init];
[dev setAddress:&addr];
[dev setPageScanRepetitionMode:packet[3 + numResponses*6 + i]];
[dev setClassOfDevice:READ_BT_24(packet, 3 + numResponses*(6+1+1+1) + i*3)];
[dev setClockOffset:(READ_BT_16(packet, 3 + numResponses*(6+1+1+1+3) + i*2) & 0x7fff)];
// hexdump(packet, size);
NSLog(@"--> adding %@", [dev toString] );
[devices addObject:dev];
if (delegate) {
[delegate deviceDetected:self device:dev];
}
}
[[inqView tableView] reloadData];
NSLog(@"bye" );
break;
}
case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
{
bt_flip_addr(event_addr, &packet[3]);
BTDevice *dev = [inqView getDeviceForAddress:&event_addr];
if (!dev) break;
[dev setConnectionState:kBluetoothConnectionNotConnected];
if (packet[2] == 0) {
[dev setName:[NSString stringWithUTF8String:(const char *) &packet[9]]];
if (delegate) {
[delegate deviceDetected:self device:dev];
}
}
[[self tableView] reloadData];
remoteNameIndex++;
[self getNextRemoteName];
break;
}
case HCI_EVENT_COMMAND_COMPLETE:
{
if (COMMAND_COMPLETE_EVENT(packet, hci_inquiry_cancel)){
// inquiry canceled
NSLog(@"Inquiry cancelled successfully");
inquiryState = kInquiryInactive;
[[self tableView] reloadData];
if (notifyDelegateOnInquiryStopped){
notifyDelegateOnInquiryStopped = false;
if (delegate) {
[delegate inquiryStopped];
}
}
}
if (COMMAND_COMPLETE_EVENT(packet, hci_remote_name_request_cancel)){
// inquiry canceled
NSLog(@"Remote name request cancelled successfully");
inquiryState = kInquiryInactive;
[[self tableView] reloadData];
if (notifyDelegateOnInquiryStopped){
notifyDelegateOnInquiryStopped = false;
if (delegate) {
[delegate inquiryStopped];
}
}
}
break;
}
case HCI_EVENT_INQUIRY_COMPLETE:
{
NSLog(@"Inquiry complete");
// reset name check
remoteNameIndex = 0;
[self getNextRemoteName];
break;
}
default:
break;
// hexdump(packet, size);
//break;
}
default:
break;
}
// forward to client app
(*clientHandler)(packet_type, channel, packet, size);
}
- (BTDevice *) getDeviceForAddress:(bd_addr_t *)addr {
uint8_t j;
for (j=0; j<[devices count]; j++){
BTDevice *dev = [devices objectAtIndex:j];
if (BD_ADDR_CMP(addr, [dev address]) == 0){
return dev;
}
}
return nil;
}
- (void) removeDeviceForAddress:(bd_addr_t *)addr {
uint8_t j;
for (j=0; j<[devices count]; j++){
BTDevice *dev = [devices objectAtIndex:j];
if (BD_ADDR_CMP(addr, [dev address]) == 0){
NSLog(@"--> removed %@", [dev toString] );
[devices removeObject:dev];
[[self tableView] reloadData];
return;
}
}
}
- (void) getNextRemoteName{
// stopped?
if (stopRemoteNameGathering) {
inquiryState = kInquiryInactive;
[[self tableView] reloadData];
if (notifyDelegateOnInquiryStopped){
notifyDelegateOnInquiryStopped = false;
if (delegate) {
[delegate inquiryStopped];
}
}
return;
}
remoteNameDevice = nil;
for (remoteNameIndex = 0; remoteNameIndex < [devices count]; remoteNameIndex++){
BTDevice *dev = [devices objectAtIndex:remoteNameIndex];
if (![dev name]){
remoteNameDevice = dev;
break;
}
}
if (remoteNameDevice) {
inquiryState = kInquiryRemoteName;
[remoteNameDevice setConnectionState:kBluetoothConnectionRemoteName];
bt_send_cmd(&hci_remote_name_request, [remoteNameDevice address], [remoteNameDevice pageScanRepetitionMode], 0, [remoteNameDevice clockOffset] | 0x8000);
} else {
inquiryState = kInquiryInactive;
// inquiry done.
if (restartInquiry) {
[self myStartInquiry];
}
}
[[self tableView] reloadData];
}
- (void) startInquiry {
//static int b = 0;
//if(!b)
//{
//b=1;
// put into loop
// @TODO: cannot be called a second time!
clientHandler = bt_register_packet_handler(packet_handler);
bluetoothState = HCI_STATE_INITIALIZING;
[[self tableView] reloadData];
stopRemoteNameGathering = false;
restartInquiry = true;
bt_send_cmd(&btstack_set_power_mode, HCI_POWER_ON );
//}
}
- (void) stopInquiry {
NSLog(@"stop inquiry called, state %u", inquiryState);
restartInquiry = false;
stopRemoteNameGathering = true;
bool immediateNotify = true;
switch (inquiryState) {
case kInquiryActive:
// just stop inquiry
immediateNotify = false;
bt_send_cmd(&hci_inquiry_cancel);
break;
case kInquiryInactive:
NSLog(@"stop inquiry called although inquiry inactive?");
break;
case kInquiryRemoteName:
if (remoteNameDevice) {
// just stop remote name request
immediateNotify = false;
bt_send_cmd(&hci_remote_name_request_cancel, [remoteNameDevice address]);
}
break;
default:
break;
}
if (immediateNotify && delegate){
[delegate inquiryStopped];
} else {
notifyDelegateOnInquiryStopped = true;
}
}
- (void) showConnecting:(BTDevice *) device {
remoteDevice = device;
[[self tableView] reloadData];
}
- (void) showConnected:(BTDevice *) device {
connectedDevice = device;
[[self tableView] reloadData];
}
/*
- (void)loadView {
[super loadView];
}
*/
/*
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
//self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
*/
/*
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
*/
/*
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
*/
/*
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
*/
/*
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
*/
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
//return NO;
//return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
// unregister self
bt_register_packet_handler(clientHandler);
// done
[super dealloc];
}
#pragma mark Table view methods
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
return @"Devices";
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
int rows = 1; // 1 for status line
if (bluetoothState == HCI_STATE_WORKING) {
rows += [devices count];
}
return rows;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:/* UITableViewCellStyleDefault = */(UITableViewCellStyle)0 reuseIdentifier:CellIdentifier] autorelease];
// cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
// Set up the cell...
NSString *label = nil;
int idx = [indexPath indexAtPosition:1];
if (bluetoothState != HCI_STATE_WORKING || idx >= [devices count]) {
if (bluetoothState == HCI_STATE_INITIALIZING){
label = @"Activating BTstack...";
cell.accessoryView = bluetoothActivity;
} else if (bluetoothState == HCI_STATE_OFF){
label = @"Bluetooth not accessible!";
cell.accessoryView = nil;
} else {
if (connectedDevice) {
label = @"Disconnect";
cell.accessoryView = nil;
} else if (remoteDevice) {
label = @"Connecting...";
cell.accessoryView = bluetoothActivity;
} else {
switch (inquiryState){
case kInquiryInactive:
if (myosd_num_of_joys==4)
{
label = @"Maximun devices connected!";
}
else if ([devices count] > 0){
label = @"Press here to find more devices...";
} else {
label = @"Press here to find first device...";
}
cell.accessoryView = nil;
break;
case kInquiryActive:
//label = @"Searching...";
label = @"Press 1 and 2 on the WiiMote to sync";
cell.accessoryView = bluetoothActivity;
break;
case kInquiryRemoteName:
label = @"Query device names...";
cell.accessoryView = bluetoothActivity;
break;
}
}
}
} else {
BTDevice *dev = [devices objectAtIndex:idx];
label = [dev nameOrAddress];
if ([dev name]){
cell.font = deviceNameFont;
} else {
cell.font = macAddressFont;
}
// pick an icon for the devices
if (showIcons) {
int major = ([dev classOfDevice] & 0x1f00) >> 8;
if (major == 0x01) {
cell.image = [UIImage imageNamed:@"computer.png"];
} else if (major == 0x02) {
cell.image = [UIImage imageNamed:@"smartphone.png"];
} else if ( major == 0x05 && ([dev classOfDevice] & 0xff) == 0x40){
cell.image = [UIImage imageNamed:@"keyboard.png"];
} else {
cell.image = [UIImage imageNamed:@"bluetooth.png"];
}
}
switch ([dev connectionState]) {
case kBluetoothConnectionNotConnected:
case kBluetoothConnectionConnected:
cell.accessoryView = nil;
break;
case kBluetoothConnectionConnecting:
case kBluetoothConnectionRemoteName:
cell.accessoryView = deviceActivity;
break;
}
}
cell.text = label;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"didSelectRowAtIndexPath %@", indexPath);
// Navigation logic may go here. Create and push another view controller.
// AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
// [self.navigationController pushViewController:anotherViewController];
// [anotherViewController release];
// valid selection?
int idx = [indexPath indexAtPosition:1];
//printf("sleccion %d\n",idx);
if (bluetoothState == HCI_STATE_WORKING) {
if (delegate) {
if (idx < [devices count]){
[delegate deviceChoosen:self device:[devices objectAtIndex:idx]];
} else if (idx == [devices count]) {
//printf("seleccionado %d %d\n",idx,connectedDevice);
if (connectedDevice) {
// DISCONNECT button
[delegate disconnectDevice:self device:connectedDevice];
} else if (myosd_num_of_joys<4){
// Find more devices
[self myStartInquiry];
}
}
}
} else {
[tableView deselectRowAtIndexPath:indexPath animated:TRUE];
}
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (allowSelection) {
return indexPath;
}
return nil;
}
@end

View File

@ -0,0 +1,49 @@
/*
* This file is part of MAME4iOS.
*
* Copyright (C) 2012 David Valdeita (Seleuco)
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, as a special exception, Seleuco
* gives permission to link the code of this program with
* the MAME library (or with modified versions of MAME that use the
* same license as MAME), and distribute linked combinations including
* the two. You must obey the GNU General Public License in all
* respects for all of the code used other than MAME. If you modify
* this file, you may extend this exception to your version of the
* file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*/
#import <UIKit/UIKit.h>
#import "BTInquiryViewController.h"
@interface WiiMoteHelper : NSObject<BTInquiryDelegate>
{
}
+ (void)startwiimote:(UIViewController *)controller;
+ (void)endwiimote;
+ (void)cancelWiiMoteSearch;
@end

View File

@ -0,0 +1,427 @@
/*
* This file is part of MAME4iOS.
*
* Copyright (C) 2012 David Valdeita (Seleuco)
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, as a special exception, Seleuco
* gives permission to link the code of this program with
* the MAME library (or with modified versions of MAME that use the
* same license as MAME), and distribute linked combinations including
* the two. You must obey the GNU General Public License in all
* respects for all of the code used other than MAME. If you modify
* this file, you may extend this exception to your version of the
* file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*/
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include "wiimote.h"
#import "WiiMoteHelper.h"
#import "BTDevice.h"
#import "BTInquiryViewController.h"
#import "btstack/btstack.h"
#import "btstack/run_loop.h"
#import "btstack/hci_cmds.h"
bool btOK = false;
bool initLoop = false;
BTDevice *device;
uint16_t wiiMoteConHandle = 0;
bool conected = false;
bool activated = false;
BTInquiryViewController *inqViewControl;
void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
bd_addr_t event_addr;
switch (packet_type) {
case L2CAP_DATA_PACKET://0x06
{
struct wiimote_t *wm = NULL;
wm = wiimote_get_by_source_cid(channel);
if(wm!=NULL)
{
byte* msg = packet + 2;
byte event = packet[1];
switch (event) {
case WM_RPT_BTN:
{
/* button */
wiimote_pressed_buttons(wm, msg);
break;
}
case WM_RPT_READ:
{
/* data read */
if(WIIMOTE_DBG)printf("WM_RPT_READ data arrive!\n");
wiimote_pressed_buttons(wm, msg);
byte err = msg[2] & 0x0F;
if (err == 0x08)
printf("Unable to read data - address does not exist.\n");
else if (err == 0x07)
printf("Unable to read data - address is for write-only registers.\n");
else if (err)
printf("Unable to read data - unknown error code %x.\n", err);
unsigned short offset = BIG_ENDIAN_SHORT(*(unsigned short*)(msg + 3));
byte len = ((msg[2] & 0xF0) >> 4) + 1;
byte *data = (msg + 5);
if(WIIMOTE_DBG)
{
int i = 0;
printf("Read: 0x%04x ; ",offset);
for (; i < len; ++i)
printf("%x ", data[i]);
printf("\n");
}
if(wiimote_handshake(wm,WM_RPT_READ,data,len))
{
//btUsed = 1;
[inqViewControl showConnected:nil];
[inqViewControl showConnecting:nil];
//Create UIAlertView alert
[inqViewControl showConnecting:nil];
UIAlertView* alert =
[[UIAlertView alloc] initWithTitle:@"Connection detected!"
message: [NSString stringWithFormat:@"%@ '%@' connection sucessfully completed!",
(wm->exp.type != EXP_NONE ? @"Classic Controller" : @"WiiMote"),
[NSNumber numberWithInt:(wm->unid)+1]]
delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles: nil];
[alert show];
//[alert dismissWithClickedButtonIndex:0 animated:TRUE];
[alert release];
if(device!=nil)
{
[device setConnectionState:kBluetoothConnectionConnected];
device = nil;
}
}
return;
}
case WM_RPT_CTRL_STATUS:
{
wiimote_pressed_buttons(wm, msg);
/* find the battery level and normalize between 0 and 1 */
if(WIIMOTE_DBG)
{
wm->battery_level = (msg[5] / (float)WM_MAX_BATTERY_CODE);
printf("BATTERY LEVEL %f\n", wm->battery_level);
}
//handshake stuff!
if(wiimote_handshake(wm,WM_RPT_CTRL_STATUS,msg,-1))
{
//btUsed = 1;
[inqViewControl showConnected:nil];
[inqViewControl showConnecting:nil];
UIAlertView* alert =
[[UIAlertView alloc] initWithTitle:@"Connection detected!"
message: [NSString stringWithFormat:@"WiiMote '%@' connection sucessfully completed!",[NSNumber numberWithInt:(wm->unid)+1]]
delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles: nil];
[alert show];
//[alert dismissWithClickedButtonIndex:0 animated:TRUE];
[alert release];
[device setConnectionState:kBluetoothConnectionConnected];
if(device!=nil)
{
[device setConnectionState:kBluetoothConnectionConnected];
device = nil;
}
}
return;
}
case WM_RPT_BTN_EXP:
{
/* button - expansion */
wiimote_pressed_buttons(wm, msg);
wiimote_handle_expansion(wm, msg+2);
break;
}
case WM_RPT_WRITE:
{
/* write feedback - safe to skip */
break;
}
default:
{
printf("Unknown event, can not handle it [Code 0x%x].", event);
return;
}
}
}
break;
}
case HCI_EVENT_PACKET://0x04
{
switch (packet[0]){
case L2CAP_EVENT_CHANNEL_OPENED:
// data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16)
if (packet[2] == 0) {
// inform about new l2cap connection
bt_flip_addr(event_addr, &packet[3]);
uint16_t psm = READ_BT_16(packet, 11);
uint16_t source_cid = READ_BT_16(packet, 13);
wiiMoteConHandle = READ_BT_16(packet, 9);
NSLog(@"Channel successfully opened: handle 0x%02x, psm 0x%02x, source cid 0x%02x, dest cid 0x%02x",
wiiMoteConHandle, psm, source_cid, READ_BT_16(packet, 15));
if (psm == 0x13) {
// interupt channel openedn succesfully, now open control channel, too.
if(WIIMOTE_DBG)printf("open control channel\n");
bt_send_cmd(&l2cap_create_channel, event_addr, 0x11);
struct wiimote_t *wm = NULL;
wm = &joys[myosd_num_of_joys];
memset(wm, 0, sizeof(struct wiimote_t));
wm->unid = myosd_num_of_joys;
wm->i_source_cid = source_cid;
memcpy(&wm->addr,&event_addr,BD_ADDR_LEN);
if(WIIMOTE_DBG)printf("addr %02x:%02x:%02x:%02x:%02x:%02x\n", wm->addr[0], wm->addr[1], wm->addr[2],wm->addr[3], wm->addr[4], wm->addr[5]);
if(WIIMOTE_DBG)printf("saved 0x%02x 0x%02x\n",source_cid,wm->i_source_cid);
wm->exp.type = EXP_NONE;
} else {
//inicializamos el wiimote!
struct wiimote_t *wm = NULL;
wm = &joys[myosd_num_of_joys];
wm->wiiMoteConHandle = wiiMoteConHandle;
wm->c_source_cid = source_cid;
wm->state = WIIMOTE_STATE_CONNECTED;
myosd_num_of_joys++;
if(WIIMOTE_DBG)printf("Devices Number: %d\n",myosd_num_of_joys);
wiimote_handshake(wm,-1,NULL,-1);
}
}
break;
case L2CAP_EVENT_CHANNEL_CLOSED:
{
// data: event (8), len(8), channel (16)
uint16_t source_cid = READ_BT_16(packet, 2);
NSLog(@"Channel successfully closed: cid 0x%02x",source_cid);
bd_addr_t addr;
int unid = wiimote_remove(source_cid,&addr);
if(unid!=-1)
{
[inqViewControl removeDeviceForAddress:&addr];
UIAlertView* alert =
[[UIAlertView alloc] initWithTitle:@"Disconnection!"
message:[NSString stringWithFormat:@"WiiMote '%@' disconnection detected.\nIs battery drainned?",[NSNumber numberWithInt:(unid+1)]]
delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles: nil];
[alert show];
[alert release];
}
}
break;
default:
break;
}
break;
}
default:
break;
}
}
@implementation WiiMoteHelper
+(void) startwiimote:(UIViewController *)controller{
if(!initLoop)
{
run_loop_init(RUN_LOOP_COCOA);
initLoop = true;
}
if(!btOK )
{
if (bt_open() ){
// Alert user?
} else {
bt_register_packet_handler(packet_handler);
btOK = true;
}
}
if (btOK)
{
// create inq controller
if(inqViewControl==nil)
{
inqViewControl = [[BTInquiryViewController alloc] init];
struct CGRect rect = controller.view.frame;
CGFloat navBarWidht = rect.size.width;
CGFloat navBarHeight = 45;
UINavigationBar *navBar = [ [ UINavigationBar alloc ] initWithFrame: CGRectMake(0, 0, navBarWidht , navBarHeight)];
[navBar autorelease];
[navBar setDelegate: inqViewControl ];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:CGRectMake(rect.size.width-70,5,60,35)];
[button setTitle:@"Done" forState:UIControlStateNormal];
button.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
[button addTarget:self action:@selector(cancelWiiMoteSearch) forControlEvents:UIControlEventTouchUpInside];
[navBar addSubview:button];
UILabel *navLabel = [[UILabel alloc] initWithFrame:CGRectMake(40,0,300, navBarHeight)];
navLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
navLabel.text = @"WiiMote Sync";
navLabel.backgroundColor = [UIColor clearColor];
navLabel.textColor = [UIColor blackColor];
navLabel.font = [UIFont systemFontOfSize: 18];
navLabel.textAlignment = UITextAlignmentLeft;
[navBar addSubview:navLabel];
[navLabel release];
[[inqViewControl tableView] setTableHeaderView:navBar];
[navBar release];
}
if(!activated)
{
UIAlertView* alertView=[[UIAlertView alloc] initWithTitle:nil
message:@"are you sure you to activate BTstack?"
delegate:self cancelButtonTitle:nil
otherButtonTitles:@"Yes",@"No",nil];
[alertView show];
[alertView release];
}
[controller presentModalViewController:inqViewControl animated:YES];
}
}
+ (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 0 )
{
[inqViewControl setDelegate:self];
[inqViewControl setAllowSelection:true];
activated = true;
[inqViewControl startInquiry];
}
else
{
[inqViewControl dismissModalViewControllerAnimated:YES];
}
}
+(void) cancelWiiMoteSearch {
[inqViewControl stopInquiry];
[inqViewControl dismissModalViewControllerAnimated:YES];
}
+(void) deviceChoosen:(BTInquiryViewController *) inqView device:(BTDevice*) deviceChoosen;
{
NSLog(@"deviceChoosen %@", [device toString]);
}
+ (void) deviceDetected:(BTInquiryViewController *) inqView device:(BTDevice*) selectedDevice {
NSLog(@"deviceDetected %@", [device toString]);
if ([selectedDevice name] && [[selectedDevice name] caseInsensitiveCompare:@"Nintendo RVL-CNT-01"] == NSOrderedSame){
NSLog(@"WiiMote found with address %@", [BTDevice stringForAddress:[selectedDevice address]]);
device = selectedDevice;
[inqViewControl stopInquiry];
[inqViewControl showConnecting:device];
// connect to device
[device setConnectionState:kBluetoothConnectionConnecting];
[[inqViewControl tableView] reloadData];
bt_send_cmd(&l2cap_create_channel, [device address], 0x13);
}
}
+ (void) inquiryStopped{
}
+ (void) disconnectDevice:(BTInquiryViewController *) inqView device:(BTDevice*) selectedDevice {
}
+ (void)endwiimote {
if(btOK)
{
int i=0;
while(i!=myosd_num_of_joys){
[inqViewControl removeDeviceForAddress:&joys[i].addr];
i++;
}
myosd_num_of_joys=0;
bt_send_cmd(&btstack_set_power_mode, HCI_POWER_OFF );
bt_close();
activated= false;
btOK = false;
}
}
@end

View File

@ -0,0 +1,85 @@
/*
* Copyright (C) 2009 by Matthias Ringwald
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* btstack.h
*
* Created by Matthias Ringwald on 7/1/09.
*
* BTstack client API
*
*/
#pragma once
#include "hci_cmds.h"
#include "run_loop.h"
#include "utils.h"
#include <stdint.h>
#if defined __cplusplus
extern "C" {
#endif
// Default TCP port for BTstack daemon
#define BTSTACK_PORT 13333
// UNIX domain socket for BTstack */
#define BTSTACK_UNIX "/tmp/BTstack"
// packet handler
typedef void (*btstack_packet_handler_t) (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
// optional: if called before bt_open, TCP socket is used instead of local unix socket
// note: address is not copied and must be valid during bt_open
void bt_use_tcp(const char * address, uint16_t port);
// init BTstack library
int bt_open();
// stop using BTstack library
int bt_close();
// send hci cmd packet
int bt_send_cmd(const hci_cmd_t *cmd, ...);
// register packet handler -- channel only valid for l2cap and rfcomm packets
// @returns old packet handler
btstack_packet_handler_t bt_register_packet_handler(btstack_packet_handler_t handler);
void bt_send_acl(uint8_t * data, uint16_t len);
void bt_send_l2cap(uint16_t local_cid, uint8_t *data, uint16_t len);
#if defined __cplusplus
}
#endif

View File

@ -0,0 +1,253 @@
/*
* Copyright (C) 2009 by Matthias Ringwald
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* hci_cmds.h
*
* Created by Matthias Ringwald on 7/23/09.
*/
#pragma once
#include <stdint.h>
#if defined __cplusplus
extern "C" {
#endif
/**
* packet types - used in BTstack and over the H4 UART interface
*/
#define HCI_COMMAND_DATA_PACKET 0x01
#define HCI_ACL_DATA_PACKET 0x02
#define HCI_SCO_DATA_PACKET 0x03
#define HCI_EVENT_PACKET 0x04
// extension for client/server communication
#define DAEMON_EVENT_PACKET 0x05
// L2CAP data
#define L2CAP_DATA_PACKET 0x06
// RFCOMM data
#define RFCOMM_DATA_PACKET 0x07
// Fixed PSM numbers
#define PSM_SDP 0x01
#define PSM_RFCOMM 0x03
#define PSM_HID_CONTROL 0x11
#define PSM_HID_INTERRUPT 0x13
// Events from host controller to host
#define HCI_EVENT_INQUIRY_COMPLETE 0x01
#define HCI_EVENT_INQUIRY_RESULT 0x02
#define HCI_EVENT_CONNECTION_COMPLETE 0x03
#define HCI_EVENT_CONNECTION_REQUEST 0x04
#define HCI_EVENT_DISCONNECTION_COMPLETE 0x05
#define HCI_EVENT_AUTHENTICATION_COMPLETE_EVENT 0x06
#define HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE 0x07
#define HCI_EVENT_ENCRIPTION_CHANGE 0x08
#define HCI_EVENT_CHANGE_CONNECTION_LINK_KEY_COMPLETE 0x09
#define HCI_EVENT_MASTER_LINK_KEY_COMPLETE 0x0A
#define HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE 0x0B
#define HCI_EVENT_READ_REMOTE_VERSION_INFORMATION_COMPLETE 0x0C
#define HCI_EVENT_QOS_SETUP_COMPLETE 0x0D
#define HCI_EVENT_COMMAND_COMPLETE 0x0E
#define HCI_EVENT_COMMAND_STATUS 0x0F
#define HCI_EVENT_HARDWARE_ERROR 0x10
#define HCI_EVENT_FLUSH_OCCURED 0x11
#define HCI_EVENT_ROLE_CHANGE 0x12
#define HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS 0x13
#define HCI_EVENT_MODE_CHANGE_EVENT 0x14
#define HCI_EVENT_RETURN_LINK_KEYS 0x15
#define HCI_EVENT_PIN_CODE_REQUEST 0x16
#define HCI_EVENT_LINK_KEY_REQUEST 0x17
#define HCI_EVENT_LINK_KEY_NOTIFICATION 0x18
#define HCI_EVENT_DATA_BUFFER_OVERFLOW 0x1A
#define HCI_EVENT_MAX_SLOTS_CHANGED 0x1B
#define HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE 0x1C
#define HCI_EVENT_PACKET_TYPE_CHANGED 0x1D
#define HCI_EVENT_INQUIRY_RESULT_WITH_RSSI 0x22
#define HCI_EVENT_EXTENDED_INQUIRY_RESPONSE 0x2F
#define HCI_EVENT_VENDOR_SPECIFIC 0xFF
// last used HCI_EVENT in 2.1 is 0x3d
// events 0x50-0x5f are used internally
// events from BTstack for application/client lib
#define BTSTACK_EVENT_STATE 0x60
// data: event(8), len(8), nr hci connections
#define BTSTACK_EVENT_NR_CONNECTIONS_CHANGED 0x61
// data: none
#define BTSTACK_EVENT_POWERON_FAILED 0x62
// data: majot (8), minor (8), revision(16)
#define BTSTACK_EVENT_VERSION 0x63
// data: system bluetooth on/off (bool)
#define BTSTACK_EVENT_SYSTEM_BLUETOOTH_ENABLED 0x64
// data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16)
#define L2CAP_EVENT_CHANNEL_OPENED 0x70
// data: event (8), len(8), channel (16)
#define L2CAP_EVENT_CHANNEL_CLOSED 0x71
// data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16)
#define L2CAP_EVENT_INCOMING_CONNECTION 0x72
// data: event(8), len(8), handle(16)
#define L2CAP_EVENT_TIMEOUT_CHECK 0x73
// data: event(8), len(8), handle(16)
#define L2CAP_EVENT_CREDITS 0x74
// data: event(8), len(8), service_record_handle(32)
#define SDP_SERVICE_REGISTERED 0x80
// last error code in 2.1 is 0x38 - we start with 0x50 for BTstack errors
#define BTSTACK_CONNECTION_TO_BTDAEMON_FAILED 0x50
#define BTSTACK_ACTIVATION_FAILED_SYSTEM_BLUETOOTH 0x51
#define BTSTACK_ACTIVATION_POWERON_FAILED 0x52
#define BTSTACK_ACTIVATION_FAILED_UNKNOWN 0x53
#define BTSTACK_NOT_ACTIVATED 0x54
#define BTSTACK_BUSY 0x55
// l2cap errors - enumeration by the command that created them
#define L2CAP_COMMAND_REJECT_REASON_COMMAND_NOT_UNDERSTOOD 0x60
#define L2CAP_COMMAND_REJECT_REASON_SIGNALING_MTU_EXCEEDED 0x61
#define L2CAP_COMMAND_REJECT_REASON_INVALID_CID_IN_REQUEST 0x62
#define L2CAP_CONNECTION_RESPONSE_RESULT_SUCCESSFUL 0x63
#define L2CAP_CONNECTION_RESPONSE_RESULT_PENDING 0x64
#define L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_PSM 0x65
#define L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_SECURITY 0x66
#define L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_RESOURCES 0x65
#define L2CAP_CONFIG_RESPONSE_RESULT_SUCCESSFUL 0x66
#define L2CAP_CONFIG_RESPONSE_RESULT_UNACCEPTABLE_PARAMS 0x67
#define L2CAP_CONFIG_RESPONSE_RESULT_REJECTED 0x68
#define L2CAP_CONFIG_RESPONSE_RESULT_UNKNOWN_OPTIONS 0x69
/**
* Default INQ Mode
*/
#define HCI_INQUIRY_LAP 0x9E8B33L // 0x9E8B33: General/Unlimited Inquiry Access Code (GIAC)
/**
* Hardware state of Bluetooth controller
*/
typedef enum {
HCI_POWER_OFF = 0,
HCI_POWER_ON
} HCI_POWER_MODE;
/**
* State of BTstack
*/
typedef enum {
HCI_STATE_OFF = 0,
HCI_STATE_INITIALIZING,
HCI_STATE_WORKING,
HCI_STATE_HALTING
} HCI_STATE;
/**
* compact HCI Command packet description
*/
typedef struct {
uint16_t opcode;
const char *format;
} hci_cmd_t;
// HCI Commands - see hci_cmds.c for info on parameters
extern const hci_cmd_t btstack_get_state;
extern const hci_cmd_t btstack_set_power_mode;
extern const hci_cmd_t btstack_set_acl_capture_mode;
extern const hci_cmd_t btstack_get_version;
extern const hci_cmd_t btstack_get_system_bluetooth_enabled;
extern const hci_cmd_t btstack_set_system_bluetooth_enabled;
extern const hci_cmd_t hci_accept_connection_request;
extern const hci_cmd_t hci_authentication_requested;
extern const hci_cmd_t hci_create_connection;
extern const hci_cmd_t hci_create_connection_cancel;
extern const hci_cmd_t hci_delete_stored_link_key;
extern const hci_cmd_t hci_disconnect;
extern const hci_cmd_t hci_host_buffer_size;
extern const hci_cmd_t hci_inquiry;
extern const hci_cmd_t hci_inquiry_cancel;
extern const hci_cmd_t hci_link_key_request_negative_reply;
extern const hci_cmd_t hci_link_key_request_reply;
extern const hci_cmd_t hci_pin_code_request_reply;
extern const hci_cmd_t hci_pin_code_request_negative_reply;
extern const hci_cmd_t hci_qos_setup;
extern const hci_cmd_t hci_read_bd_addr;
extern const hci_cmd_t hci_read_buffer_size;
extern const hci_cmd_t hci_read_link_policy_settings;
extern const hci_cmd_t hci_read_link_supervision_timeout;
extern const hci_cmd_t hci_remote_name_request;
extern const hci_cmd_t hci_remote_name_request_cancel;
extern const hci_cmd_t hci_reset;
extern const hci_cmd_t hci_role_discovery;
extern const hci_cmd_t hci_set_event_mask;
extern const hci_cmd_t hci_switch_role_command;
extern const hci_cmd_t hci_write_authentication_enable;
extern const hci_cmd_t hci_write_class_of_device;
extern const hci_cmd_t hci_write_extended_inquiry_response;
extern const hci_cmd_t hci_write_inquiry_mode;
extern const hci_cmd_t hci_write_link_policy_settings;
extern const hci_cmd_t hci_write_link_supervision_timeout;
extern const hci_cmd_t hci_write_local_name;
extern const hci_cmd_t hci_write_page_timeout;
extern const hci_cmd_t hci_write_scan_enable;
extern const hci_cmd_t hci_write_simple_pairing_mode;
extern const hci_cmd_t l2cap_accept_connection;
extern const hci_cmd_t l2cap_create_channel;
extern const hci_cmd_t l2cap_create_channel_mtu;
extern const hci_cmd_t l2cap_decline_connection;
extern const hci_cmd_t l2cap_disconnect;
extern const hci_cmd_t l2cap_register_service;
extern const hci_cmd_t l2cap_unregister_service;
extern const hci_cmd_t sdp_register_service_record;
extern const hci_cmd_t sdp_unregister_service_record;
#if defined __cplusplus
}
#endif

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2009 by Matthias Ringwald
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* linked_list.h
*
* Created by Matthias Ringwald on 7/13/09.
*/
#pragma once
#if defined __cplusplus
extern "C" {
#endif
typedef struct linked_item {
struct linked_item *next; // <-- next element in list, or NULL
void *user_data; // <-- pointer to struct base
} linked_item_t;
typedef linked_item_t * linked_list_t;
void linked_item_set_user(linked_item_t *item, void *user_data); // <-- set user data
void * linked_item_get_user(linked_item_t *item); // <-- get user data
int linked_list_empty(linked_list_t * list);
void linked_list_add(linked_list_t * list, linked_item_t *item); // <-- add item to list as first element
void linked_list_add_tail(linked_list_t * list, linked_item_t *item); // <-- add item to list as last element
int linked_list_remove(linked_list_t * list, linked_item_t *item); // <-- remove item from list
void test_linked_list();
#if defined __cplusplus
}
#endif

View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2009 by Matthias Ringwald
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* run_loop.h
*
* Created by Matthias Ringwald on 6/6/09.
*/
#pragma once
#include "linked_list.h"
#include <sys/time.h>
#if defined __cplusplus
extern "C" {
#endif
typedef enum {
RUN_LOOP_POSIX = 1,
RUN_LOOP_COCOA,
RUN_LOOP_EMBEDDED
} RUN_LOOP_TYPE;
typedef struct data_source {
linked_item_t item;
int fd; // <-- file descriptor to watch or 0
int (*process)(struct data_source *ds); // <-- do processing
} data_source_t;
typedef struct timer {
linked_item_t item;
struct timeval timeout; // <-- next timeout
void (*process)(struct timer *ts); // <-- do processing
} timer_source_t;
// init must be called before any other run_loop call
void run_loop_init(RUN_LOOP_TYPE type);
// add/remove data_source
void run_loop_add_data_source(data_source_t *dataSource);
int run_loop_remove_data_source(data_source_t *dataSource);
// set timer based on current time
void run_loop_set_timer(timer_source_t *a, int timeout_in_ms);
// add/remove timer_source
void run_loop_add_timer(timer_source_t *timer);
int run_loop_remove_timer(timer_source_t *timer);
// execute configured run_loop
void run_loop_execute();
#if defined __cplusplus
}
#endif

View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2010 by Matthias Ringwald
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* sdp_util.h
*/
#pragma once
#include <stdint.h>
#if defined __cplusplus
extern "C" {
#endif
typedef enum {
DE_NIL = 0,
DE_UINT,
DE_INT,
DE_UUID,
DE_STRING,
DE_BOOL,
DE_DES,
DE_DEA,
DE_URL
} de_type_t;
typedef enum {
DE_SIZE_8 = 0,
DE_SIZE_16,
DE_SIZE_32,
DE_SIZE_64,
DE_SIZE_128,
DE_SIZE_VAR_8,
DE_SIZE_VAR_16,
DE_SIZE_VAR_32
} de_size_t;
// UNIVERSAL ATTRIBUTE DEFINITIONS
#define SDP_ServiceRecordHandle 0x0000
#define SDP_ServiceClassIDList 0x0001
#define SDP_ServiceRecordState 0x0002
#define SDP_ServiceID 0x0003
#define SDP_ProtocolDescriptorList 0x0004
#define SDP_BrowseGroupList 0x0005
#define SDP_LanguageBaseAttributeIDList 0x0006
#define SDP_ServiceInfoTimeToLive 0x0007
#define SDP_ServiceAvailability 0x0008
#define SDP_BluetoothProfileDescriptorList 0x0009
#define SDP_DocumentationURL 0x000a
#define SDP_ClientExecutableURL 0x000b
#define SDP_IconURL 0x000c
#define SDP_AdditionalProtocolDescriptorList 0x000d
// OFFSETS FOR LOCALIZED ATTRIBUTES - SDP_LanguageBaseAttributeIDList
#define SDP_Offest_ServiceName 0x0000
#define SDP_Offest_ServiceDescription 0x0001
#define SDP_Offest_ProviderName 0x0002
#pragma mark DateElement
void de_dump_data_element(uint8_t * record);
int de_get_len(uint8_t *header);
de_size_t de_get_size_type(uint8_t *header);
de_type_t de_get_element_type(uint8_t *header);
void de_create_sequence(uint8_t *header);
uint8_t * de_push_sequence(uint8_t *header);
void de_pop_sequence(uint8_t * parent, uint8_t * child);
void de_add_number(uint8_t *seq, de_type_t type, de_size_t size, uint32_t value);
void de_add_data( uint8_t *seq, de_type_t type, uint16_t size, uint8_t *data);
int de_get_data_size(uint8_t * header);
#pragma mark SDP
int sdp_append_attributes_in_attributeIDList(uint8_t *record, uint8_t *attributeIDList, uint16_t startIndex, uint16_t maxBytes, uint8_t *buffer);
uint8_t * sdp_get_attribute_value_for_attribute_id(uint8_t * record, uint16_t attributeID);
int sdp_record_matches_service_search_pattern(uint8_t *record, uint8_t *serviceSearchPattern);
#if defined __cplusplus
}
#endif

View File

@ -0,0 +1,115 @@
/*
* Copyright (C) 2009 by Matthias Ringwald
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* utils.h
*
* General utility functions
*
* Created by Matthias Ringwald on 7/23/09.
*/
#pragma once
#include <stdint.h>
#if defined __cplusplus
extern "C" {
#endif
/**
* @brief hci connection handle type
*/
typedef uint16_t hci_con_handle_t;
/**
* @brief Length of a bluetooth device address.
*/
#define BD_ADDR_LEN 6
typedef uint8_t bd_addr_t[BD_ADDR_LEN];
/**
* @brief The link key type
*/
#define LINK_KEY_LEN 16
typedef uint8_t link_key_t[LINK_KEY_LEN];
// helper for BT little endian format
#define READ_BT_16( buffer, pos) ( ((uint16_t) buffer[pos]) | (((uint16_t)buffer[pos+1]) << 8))
#define READ_BT_24( buffer, pos) ( ((uint32_t) buffer[pos]) | (((uint32_t)buffer[pos+1]) << 8) | (((uint32_t)buffer[pos+2]) << 16))
#define READ_BT_32( buffer, pos) ( ((uint32_t) buffer[pos]) | (((uint32_t)buffer[pos+1]) << 8) | (((uint32_t)buffer[pos+2]) << 16) | (((uint32_t) buffer[pos+3])) << 24)
// helper for SDP big endian format
#define READ_NET_16( buffer, pos) ( ((uint16_t) buffer[pos+1]) | (((uint16_t)buffer[pos ]) << 8))
#define READ_NET_32( buffer, pos) ( ((uint32_t) buffer[pos+3]) | (((uint32_t)buffer[pos+2]) << 8) | (((uint32_t)buffer[pos+1]) << 16) | (((uint32_t) buffer[pos])) << 24)
// HCI CMD OGF/OCF
#define READ_CMD_OGF(buffer) (buffer[1] >> 2)
#define READ_CMD_OCF(buffer) ((buffer[1] & 0x03) << 8 | buffer[0])
// check if command complete event for given command
#define COMMAND_COMPLETE_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_COMPLETE && READ_BT_16(event,3) == cmd.opcode)
// ACL Packet
#define READ_ACL_CONNECTION_HANDLE( buffer ) ( READ_BT_16(buffer,0) & 0x0fff)
#define READ_ACL_FLAGS( buffer ) ( buffer[1] >> 4 )
#define READ_ACL_LENGTH( buffer ) (READ_BT_16(buffer, 2))
// L2CAP Packet
#define READ_L2CAP_LENGTH(buffer) ( READ_BT_16(buffer, 4))
#define READ_L2CAP_CHANNEL_ID(buffer) ( READ_BT_16(buffer, 6))
void bt_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);
void bt_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);
void bt_flip_addr(bd_addr_t dest, bd_addr_t src);
void net_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);
void net_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);
void hexdump(void *data, int size);
void printUUID(uint8_t *uuid);
void print_bd_addr(bd_addr_t addr);
int sscan_bd_addr(uint8_t * addr_string, bd_addr_t addr);
uint8_t crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum);
uint8_t crc8_calc(uint8_t *data, uint16_t len);
#define BD_ADDR_CMP(a,b) memcmp(a,b, BD_ADDR_LEN)
#define BD_ADDR_COPY(dest,src) memcpy(dest,src,BD_ADDR_LEN)
#ifdef EMBEDDED
void bzero(void *s, uint32_t n);
#endif
#if defined __cplusplus
}
#endif

Binary file not shown.

View File

@ -0,0 +1,890 @@
/*
* This file is part of iMAME4all.
*
* Copyright (C) 2010 David Valdeita (Seleuco)
*
* based on:
*
* wiiuse
*
* Written By:
* Michael Laforest < para >
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
*
* Copyright 2006-2007
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, as a special exception, Seleuco
* gives permission to link the code of this program with
* the MAME library (or with modified versions of MAME that use the
* same license as MAME), and distribute linked combinations including
* the two. You must obey the GNU General Public License in all
* respects for all of the code used other than MAME. If you modify
* this file, you may extend this exception to your version of the
* file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include "btstack/btstack.h"
#include "wiimote.h"
//int num_of_joys = 0;
struct wiimote_t joys[4];
extern int g_pref_wii_DZ_value;
#define STICK4WAY (myosd_waysStick == 4 && myosd_inGame)
#define STICK2WAY (myosd_waysStick == 2 && myosd_inGame)
int wiimote_send(struct wiimote_t* wm, byte report_type, byte* msg, int len);
int wiimote_read_data(struct wiimote_t* wm, unsigned int addr, unsigned short len);
int wiimote_write_data(struct wiimote_t* wm, unsigned int addr, byte* data, byte len);
void wiimote_set_leds(struct wiimote_t* wm, int leds);
int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len);
void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg);
int wiimote_remove(uint16_t source_cid, bd_addr_t *addr){
int i = 0;
int unid = -1;
int found = 0;
for(;i<myosd_num_of_joys;i++)
{
if(joys[i].c_source_cid==source_cid && !found)
{
found=1;
struct wiimote_t *wm = NULL;
wm = &joys[i];
if(WIIMOTE_DBG)printf("%02x:%02x:%02x:%02x:%02x:%02x\n",wm->addr[0], wm->addr[1], wm->addr[2],wm->addr[3], wm->addr[4], wm->addr[5]);
memcpy(addr,&(wm->addr),BD_ADDR_LEN);
unid = wm->unid;
continue;
}
if(found)
{
memcpy(&joys[i-1],&joys[i],sizeof(struct wiimote_t ));
joys[i-1].unid = i-1;
struct wiimote_t *wm = NULL;
wm = &joys[i-1];
if(wm->unid==0)
wiimote_set_leds(wm, WIIMOTE_LED_1);
else if(wm->unid==1)
wiimote_set_leds(wm, WIIMOTE_LED_2);
else if(wm->unid==2)
wiimote_set_leds(wm, WIIMOTE_LED_3);
else if(wm->unid==3)
wiimote_set_leds(wm, WIIMOTE_LED_4);
}
}
if(found)
{
myosd_num_of_joys--;
if(WIIMOTE_DBG)printf("NUM JOYS %d\n",myosd_num_of_joys);
return unid;
}
return unid;
}
/**
* @brief Find a wiimote_t structure by its source_cid.
*
* @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* wiimote_get_by_source_cid(uint16_t source_cid){
int i = 0;
for (; i < myosd_num_of_joys; ++i) {
if(WIIMOTE_DBG)printf("0x%02x 0x%02x\n",joys[i].i_source_cid,source_cid);
if (joys[i].i_source_cid == source_cid)
return &joys[i];
}
return NULL;
}
/**
* @brief Request the wiimote controller status.
*
* @param wm Pointer to a wiimote_t structure.
*
* Controller status includes: battery level, LED status, expansions
*/
void wiimote_status(struct wiimote_t* wm) {
byte buf = 0;
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
return;
if(WIIMOTE_DBG)printf("Requested wiimote status.\n");
wiimote_send(wm, WM_CMD_CTRL_STATUS, &buf, 1);
}
void wiimote_data_report(struct wiimote_t* wm, byte type) {
byte buf[2] = {0x0,0x0};
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
return;
buf[1] = type;
//CUIDADO es un &buf?
wiimote_send(wm, WM_CMD_REPORT_TYPE, buf, 2);
}
/**
* @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 wiimote_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);
buf = wm->leds;
wiimote_send(wm, WM_CMD_LED, &buf, 1);
}
/**
* @brief Find what buttons are pressed.
*
* @param wm Pointer to a wiimote_t structure.
* @param msg The message specified in the event packet.
*/
void wiimote_pressed_buttons(struct wiimote_t* wm, byte* msg) {
short now;
/* convert to big endian */
now = BIG_ENDIAN_SHORT(*(short*)msg) & WIIMOTE_BUTTON_ALL;
/* buttons pressed now */
wm->btns = now;
}
/**
* @brief Handle data from the expansion.
*
* @param wm A pointer to a wiimote_t structure.
* @param msg The message specified in the event packet for the expansion.
*/
void wiimote_handle_expansion(struct wiimote_t* wm, byte* msg) {
switch (wm->exp.type) {
case EXP_CLASSIC:
classic_ctrl_event(&wm->exp.classic, msg);
break;
default:
break;
}
}
/**
* @brief Get initialization data from the wiimote.
*
* @param wm Pointer to a wiimote_t structure.
* @param data unused
* @param len unused
*
* When first called for a wiimote_t structure, a request
* is sent to the wiimote for initialization information.
* This includes factory set accelerometer data.
* The handshake will be concluded when the wiimote responds
* with this data.
*/
int wiimote_handshake(struct wiimote_t* wm, byte event, byte* data, unsigned short len) {
if (!wm) return 0;
while(1)
{
if(WIIMOTE_DBG)printf("Handshake %d\n",wm->handshake_state);
switch (wm->handshake_state) {
case 0://no ha habido nunca handshake, debemos forzar un mensaje de staus para ver que pasa.
{
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
wiimote_set_leds(wm, WIIMOTE_LED_NONE);
/* request the status of the wiimote to see if there is an expansion */
wiimote_status(wm);
wm->handshake_state=1;
return 0;
}
case 1://estamos haciendo handshake o bien se necesita iniciar un nuevo handshake ya que se inserta(quita una expansion.
{
int attachment = 0;
if(event != WM_RPT_CTRL_STATUS)
return 0;
/* is an attachment connected to the expansion port? */
if ((data[2] & WM_CTRL_STATUS_BYTE1_ATTACHMENT) == WM_CTRL_STATUS_BYTE1_ATTACHMENT)
{
attachment = 1;
}
if(WIIMOTE_DBG)printf("attachment %d %d\n",attachment,WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP));
/* expansion port */
if (attachment && !WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP);
/* send the initialization code for the attachment */
if(WIIMOTE_DBG)printf("haciendo el handshake de la expansion\n");
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE))
{
if(WIIMOTE_DBG)printf("rehandshake\n");
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);//forzamos un handshake por si venimos de un hanshake completo
}
byte buf;
//Old way. initialize the extension was by writing the single encryption byte 0x00 to 0x(4)A40040
//buf = 0x00;
//wiimote_write_data(wm, WM_EXP_MEM_ENABLE, &buf, 1);
//NEW WAY 0x55 to 0x(4)A400F0, then writing 0x00 to 0x(4)A400FB. (support clones)
buf = 0x55;
wiimote_write_data(wm, 0x04A400F0, &buf, 1);
usleep(100000);
buf = 0x00;
wiimote_write_data(wm, 0x04A400FB, &buf, 1);
//check extension type!
usleep(100000);
wiimote_read_data(wm, WM_EXP_MEM_CALIBR+220, 4);
//wiimote_read_data(wm, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN);
wm->handshake_state = 4;
return 0;
} else if (!attachment && WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) {
/* attachment removed */
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
wm->exp.type = EXP_NONE;
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE))
{
if(WIIMOTE_DBG)printf("rehandshake\n");
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);//forzamos un handshake por si venimos de un hanshake completo
}
}
if(!attachment && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE))
{
wm->handshake_state = 2;
continue;
}
return 0;
}
case 2://find handshake no expansion
{
if(WIIMOTE_DBG)printf("Finalizado HANDSHAKE SIN EXPANSION\n");
wiimote_data_report(wm,WM_RPT_BTN);
wm->handshake_state = 6;
continue;
}
case 3://find handshake expansion
{
if(WIIMOTE_DBG)printf("Finalizado HANDSHAKE CON EXPANSION\n");
wiimote_data_report(wm,WM_RPT_BTN_EXP);
wm->handshake_state = 6;
continue;
}
case 4:
{
if(event != WM_RPT_READ)
return 0;
int id = BIG_ENDIAN_LONG(*(int*)(data));
if(WIIMOTE_DBG)printf("Expansion id=0x%04x\n",id);
if(id!=/*EXP_ID_CODE_CLASSIC_CONTROLLER*/0xa4200101)
{
wm->handshake_state = 2;
//WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
continue;
}
else
{
usleep(100000);
wiimote_read_data(wm, WM_EXP_MEM_CALIBR, 16);//pedimos datos de calibracion del JOY!
wm->handshake_state = 5;
}
return 0;
}
case 5:
{
if(event != WM_RPT_READ)
return 0;
classic_ctrl_handshake(wm, &wm->exp.classic, data,len);
wm->handshake_state = 3;
continue;
}
case 6:
{
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
wm->handshake_state = 1;
if(wm->unid==0)
wiimote_set_leds(wm, WIIMOTE_LED_1);
else if(wm->unid==1)
wiimote_set_leds(wm, WIIMOTE_LED_2);
else if(wm->unid==2)
wiimote_set_leds(wm, WIIMOTE_LED_3);
else if(wm->unid==3)
wiimote_set_leds(wm, WIIMOTE_LED_4);
return 1;
}
default:
{
break;
}
}
}
}
/**
* @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 wiimote.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 wiimote_send(struct wiimote_t* wm, byte report_type, byte* msg, int len) {
byte buf[32];
buf[0] = WM_SET_REPORT | WM_BT_OUTPUT;
buf[1] = report_type;
memcpy(buf+2, msg, len);
if(WIIMOTE_DBG)
{
int x = 2;
printf("[DEBUG] (id %i) SEND: (%x) %.2x ", wm->unid, buf[0], buf[1]);
for (; x < len+2; ++x)
printf("%.2x ", buf[x]);
printf("\n");
}
bt_send_l2cap( wm->c_source_cid, buf, len+2);
return 1;
}
/**
* @brief Read data from the wiimote (event version).
*
* @param wm Pointer to a wiimote_t structure.
* @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 wiimote_read_data(struct wiimote_t* wm, unsigned int addr, unsigned short len) {
//No puden ser mas de 16 lo leido o vendra en trozos!
if (!wm || !WIIMOTE_IS_CONNECTED(wm))
return 0;
if (!len /*|| len > 16*/)
return 0;
byte buf[6];
/* the offset is in big endian */
*(int*)(buf) = BIG_ENDIAN_LONG(addr);
/* the length is in big endian */
*(short*)(buf + 4) = BIG_ENDIAN_SHORT(len);
if(WIIMOTE_DBG)printf("Request read at address: 0x%x length: %i", addr, len);
wiimote_send(wm, WM_CMD_READ_DATA, buf, 6);
return 1;
}
/**
* @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 wiimote_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;
if(WIIMOTE_DBG)printf("Writing %i bytes to memory location 0x%x...\n", len, addr);
if(WIIMOTE_DBG)
{
int i = 0;
printf("Write data is: ");
for (; i < len; ++i)
printf("%x ", data[i]);
printf("\n");
}
/* the offset is in big endian */
*(int*)(buf) = BIG_ENDIAN_LONG(addr);
/* length */
*(byte*)(buf + 4) = len;
/* data */
memcpy(buf + 5, data, len);
wiimote_send(wm, WM_CMD_WRITE_DATA, buf, 21);
return 1;
}
/////////////////////// CLASSIC /////////////////
static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now);
void calc_joystick_state(struct joystick_t* js, float x, float y);
/**
* @brief Handle the handshake data from the classic controller.
*
* @param cc A pointer to a classic_ctrl_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 classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte* data, unsigned short len) {
int i;
int offset = 0;
cc->btns = 0;
cc->r_shoulder = 0;
cc->l_shoulder = 0;
/* decrypt data */
/*
for (i = 0; i < len; ++i)
data[i] = (data[i] ^ 0x17) + 0x17;
*/
if(WIIMOTE_DBG)
{
int x = 0;
printf("[DECRIPTED]");
for (; x < len; x++)
printf("%.2x ", data[x]);
printf("\n");
}
/*
if (data[offset] == 0xFF)
{
return 0;//ERROR!
}
*/
/* joystick stuff */
if (data[offset] != 0xFF && data[offset] != 0x00)
{
cc->ljs.max.x = data[0 + offset] / 4;
cc->ljs.min.x = data[1 + offset] / 4;
cc->ljs.center.x = data[2 + offset] / 4;
cc->ljs.max.y = data[3 + offset] / 4;
cc->ljs.min.y = data[4 + offset] / 4;
cc->ljs.center.y = data[5 + offset] / 4;
cc->rjs.max.x = data[6 + offset] / 8;
cc->rjs.min.x = data[7 + offset] / 8;
cc->rjs.center.x = data[8 + offset] / 8;
cc->rjs.max.y = data[9 + offset] / 8;
cc->rjs.min.y = data[10 + offset] / 8;
cc->rjs.center.y = data[11 + offset] / 8;
}
else
{
cc->ljs.max.x = 55;
cc->ljs.min.x = 5;
cc->ljs.center.x = 30;
cc->ljs.max.y = 55;
cc->ljs.min.y = 5;
cc->ljs.center.y = 30;
cc->rjs.max.x = 30;
cc->rjs.min.x = 0;
cc->rjs.center.x = 15;
cc->rjs.max.y = 30;
cc->rjs.min.y = 0;
cc->rjs.center.y = 15;
}
/* handshake done */
wm->exp.type = EXP_CLASSIC;
return 1;
}
/**
* @brief Handle classic controller event.
*
* @param cc A pointer to a classic_ctrl_t structure.
* @param msg The message specified in the event packet.
*/
void classic_ctrl_event(struct classic_ctrl_t* cc, byte* msg) {
int i, lx, ly, rx, ry;
byte l, r;
/* decrypt data */
/*
for (i = 0; i < 6; ++i)
msg[i] = (msg[i] ^ 0x17) + 0x17;
*/
classic_ctrl_pressed_buttons(cc, BIG_ENDIAN_SHORT(*(short*)(msg + 4)));
/* left/right buttons */
l = (((msg[2] & 0x60) >> 2) | ((msg[3] & 0xE0) >> 5));
r = (msg[3] & 0x1F);
/*
* TODO - LR range hardcoded from 0x00 to 0x1F.
* This is probably in the calibration somewhere.
*/
cc->r_shoulder = ((float)r / 0x1F);
cc->l_shoulder = ((float)l / 0x1F);
/* calculate joystick orientation */
lx = (msg[0] & 0x3F);
ly = (msg[1] & 0x3F);
rx = ((msg[0] & 0xC0) >> 3) | ((msg[1] & 0xC0) >> 5) | ((msg[2] & 0x80) >> 7);
ry = (msg[2] & 0x1F);
if(WIIMOTE_DBG)
printf("lx ly rx ry %d %d %d %d\n",lx,ly,rx,ry);
calc_joystick_state(&cc->ljs, lx, ly);
calc_joystick_state(&cc->rjs, rx, ry);
/*
printf("classic L button pressed: %f\n", cc->l_shoulder);
printf("classic R button pressed: %f\n", cc->r_shoulder);
printf("classic left joystick angle: %f\n", cc->ljs.ang);
printf("classic left joystick magnitude: %f\n", cc->ljs.mag);
printf("classic right joystick angle: %f\n", cc->rjs.ang);
printf("classic right joystick magnitude: %f\n", cc->rjs.mag);
*/
}
/**
* @brief Find what buttons are pressed.
*
* @param cc A pointer to a classic_ctrl_t structure.
* @param msg The message byte specified in the event packet.
*/
static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now) {
/* message is inverted (0 is active, 1 is inactive) */
now = ~now & CLASSIC_CTRL_BUTTON_ALL;
/* buttons pressed now */
cc->btns = now;
}
/**
* @brief Calculate the angle and magnitude of a joystick.
*
* @param js [out] Pointer to a joystick_t structure.
* @param x The raw x-axis value.
* @param y The raw y-axis value.
*/
void calc_joystick_state(struct joystick_t* js, float x, float y) {
float rx, ry, ang;
/*
* Since the joystick center may not be exactly:
* (min + max) / 2
* Then the range from the min to the center and the center to the max
* may be different.
* Because of this, depending on if the current x or y value is greater
* or less than the assoicated axis center value, it needs to be interpolated
* between the center and the minimum or maxmimum rather than between
* the minimum and maximum.
*
* So we have something like this:
* (x min) [-1] ---------*------ [0] (x center) [0] -------- [1] (x max)
* Where the * is the current x value.
* The range is therefore -1 to 1, 0 being the exact center rather than
* the middle of min and max.
*/
if (x == js->center.x)
rx = 0;
else if (x >= js->center.x)
rx = ((float)(x - js->center.x) / (float)(js->max.x - js->center.x));
else
rx = ((float)(x - js->min.x) / (float)(js->center.x - js->min.x)) - 1.0f;
if (y == js->center.y)
ry = 0;
else if (y >= js->center.y)
ry = ((float)(y - js->center.y) / (float)(js->max.y - js->center.y));
else
ry = ((float)(y - js->min.y) / (float)(js->center.y - js->min.y)) - 1.0f;
/* calculate the joystick angle and magnitude */
ang = RAD_TO_DEGREE(atanf(ry / rx));
ang -= 90.0f;
if (rx < 0.0f)
ang -= 180.0f;
js->ang = absf(ang);
js->mag = (float) sqrt((rx * rx) + (ry * ry));
js->rx = rx;
js->ry = ry;
}
////////////////////////////////////////////////////////////
extern float joy_analog_x[4];
extern float joy_analog_y[4];
int iOS_wiimote_check (struct wiimote_t *wm)
{
return wm->btns;
}
#if 0
joy_analog_x[wm->unid]=0.0f;
joy_analog_y[wm->unid]=0.0f;
if (1) {
if (wm->exp.type == EXP_CLASSIC) {
float deadZone;
switch(g_pref_wii_DZ_value)
{
case 0: deadZone = 0.12f;break;
case 1: deadZone = 0.15f;break;
case 2: deadZone = 0.17f;break;
case 3: deadZone = 0.2f;break;
case 4: deadZone = 0.3f;break;
case 5: deadZone = 0.4f;break;
}
//printf("deadzone %f\n",deadZone);
struct classic_ctrl_t* cc = (classic_ctrl_t*)&wm->exp.classic;
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_ZL)) joyExKey |= MYOSD_R1;
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_B)) joyExKey |= MYOSD_X;
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_Y)) joyExKey |= MYOSD_A;
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_A)) joyExKey |= MYOSD_B;
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_X)) joyExKey |= MYOSD_Y;
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_ZR)) joyExKey |= MYOSD_L1;
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_UP)){
if(!STICK2WAY &&
!(STICK4WAY && (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_LEFT) ||
(IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_RIGHT)))))
joyExKey |= MYOSD_UP;
}
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_DOWN)){
if(!STICK2WAY &&
!(STICK4WAY && (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_LEFT) ||
(IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_RIGHT)))))
joyExKey |= MYOSD_DOWN;
}
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_LEFT)) joyExKey |= MYOSD_LEFT;
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_RIGHT)) joyExKey |= MYOSD_RIGHT;
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_FULL_L)) joyExKey |= MYOSD_L1;
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_MINUS)) joyExKey |= MYOSD_SELECT;
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_HOME)) {//myosd_exitGame = 0;usleep(50000);
myosd_exitGame = 1;}
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_PLUS)) joyExKey |= MYOSD_START;
if (IS_PRESSED(cc, CLASSIC_CTRL_BUTTON_FULL_R)) joyExKey |= MYOSD_R1;
if(cc->ljs.mag >= deadZone)
{
joy_analog_x[wm->unid] = ( cc->ljs.rx > 1.0 ) ? 1.0 : ( cc->ljs.rx < -1.0 ) ? -1.0 : cc->ljs.rx;
joy_analog_y[wm->unid] = ( cc->ljs.ry > 1.0 ) ? 1.0 : ( cc->ljs.ry < -1.0 ) ? -1.0 : cc->ljs.ry;
float v = cc->ljs.ang;
if(STICK2WAY)
{
if( v < 180){
joyExKey |= MYOSD_RIGHT;
//printf("Right\n");
}
else if ( v >= 180){
joyExKey |= MYOSD_LEFT;
//printf("Left\n");
}
}
else if(STICK4WAY)
{
if(v >= 315 || v < 45){
joyExKey |= MYOSD_UP;
//printf("Up\n");
}
else if (v >= 45 && v < 135){
joyExKey |= MYOSD_RIGHT;
//printf("Right\n");
}
else if (v >= 135 && v < 225){
joyExKey |= MYOSD_DOWN;
//printf("Down\n");
}
else if (v >= 225 && v < 315){
joyExKey |= MYOSD_LEFT;
//printf("Left\n");
}
}
else
{
if( v >= 330 || v < 30){
joyExKey |= MYOSD_UP;
//printf("Up\n");
}
else if ( v >= 30 && v <60 ) {
joyExKey |= MYOSD_UP;joyExKey |= MYOSD_RIGHT;
//printf("UpRight\n");
}
else if ( v >= 60 && v < 120 ){
joyExKey |= MYOSD_RIGHT;
//printf("Right\n");
}
else if ( v >= 120 && v < 150 ){
joyExKey |= MYOSD_RIGHT;joyExKey |= MYOSD_DOWN;
//printf("RightDown\n");
}
else if ( v >= 150 && v < 210 ){
joyExKey |= MYOSD_DOWN;
//printf("Down\n");
}
else if ( v >= 210 && v < 240 ){
joyExKey |= MYOSD_DOWN;joyExKey |= MYOSD_LEFT;
//printf("DownLeft\n");
}
else if ( v >= 240 && v < 300 ){
joyExKey |= MYOSD_LEFT;
//printf("Left\n");
}
else if ( v >= 300 && v < 330 ){
joyExKey |= MYOSD_LEFT;
joyExKey |= MYOSD_UP;
//printf("LeftUp\n");
}
}
}
if(cc->rjs.mag >= deadZone)
{
float v = cc->rjs.ang;
if( v >= 330 || v < 30){
joyExKey |= MYOSD_Y;
//printf("Y\n");
}
else if ( v >= 30 && v <60 ) {
joyExKey |= MYOSD_Y;joyExKey |= MYOSD_B;
//printf("Y B\n");
}
else if ( v >= 60 && v < 120 ){
joyExKey |= MYOSD_B;
//printf("B\n");
}
else if ( v >= 120 && v < 150 ){
joyExKey |= MYOSD_B;joyExKey |= MYOSD_X;
//printf("B X\n");
}
else if ( v >= 150 && v < 210 ){
joyExKey |= MYOSD_X;
//printf("X\n");
}
else if ( v >= 210 && v < 240 ){
joyExKey |= MYOSD_X;joyExKey |= MYOSD_A;
//printf("X A\n");
}
else if ( v >= 240 && v < 300 ){
joyExKey |= MYOSD_A;
//printf("A\n");
}
else if ( v >= 300 && v < 330 ){
joyExKey |= MYOSD_A;joyExKey |= MYOSD_Y;
//printf("A Y\n");
}
}
/*
printf("classic L button pressed: %f\n", cc->l_shoulder);
printf("classic R button pressed: %f\n", cc->r_shoulder);
printf("classic left joystick angle: %f\n", cc->ljs.ang);
printf("classic left joystick magnitude: %f\n", cc->ljs.mag);
printf("classic left joystick rx: %f\n", cc->ljs.rx);
printf("classic left joystick ry: %f\n", cc->ljs.ry);
printf("classic right joystick angle: %f\n", cc->rjs.ang);
printf("classic right joystick magnitude: %f\n", cc->rjs.mag);
printf("classic right rx: %f\n", cc->rjs.rx);
printf("classic right ry: %f\n", cc->rjs.ry);
*/
}
return joyExKey;
} else {
joyExKey = 0;
return joyExKey;
}
}
#endif

View File

@ -0,0 +1,294 @@
/*
* This file is part of iMAME4all.
*
* Copyright (C) 2010 David Valdeita (Seleuco)
*
* based on:
*
* wiiuse
*
* Written By:
* Michael Laforest < para >
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
*
* Copyright 2006-2007
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* In addition, as a special exception, Seleuco
* gives permission to link the code of this program with
* the MAME library (or with modified versions of MAME that use the
* same license as MAME), and distribute linked combinations including
* the two. You must obey the GNU General Public License in all
* respects for all of the code used other than MAME. If you modify
* this file, you may extend this exception to your version of the
* file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*/
#ifndef __WIIMOTE_H__
#define __WIIMOTE_H__
#include "btstack/utils.h"
#if defined(__cplusplus)
extern "C" {
#endif
typedef unsigned char byte;
typedef char sbyte;
#define WIIMOTE_PI 3.14159265
#define WIIMOTE_DBG 0
/* Convert between radians and degrees */
#define RAD_TO_DEGREE(r) ((r * 180.0f) / WIIMOTE_PI)
#define DEGREE_TO_RAD(d) (d * (WIIMOTE_PI / 180.0f))
/* Convert to big endian */
#define BIG_ENDIAN_LONG(i) (htonl(i))
#define BIG_ENDIAN_SHORT(i) (htons(i))
#define absf(x) ((x >= 0) ? (x) : (x * -1.0f))
#define diff_f(x, y) ((x >= y) ? (absf(x - y)) : (absf(y - x)))
/* wiimote state flags*/
#define WIIMOTE_STATE_DEV_FOUND 0x0001
#define WIIMOTE_STATE_HANDSHAKE 0x0002 /* actual connection exists but no handshake yet */
#define WIIMOTE_STATE_HANDSHAKE_COMPLETE 0x0004
#define WIIMOTE_STATE_CONNECTED 0x0008
#define WIIMOTE_STATE_EXP 0x0040
/* Communication channels */
#define WM_OUTPUT_CHANNEL 0x11
#define WM_INPUT_CHANNEL 0x13
#define WM_SET_REPORT 0x50
/* commands */
#define WM_CMD_LED 0x11
#define WM_CMD_REPORT_TYPE 0x12
#define WM_CMD_RUMBLE 0x13
#define WM_CMD_IR 0x13
#define WM_CMD_CTRL_STATUS 0x15
#define WM_CMD_WRITE_DATA 0x16
#define WM_CMD_READ_DATA 0x17
#define WM_CMD_IR_2 0x1A
/* input report ids */
#define WM_RPT_CTRL_STATUS 0x20
#define WM_RPT_READ 0x21
#define WM_RPT_WRITE 0x22
#define WM_RPT_BTN 0x30
#define WM_RPT_BTN_ACC 0x31
#define WM_RPT_BTN_ACC_IR 0x33
#define WM_RPT_BTN_EXP 0x34
#define WM_RPT_BTN_ACC_EXP 0x35
#define WM_RPT_BTN_IR_EXP 0x36
#define WM_RPT_BTN_ACC_IR_EXP 0x37
#define WM_BT_INPUT 0x01
#define WM_BT_OUTPUT 0x02
/* controller status stuff */
#define WM_MAX_BATTERY_CODE 0xC8
#define EXP_ID_CODE_CLASSIC_CONTROLLER 0x9A1EFDFD
/* offsets in wiimote memory */
#define WM_MEM_OFFSET_CALIBRATION 0x16
#define WM_EXP_MEM_BASE 0x04A40000
#define WM_EXP_MEM_ENABLE 0x04A40040
#define WM_EXP_MEM_CALIBR 0x04A40020
#define EXP_HANDSHAKE_LEN 224
/* controller status flags for the first message byte */
/* bit 1 is unknown */
#define WM_CTRL_STATUS_BYTE1_ATTACHMENT 0x02
#define WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED 0x04
#define WM_CTRL_STATUS_BYTE1_IR_ENABLED 0x08
#define WM_CTRL_STATUS_BYTE1_LED_1 0x10
#define WM_CTRL_STATUS_BYTE1_LED_2 0x20
#define WM_CTRL_STATUS_BYTE1_LED_3 0x40
#define WM_CTRL_STATUS_BYTE1_LED_4 0x80
/* led bit masks */
#define WIIMOTE_LED_NONE 0x00
#define WIIMOTE_LED_1 0x10
#define WIIMOTE_LED_2 0x20
#define WIIMOTE_LED_3 0x40
#define WIIMOTE_LED_4 0x80
/* button codes */
#define WIIMOTE_BUTTON_TWO 0x0001
#define WIIMOTE_BUTTON_ONE 0x0002
#define WIIMOTE_BUTTON_B 0x0004
#define WIIMOTE_BUTTON_A 0x0008
#define WIIMOTE_BUTTON_MINUS 0x0010
#define WIIMOTE_BUTTON_ZACCEL_BIT6 0x0020
#define WIIMOTE_BUTTON_ZACCEL_BIT7 0x0040
#define WIIMOTE_BUTTON_HOME 0x0080
#define WIIMOTE_BUTTON_LEFT 0x0100
#define WIIMOTE_BUTTON_RIGHT 0x0200
#define WIIMOTE_BUTTON_DOWN 0x0400
#define WIIMOTE_BUTTON_UP 0x0800
#define WIIMOTE_BUTTON_PLUS 0x1000
#define WIIMOTE_BUTTON_ZACCEL_BIT4 0x2000
#define WIIMOTE_BUTTON_ZACCEL_BIT5 0x4000
#define WIIMOTE_BUTTON_UNKNOWN 0x8000
#define WIIMOTE_BUTTON_ALL 0x1F9F
/* classic controller button codes */
#define CLASSIC_CTRL_BUTTON_UP 0x0001
#define CLASSIC_CTRL_BUTTON_LEFT 0x0002
#define CLASSIC_CTRL_BUTTON_ZR 0x0004
#define CLASSIC_CTRL_BUTTON_X 0x0008
#define CLASSIC_CTRL_BUTTON_A 0x0010
#define CLASSIC_CTRL_BUTTON_Y 0x0020
#define CLASSIC_CTRL_BUTTON_B 0x0040
#define CLASSIC_CTRL_BUTTON_ZL 0x0080
#define CLASSIC_CTRL_BUTTON_FULL_R 0x0200
#define CLASSIC_CTRL_BUTTON_PLUS 0x0400
#define CLASSIC_CTRL_BUTTON_HOME 0x0800
#define CLASSIC_CTRL_BUTTON_MINUS 0x1000
#define CLASSIC_CTRL_BUTTON_FULL_L 0x2000
#define CLASSIC_CTRL_BUTTON_DOWN 0x4000
#define CLASSIC_CTRL_BUTTON_RIGHT 0x8000
#define CLASSIC_CTRL_BUTTON_ALL 0xFEFF
/* expansion codes */
#define EXP_NONE 0
#define EXP_CLASSIC 2
/**
* @struct vec2b_t
* @brief Unsigned x,y byte vector.
*/
typedef struct vec2b_t {
byte x, y;
} vec2b_t;
/**
* @struct joystick_t
* @brief Joystick calibration structure.
*
* The angle \a ang is relative to the positive y-axis into quadrant I
* and ranges from 0 to 360 degrees. So if the joystick is held straight
* upwards then angle is 0 degrees. If it is held to the right it is 90,
* down is 180, and left is 270.
*
* The magnitude \a mag is the distance from the center to where the
* joystick is being held. The magnitude ranges from 0 to 1.
* If the joystick is only slightly tilted from the center the magnitude
* will be low, but if it is closer to the outter edge the value will
* be higher.
*/
typedef struct joystick_t {
struct vec2b_t max; /**< maximum joystick values */
struct vec2b_t min; /**< minimum joystick values */
struct vec2b_t center; /**< center joystick values */
float ang; /**< angle the joystick is being held */
float mag; /**< magnitude of the joystick (range 0-1) */
float rx, ry;
} joystick_t;
/**
* @struct classic_ctrl_t
* @brief Classic controller expansion device.
*/
typedef struct classic_ctrl_t {
short btns; /**< what buttons have just been pressed */
float r_shoulder; /**< right shoulder button (range 0-1) */
float l_shoulder; /**< left shoulder button (range 0-1) */
struct joystick_t ljs; /**< left joystick calibration */
struct joystick_t rjs; /**< right joystick calibration */
} classic_ctrl_t;
/**
* @struct expansion_t
* @brief Generic expansion device plugged into wiimote.
*/
typedef struct expansion_t {
int type; /**< type of expansion attached */
union {
struct classic_ctrl_t classic;
};
} expansion_t;
/**
* @struct wiimote_t
* @brief Wiimote structure.
*/
typedef struct wiimote_t {
int unid; /**< user specified id */
uint16_t wiiMoteConHandle;
uint16_t i_source_cid;
uint16_t c_source_cid;
bd_addr_t addr;
int state; /**< various state flags */
byte leds; /**< currently lit leds */
float battery_level; /**< battery level */
byte handshake_state; /**< the state of the connection handshake */
struct expansion_t exp; /**< wiimote expansion device */
unsigned short btns; /**< what buttons have just been pressed */
} wiimote;
/**
* @brief Check if a button is pressed.
* @param dev Pointer to a wiimote_t or expansion structure.
* @param button The button you are interested in.
* @return 1 if the button is pressed, 0 if not.
*/
#define IS_PRESSED(dev, button) ((dev->btns & button) == button)
/* macro to manage states */
#define WIIMOTE_IS_SET(wm, s) ((wm->state & (s)) == (s))
#define WIIMOTE_ENABLE_STATE(wm, s) (wm->state |= (s))
#define WIIMOTE_DISABLE_STATE(wm, s) (wm->state &= ~(s))
#define WIIMOTE_TOGGLE_STATE(wm, s) ((wm->state & (s)) ? WIIMOTE_DISABLE_STATE(wm, s) : WIIMOTE_ENABLE_STATE(wm, s))
#define WIIMOTE_IS_CONNECTED(wm) (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED))
extern struct wiimote_t joys[4];
extern int myosd_num_of_joys;
//devuelve un int haciendo polling de lo guardado en el wiimote
int iOS_wiimote_check (struct wiimote_t *wm);
int wiimote_remove(uint16_t source_cid, bd_addr_t *addr);
struct wiimote_t* wiimote_get_by_source_cid(uint16_t source_cid);
int wiimote_handshake(struct wiimote_t* wm, byte event, byte* data, unsigned short len);
void wiimote_status(struct wiimote_t* wm);
void wiimote_data_report(struct wiimote_t* wm, byte type);
void wiimote_pressed_buttons(struct wiimote_t* wm, byte* msg);
void wiimote_handle_expansion(struct wiimote_t* wm, byte* msg);
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -78,7 +78,7 @@
<string key="NSFrame">{{20, 20}, {260, 44}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="562513162"/>
<reference key="NSNextKeyView" ref="1033465661"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
@ -238,6 +238,29 @@
<reference ref="4"/>
</array>
</object>
<object class="IBUIButton" id="1033465661">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{20, 71}, {260, 44}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="562513162"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Connect WiiMotes</string>
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
</object>
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
<reference key="IBUIFontDescription" ref="230061939"/>
<reference key="IBUIFont" ref="495303882"/>
</object>
</array>
<string key="NSFrame">{{0, 20}, {300, 300}}</string>
<reference key="NSSuperview"/>
@ -318,6 +341,15 @@
</object>
<int key="connectionID">139</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">conntectWiimotes:</string>
<reference key="source" ref="1033465661"/>
<reference key="destination" ref="372490531"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">147</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
@ -539,6 +571,54 @@
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="65927411">
<reference key="firstItem" ref="1033465661"/>
<int key="firstAttribute">5</int>
<int key="relation">0</int>
<reference key="secondItem" ref="191373211"/>
<int key="secondAttribute">5</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="191373211"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="402510427">
<reference key="firstItem" ref="191373211"/>
<int key="firstAttribute">6</int>
<int key="relation">0</int>
<reference key="secondItem" ref="1033465661"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="191373211"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="828923997">
<reference key="firstItem" ref="1033465661"/>
<int key="firstAttribute">3</int>
<int key="relation">0</int>
<reference key="secondItem" ref="38801877"/>
<int key="secondAttribute">4</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">8</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="191373211"/>
<int key="scoringType">6</int>
<float key="scoringTypeFloat">24</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="38515434">
<reference key="firstItem" ref="191373211"/>
<int key="firstAttribute">6</int>
@ -593,6 +673,7 @@
<reference ref="58186559"/>
<reference ref="562513162"/>
<reference ref="61755535"/>
<reference ref="1033465661"/>
</array>
<reference key="parent" ref="0"/>
</object>
@ -766,6 +847,27 @@
<reference key="object" ref="201787259"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">140</int>
<reference key="object" ref="1033465661"/>
<array class="NSMutableArray" key="children"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">142</int>
<reference key="object" ref="828923997"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">143</int>
<reference key="object" ref="402510427"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">146</int>
<reference key="object" ref="65927411"/>
<reference key="parent" ref="191373211"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
@ -778,6 +880,9 @@
<reference ref="89828506"/>
<reference ref="509206074"/>
<reference ref="38515434"/>
<reference ref="828923997"/>
<reference ref="402510427"/>
<reference ref="65927411"/>
<reference ref="804573855"/>
<reference ref="201787259"/>
<reference ref="85952235"/>
@ -815,6 +920,11 @@
<string key="132.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="133.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="135.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="140.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<boolean value="NO" key="140.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="142.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="143.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="146.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="17.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<boolean value="NO" key="17.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="30.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
@ -834,7 +944,7 @@
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">139</int>
<int key="maxID">147</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
@ -849,6 +959,50 @@
<object class="IBPartialClassDescription">
<string key="className">RetroArch_iOS</string>
<string key="superclassName">UIResponder</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="chooseState:">id</string>
<string key="closeGamePressed:">id</string>
<string key="closePauseMenu:">id</string>
<string key="conntectWiimotes:">id</string>
<string key="loadState:">id</string>
<string key="resetGame:">id</string>
<string key="saveState:">id</string>
<string key="showPauseMenu:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="chooseState:">
<string key="name">chooseState:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="closeGamePressed:">
<string key="name">closeGamePressed:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="closePauseMenu:">
<string key="name">closePauseMenu:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="conntectWiimotes:">
<string key="name">conntectWiimotes:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="loadState:">
<string key="name">loadState:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="resetGame:">
<string key="name">resetGame:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="saveState:">
<string key="name">saveState:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="showPauseMenu:">
<string key="name">showPauseMenu:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/RetroArch_iOS.h</string>

View File

@ -17,6 +17,9 @@
#include "rarch_wrapper.h"
#include "general.h"
#include "BTStack/wiimote.h"
#import "BTStack/WiiMoteHelper.h"
#define ALMOST_INVISIBLE .021f
@interface RANavigator : UINavigationController
@ -359,5 +362,11 @@
[self pushViewController:[RASettingsList new] isGame:NO];
}
- (IBAction)conntectWiimotes:(id)sender
{
[WiiMoteHelper startwiimote:_navigator];
}
@end

View File

@ -18,6 +18,7 @@
#include "../../performance.h"
#include "../../general.h"
#include "../../driver.h"
#include "BTStack/wiimote.h"
#define MAX_TOUCH 16
#define MAX_KEYS 256
@ -150,6 +151,23 @@ static int16_t ios_input_state(void *data, const struct retro_keybind **binds, u
switch (device)
{
case RETRO_DEVICE_JOYPAD:
if (myosd_num_of_joys > 0)
{
struct wiimote_t* wm = &joys[0];
switch (id)
{
case RETRO_DEVICE_ID_JOYPAD_A: return IS_PRESSED(wm, WIIMOTE_BUTTON_TWO);
case RETRO_DEVICE_ID_JOYPAD_B: return IS_PRESSED(wm, WIIMOTE_BUTTON_ONE);
case RETRO_DEVICE_ID_JOYPAD_START: return IS_PRESSED(wm, WIIMOTE_BUTTON_PLUS);
case RETRO_DEVICE_ID_JOYPAD_SELECT: return IS_PRESSED(wm, WIIMOTE_BUTTON_MINUS);
case RETRO_DEVICE_ID_JOYPAD_UP: return IS_PRESSED(wm, WIIMOTE_BUTTON_UP);
case RETRO_DEVICE_ID_JOYPAD_DOWN: return IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN);
case RETRO_DEVICE_ID_JOYPAD_LEFT: return IS_PRESSED(wm, WIIMOTE_BUTTON_LEFT);
case RETRO_DEVICE_ID_JOYPAD_RIGHT: return IS_PRESSED(wm, WIIMOTE_BUTTON_RIGHT);
}
}
return l_ios_joypad_device_state(binds, port, id);
case RETRO_DEVICE_ANALOG:
return 0;