(iOS) Move BTstack into a thread. It may still need synchronization with the input buffers, but shouldn't cause crashes or anything.

This commit is contained in:
meancoot 2013-03-23 21:12:29 -04:00
parent e3b4cb9a2d
commit a7497ab416
6 changed files with 109 additions and 123 deletions

View File

@ -74,7 +74,6 @@
966B9C9A16E418B7005B61E1 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
966B9C9E16E418B7005B61E1 /* wiimote.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wiimote.c; sourceTree = "<group>"; };
966B9C9F16E418B7005B61E1 /* wiimote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wiimote.h; sourceTree = "<group>"; };
966B9CA016E418B7005B61E1 /* WiiMoteHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WiiMoteHelper.h; sourceTree = "<group>"; };
966B9CA116E418B7005B61E1 /* WiiMoteHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WiiMoteHelper.m; sourceTree = "<group>"; };
966B9CA916E41C07005B61E1 /* browser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = browser.h; sourceTree = "<group>"; };
966B9CAA16E41C07005B61E1 /* browser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = browser.m; sourceTree = "<group>"; };
@ -157,7 +156,6 @@
966B9C9416E418B7005B61E1 /* btstack */,
966B9C9E16E418B7005B61E1 /* wiimote.c */,
966B9C9F16E418B7005B61E1 /* wiimote.h */,
966B9CA016E418B7005B61E1 /* WiiMoteHelper.h */,
966B9CA116E418B7005B61E1 /* WiiMoteHelper.m */,
);
path = BTStack;

View File

@ -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];
}
}

View File

@ -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 <UIKit/UIKit.h>
@interface WiiMoteHelper : NSObject
+ (BOOL)haveBluetooth;
+ (void)startBluetooth;
+ (BOOL)isBluetoothRunning;
+ (void)stopBluetooth;
@end

View File

@ -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

View File

@ -15,13 +15,12 @@
#include <stdio.h>
#include <assert.h>
#include <dlfcn.h>
#include <pthread.h>
#include <CoreFoundation/CFRunLoop.h>
#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;
}

View File

@ -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;