From a7497ab4166d2dfb69e527c80abdefb336f9896b Mon Sep 17 00:00:00 2001 From: meancoot Date: Sat, 23 Mar 2013 21:12:29 -0400 Subject: [PATCH] (iOS) Move BTstack into a thread. It may still need synchronization with the input buffers, but shouldn't cause crashes or anything. --- ios/RetroArch.xcodeproj/project.pbxproj | 2 - ios/RetroArch/RetroArch_iOS.m | 14 ++-- ios/RetroArch/input/BTStack/WiiMoteHelper.h | 40 ---------- ios/RetroArch/input/BTStack/WiiMoteHelper.m | 85 +++++---------------- ios/RetroArch/input/BTStack/btdynamic.c | 82 ++++++++++++++++++-- ios/RetroArch/input/BTStack/btdynamic.h | 9 ++- 6 files changed, 109 insertions(+), 123 deletions(-) delete mode 100644 ios/RetroArch/input/BTStack/WiiMoteHelper.h diff --git a/ios/RetroArch.xcodeproj/project.pbxproj b/ios/RetroArch.xcodeproj/project.pbxproj index 56f421b2d0..cb0c1158cb 100644 --- a/ios/RetroArch.xcodeproj/project.pbxproj +++ b/ios/RetroArch.xcodeproj/project.pbxproj @@ -74,7 +74,6 @@ 966B9C9A16E418B7005B61E1 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; 966B9C9E16E418B7005B61E1 /* wiimote.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wiimote.c; sourceTree = ""; }; 966B9C9F16E418B7005B61E1 /* wiimote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wiimote.h; sourceTree = ""; }; - 966B9CA016E418B7005B61E1 /* WiiMoteHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WiiMoteHelper.h; sourceTree = ""; }; 966B9CA116E418B7005B61E1 /* WiiMoteHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WiiMoteHelper.m; sourceTree = ""; }; 966B9CA916E41C07005B61E1 /* browser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = browser.h; sourceTree = ""; }; 966B9CAA16E41C07005B61E1 /* browser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = browser.m; sourceTree = ""; }; @@ -157,7 +156,6 @@ 966B9C9416E418B7005B61E1 /* btstack */, 966B9C9E16E418B7005B61E1 /* wiimote.c */, 966B9C9F16E418B7005B61E1 /* wiimote.h */, - 966B9CA016E418B7005B61E1 /* WiiMoteHelper.h */, 966B9CA116E418B7005B61E1 /* WiiMoteHelper.m */, ); path = BTStack; diff --git a/ios/RetroArch/RetroArch_iOS.m b/ios/RetroArch/RetroArch_iOS.m index 2310a728ec..7ab8d94a4b 100644 --- a/ios/RetroArch/RetroArch_iOS.m +++ b/ios/RetroArch/RetroArch_iOS.m @@ -19,7 +19,7 @@ #import "browser/browser.h" #import "settings/settings.h" -#import "input/BTStack/WiiMoteHelper.h" +#include "input/BTstack/btdynamic.h" #define kDOCSFOLDER [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] @@ -274,9 +274,9 @@ #pragma mark Bluetooth Helpers - (UIBarButtonItem*)createBluetoothButton { - if ([WiiMoteHelper haveBluetooth]) + if (btstack_is_loaded()) { - const bool isBTOn = [WiiMoteHelper isBluetoothRunning]; + const bool isBTOn = btstack_is_running(); return [[UIBarButtonItem alloc] initWithTitle:isBTOn ? @"Stop Bluetooth" : @"Start Bluetooth" style:UIBarButtonItemStyleBordered @@ -289,18 +289,18 @@ - (IBAction)startBluetooth { - if ([WiiMoteHelper haveBluetooth]) + if (btstack_is_loaded()) { - [WiiMoteHelper startBluetooth]; + btstack_start(); [self.topViewController.navigationItem setRightBarButtonItem:[self createBluetoothButton] animated:YES]; } } - (IBAction)stopBluetooth { - if ([WiiMoteHelper haveBluetooth]) + if (btstack_is_loaded()) { - [WiiMoteHelper stopBluetooth]; + btstack_stop(); [self.topViewController.navigationItem setRightBarButtonItem:[self createBluetoothButton] animated:YES]; } } diff --git a/ios/RetroArch/input/BTStack/WiiMoteHelper.h b/ios/RetroArch/input/BTStack/WiiMoteHelper.h deleted file mode 100644 index a122cf4284..0000000000 --- a/ios/RetroArch/input/BTStack/WiiMoteHelper.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 - -@interface WiiMoteHelper : NSObject -+ (BOOL)haveBluetooth; -+ (void)startBluetooth; -+ (BOOL)isBluetoothRunning; -+ (void)stopBluetooth; -@end - diff --git a/ios/RetroArch/input/BTStack/WiiMoteHelper.m b/ios/RetroArch/input/BTStack/WiiMoteHelper.m index 9888883d46..a678e0af32 100644 --- a/ios/RetroArch/input/BTStack/WiiMoteHelper.m +++ b/ios/RetroArch/input/BTStack/WiiMoteHelper.m @@ -39,10 +39,6 @@ #import "BTDevice.h" -static WiiMoteHelper* instance; -static bool btstackOpen; -static bool btOK; - static BTDevice* discoveredDevice; static bd_addr_t address; static uint32_t handle[2]; @@ -50,7 +46,27 @@ static uint32_t remote_cid[2]; static uint32_t local_cid[2]; uint8_t psdata_buffer[512]; -void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +static void set_ps3_data(unsigned leds) +{ + // TODO: LEDS + + static uint8_t report_buffer[] = { + 0x52, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + bt_send_l2cap_ptr(local_cid[0], report_buffer, sizeof(report_buffer)); +} + + +void btstack_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { #if 1 // WiiMote bd_addr_t event_addr; @@ -303,62 +319,3 @@ void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint } #endif } - -@implementation WiiMoteHelper -+ (BOOL)haveBluetooth -{ - if (!btstackOpen) - { - btstackOpen = load_btstack(); - - if (btstackOpen) - { - run_loop_init_ptr(RUN_LOOP_COCOA); - bt_register_packet_handler_ptr(packet_handler); - } - } - - return btstackOpen; -} - -+ (void)startBluetooth -{ - if (btstackOpen) - { - instance = instance ? instance : [WiiMoteHelper new]; - - if (!btOK) - { - if (bt_open_ptr()) - { - btOK = false; - return; - } - - bt_send_cmd_ptr(btstack_set_power_mode_ptr, HCI_POWER_ON); - - btOK = true; - } - } -} - -+ (BOOL)isBluetoothRunning -{ - return btstackOpen && btOK; -} - -+ (void)stopBluetooth -{ - if (btstackOpen) - { - myosd_num_of_joys = 0; - - if (btOK) - bt_send_cmd_ptr(btstack_set_power_mode_ptr, HCI_POWER_OFF); - - btOK = false; - instance = nil; - } -} - -@end diff --git a/ios/RetroArch/input/BTStack/btdynamic.c b/ios/RetroArch/input/BTStack/btdynamic.c index 7d8168e7ab..d633eb6bbc 100644 --- a/ios/RetroArch/input/BTStack/btdynamic.c +++ b/ios/RetroArch/input/BTStack/btdynamic.c @@ -15,13 +15,12 @@ #include #include #include +#include +#include #define BUILDING_BTDYNAMIC #include "btdynamic.h" -static bool bt_tested; -static bool bt_is_loaded; - #define GRAB(A) {#A, (void**)&A##_ptr} static struct { @@ -35,6 +34,7 @@ static struct GRAB(bt_send_cmd), GRAB(bt_send_l2cap), GRAB(run_loop_init), + GRAB(run_loop_execute), GRAB(btstack_get_system_bluetooth_enabled), GRAB(btstack_set_power_mode), GRAB(btstack_set_system_bluetooth_enabled), @@ -52,14 +52,47 @@ static struct {0, 0} }; -bool load_btstack() +extern void btstack_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); + +static pthread_t btstack_thread; +static bool btstack_tested; +static bool btstack_loaded; + +// TODO: This may need to be synchronized, but an extra iterate on the bluetooth thread won't kill anybody. +static volatile bool btstack_terminate = true; + +static void* btstack_thread_function(void* data) +{ + bt_register_packet_handler_ptr(btstack_packet_handler); + + static bool btstack_running = false; + if (!btstack_running) + btstack_running = bt_open_ptr() ? false : true; + + if (btstack_running) + { + bt_send_cmd_ptr(btstack_set_power_mode_ptr, HCI_POWER_ON); + + // Loop + while (!btstack_terminate && kCFRunLoopRunTimedOut == CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, false)); + + bt_send_cmd_ptr(btstack_set_power_mode_ptr, HCI_POWER_OFF); + } + + return 0; +} + + +bool btstack_load() { - assert(sizeof(void**) == sizeof(void(*))); + assert(sizeof(void**) == sizeof(void(*)())); - if (bt_tested) - return bt_is_loaded; + if (btstack_tested) + return btstack_loaded; + + btstack_tested = true; + btstack_loaded = false; - bt_tested = true; void* btstack = dlopen("/usr/lib/libBTstack.dylib", RTLD_LAZY); if (!btstack) @@ -76,5 +109,38 @@ bool load_btstack() } } + run_loop_init_ptr(RUN_LOOP_COCOA); + + btstack_loaded = true; + return true; } + +void btstack_start() +{ + if (btstack_terminate) + { + btstack_terminate = false; + pthread_create(&btstack_thread, NULL, btstack_thread_function, 0); + } +} + +void btstack_stop() +{ + if (!btstack_terminate) + { + btstack_terminate = true; + pthread_join(btstack_thread, 0); + } +} + +bool btstack_is_loaded() +{ + return btstack_load(); +} + +bool btstack_is_running() +{ + return !btstack_terminate; +} + diff --git a/ios/RetroArch/input/BTStack/btdynamic.h b/ios/RetroArch/input/BTStack/btdynamic.h index 95818ab724..9e31862ef3 100644 --- a/ios/RetroArch/input/BTStack/btdynamic.h +++ b/ios/RetroArch/input/BTStack/btdynamic.h @@ -19,20 +19,25 @@ #include "btstack/utils.h" #include "btstack/btstack.h" +bool btstack_load(); +void btstack_start(); +void btstack_stop(); +bool btstack_is_loaded(); +bool btstack_is_running(); + #ifndef BUILDING_BTDYNAMIC #define BTDIMPORT extern #else #define BTDIMPORT #endif -bool load_btstack(); - BTDIMPORT int (*bt_open_ptr)(void); BTDIMPORT void (*bt_flip_addr_ptr)(bd_addr_t dest, bd_addr_t src); BTDIMPORT btstack_packet_handler_t (*bt_register_packet_handler_ptr)(btstack_packet_handler_t handler); BTDIMPORT int (*bt_send_cmd_ptr)(const hci_cmd_t *cmd, ...); BTDIMPORT void (*bt_send_l2cap_ptr)(uint16_t local_cid, uint8_t *data, uint16_t len); BTDIMPORT void (*run_loop_init_ptr)(RUN_LOOP_TYPE type); +BTDIMPORT void (*run_loop_execute_ptr)(); BTDIMPORT const hci_cmd_t* btstack_get_system_bluetooth_enabled_ptr; BTDIMPORT const hci_cmd_t* btstack_set_power_mode_ptr;