diff --git a/ios/RetroArch.xcodeproj/project.pbxproj b/ios/RetroArch.xcodeproj/project.pbxproj index 461c22e844..05944e26d8 100644 --- a/ios/RetroArch.xcodeproj/project.pbxproj +++ b/ios/RetroArch.xcodeproj/project.pbxproj @@ -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 = ""; }; + 9614C6AD16DD7C00000B36EF /* BTDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTDevice.h; sourceTree = ""; }; + 9614C6AE16DD7C00000B36EF /* BTDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTDevice.m; sourceTree = ""; }; + 9614C6AF16DD7C00000B36EF /* BTInquiryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTInquiryViewController.h; sourceTree = ""; }; + 9614C6B016DD7C00000B36EF /* BTInquiryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTInquiryViewController.m; sourceTree = ""; }; + 9614C6B216DD7C00000B36EF /* btstack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = btstack.h; sourceTree = ""; }; + 9614C6B316DD7C00000B36EF /* hci_cmds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hci_cmds.h; sourceTree = ""; }; + 9614C6B416DD7C00000B36EF /* linked_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = linked_list.h; sourceTree = ""; }; + 9614C6B516DD7C00000B36EF /* run_loop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = run_loop.h; sourceTree = ""; }; + 9614C6B616DD7C00000B36EF /* sdp_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sdp_util.h; sourceTree = ""; }; + 9614C6B716DD7C00000B36EF /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; + 9614C6B816DD7C00000B36EF /* libBTstack.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libBTstack.dylib; sourceTree = ""; }; + 9614C6B916DD7C00000B36EF /* WiiMoteHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WiiMoteHelper.h; sourceTree = ""; }; + 9614C6BA16DD7C00000B36EF /* WiiMoteHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WiiMoteHelper.m; sourceTree = ""; }; + 9614C6BF16DD7D54000B36EF /* wiimote.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wiimote.c; sourceTree = ""; }; + 9614C6C016DD7D54000B36EF /* wiimote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wiimote.h; sourceTree = ""; }; 962979EE16C3EA3E00E6DCE0 /* ioseagl_ctx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioseagl_ctx.c; sourceTree = ""; }; 962979F416C43B9500E6DCE0 /* ic_dir.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_dir.png; path = "../android/phoenix/res/drawable-xhdpi/ic_dir.png"; sourceTree = ""; }; 962979F516C43B9500E6DCE0 /* ic_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_file.png; path = "../android/phoenix/res/drawable-xhdpi/ic_file.png"; sourceTree = ""; }; @@ -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 = ""; + }; + 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 = ""; + }; 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", diff --git a/ios/RetroArch/BTStack/BTDevice.h b/ios/RetroArch/BTStack/BTDevice.h new file mode 100644 index 0000000000..43d018cce5 --- /dev/null +++ b/ios/RetroArch/BTStack/BTDevice.h @@ -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 +#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 diff --git a/ios/RetroArch/BTStack/BTDevice.m b/ios/RetroArch/BTStack/BTDevice.m new file mode 100644 index 0000000000..57fbc6df17 --- /dev/null +++ b/ios/RetroArch/BTStack/BTDevice.m @@ -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 diff --git a/ios/RetroArch/BTStack/BTInquiryViewController.h b/ios/RetroArch/BTStack/BTInquiryViewController.h new file mode 100644 index 0000000000..b8638e142b --- /dev/null +++ b/ios/RetroArch/BTStack/BTInquiryViewController.h @@ -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 + +#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 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 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 diff --git a/ios/RetroArch/BTStack/BTInquiryViewController.m b/ios/RetroArch/BTStack/BTInquiryViewController.m new file mode 100644 index 0000000000..d274a6a7d9 --- /dev/null +++ b/ios/RetroArch/BTStack/BTInquiryViewController.m @@ -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 + +#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 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 + diff --git a/ios/RetroArch/BTStack/WiiMoteHelper.h b/ios/RetroArch/BTStack/WiiMoteHelper.h new file mode 100644 index 0000000000..ad263a3ee7 --- /dev/null +++ b/ios/RetroArch/BTStack/WiiMoteHelper.h @@ -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 + +#import "BTInquiryViewController.h" + +@interface WiiMoteHelper : NSObject +{ +} + ++ (void)startwiimote:(UIViewController *)controller; ++ (void)endwiimote; ++ (void)cancelWiiMoteSearch; + +@end + + + + + diff --git a/ios/RetroArch/BTStack/WiiMoteHelper.m b/ios/RetroArch/BTStack/WiiMoteHelper.m new file mode 100644 index 0000000000..8898040797 --- /dev/null +++ b/ios/RetroArch/BTStack/WiiMoteHelper.m @@ -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 +#include +#include + +#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 + diff --git a/ios/RetroArch/BTStack/btstack/btstack.h b/ios/RetroArch/BTStack/btstack/btstack.h new file mode 100644 index 0000000000..04a2e146f4 --- /dev/null +++ b/ios/RetroArch/BTStack/btstack/btstack.h @@ -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 + +#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 diff --git a/ios/RetroArch/BTStack/btstack/hci_cmds.h b/ios/RetroArch/BTStack/btstack/hci_cmds.h new file mode 100644 index 0000000000..cfb36cc7a1 --- /dev/null +++ b/ios/RetroArch/BTStack/btstack/hci_cmds.h @@ -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 + +#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 diff --git a/ios/RetroArch/BTStack/btstack/linked_list.h b/ios/RetroArch/BTStack/btstack/linked_list.h new file mode 100644 index 0000000000..2518094876 --- /dev/null +++ b/ios/RetroArch/BTStack/btstack/linked_list.h @@ -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 diff --git a/ios/RetroArch/BTStack/btstack/run_loop.h b/ios/RetroArch/BTStack/btstack/run_loop.h new file mode 100644 index 0000000000..ea2673d5d4 --- /dev/null +++ b/ios/RetroArch/BTStack/btstack/run_loop.h @@ -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 + +#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 + diff --git a/ios/RetroArch/BTStack/btstack/sdp_util.h b/ios/RetroArch/BTStack/btstack/sdp_util.h new file mode 100644 index 0000000000..fb91038f2e --- /dev/null +++ b/ios/RetroArch/BTStack/btstack/sdp_util.h @@ -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 + +#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 diff --git a/ios/RetroArch/BTStack/btstack/utils.h b/ios/RetroArch/BTStack/btstack/utils.h new file mode 100644 index 0000000000..39064f370b --- /dev/null +++ b/ios/RetroArch/BTStack/btstack/utils.h @@ -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 + +#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 + diff --git a/ios/RetroArch/BTStack/libBTstack.dylib b/ios/RetroArch/BTStack/libBTstack.dylib new file mode 100755 index 0000000000..7e3173a408 Binary files /dev/null and b/ios/RetroArch/BTStack/libBTstack.dylib differ diff --git a/ios/RetroArch/BTStack/wiimote.c b/ios/RetroArch/BTStack/wiimote.c new file mode 100644 index 0000000000..9a6576989f --- /dev/null +++ b/ios/RetroArch/BTStack/wiimote.c @@ -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 +#include +#include +#include +#include + +#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(;iaddr[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 diff --git a/ios/RetroArch/BTStack/wiimote.h b/ios/RetroArch/BTStack/wiimote.h new file mode 100644 index 0000000000..ba58a97659 --- /dev/null +++ b/ios/RetroArch/BTStack/wiimote.h @@ -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 diff --git a/ios/RetroArch/PauseView.xib b/ios/RetroArch/PauseView.xib index f81d6519b1..070ab1125c 100644 --- a/ios/RetroArch/PauseView.xib +++ b/ios/RetroArch/PauseView.xib @@ -78,7 +78,7 @@ {{20, 20}, {260, 44}} - + _NS:9 NO IBIPadFramework @@ -238,6 +238,29 @@ + + + 292 + {{20, 71}, {260, 44}} + + + + _NS:9 + NO + IBIPadFramework + 0 + 0 + 1 + Connect WiiMotes + + + 1 + MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA + + + + + {{0, 20}, {300, 300}} @@ -318,6 +341,15 @@ 139 + + + conntectWiimotes: + + + 7 + + 147 + @@ -539,6 +571,54 @@ 29 3 + + + 5 + 0 + + 5 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 4 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + 6 @@ -593,6 +673,7 @@ + @@ -766,6 +847,27 @@ + + 140 + + + + + + 142 + + + + + 143 + + + + + 146 + + + @@ -778,6 +880,9 @@ + + + @@ -815,6 +920,11 @@ com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin @@ -834,7 +944,7 @@ - 139 + 147 @@ -849,6 +959,50 @@ RetroArch_iOS UIResponder + + id + id + id + id + id + id + id + id + + + + chooseState: + id + + + closeGamePressed: + id + + + closePauseMenu: + id + + + conntectWiimotes: + id + + + loadState: + id + + + resetGame: + id + + + saveState: + id + + + showPauseMenu: + id + + IBProjectSource ./Classes/RetroArch_iOS.h diff --git a/ios/RetroArch/RetroArch_iOS.m b/ios/RetroArch/RetroArch_iOS.m index 2d3282a4e4..005906567e 100644 --- a/ios/RetroArch/RetroArch_iOS.m +++ b/ios/RetroArch/RetroArch_iOS.m @@ -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 diff --git a/ios/RetroArch/ios_input.m b/ios/RetroArch/ios_input.m index 1887539b41..a83b7cb2cf 100644 --- a/ios/RetroArch/ios_input.m +++ b/ios/RetroArch/ios_input.m @@ -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;