mirror of
https://github.com/libretro/RetroArch
synced 2025-03-01 16:13:40 +00:00
(iOS) Move all bluetooth processing to WiiMoteHelper.m; delete BTstackManager.m
This commit is contained in:
parent
1c332e42f8
commit
95259d4b86
@ -21,7 +21,6 @@
|
||||
963F5AC316CC522F009BBD19 /* RASettingsList.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5ABF16CC522F009BBD19 /* RASettingsList.m */; };
|
||||
963F5AC816CC523B009BBD19 /* RAGameView.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5AC516CC523B009BBD19 /* RAGameView.m */; };
|
||||
966B9CA216E418B7005B61E1 /* BTDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9C9116E418B7005B61E1 /* BTDevice.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
966B9CA416E418B7005B61E1 /* BTstackManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9C9C16E418B7005B61E1 /* BTstackManager.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
966B9CA616E418B7005B61E1 /* wiimote.c in Sources */ = {isa = PBXBuildFile; fileRef = 966B9C9E16E418B7005B61E1 /* wiimote.c */; };
|
||||
966B9CA716E418B7005B61E1 /* WiiMoteHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CA116E418B7005B61E1 /* WiiMoteHelper.m */; };
|
||||
966B9CAE16E41C07005B61E1 /* browser.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAA16E41C07005B61E1 /* browser.m */; };
|
||||
@ -73,8 +72,6 @@
|
||||
966B9C9816E418B7005B61E1 /* run_loop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = run_loop.h; sourceTree = "<group>"; };
|
||||
966B9C9916E418B7005B61E1 /* sdp_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sdp_util.h; sourceTree = "<group>"; };
|
||||
966B9C9A16E418B7005B61E1 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
|
||||
966B9C9B16E418B7005B61E1 /* BTstackManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTstackManager.h; sourceTree = "<group>"; };
|
||||
966B9C9C16E418B7005B61E1 /* BTstackManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTstackManager.m; 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>"; };
|
||||
@ -158,8 +155,6 @@
|
||||
966B9C9016E418B7005B61E1 /* BTDevice.h */,
|
||||
966B9C9116E418B7005B61E1 /* BTDevice.m */,
|
||||
966B9C9416E418B7005B61E1 /* btstack */,
|
||||
966B9C9B16E418B7005B61E1 /* BTstackManager.h */,
|
||||
966B9C9C16E418B7005B61E1 /* BTstackManager.m */,
|
||||
966B9C9E16E418B7005B61E1 /* wiimote.c */,
|
||||
966B9C9F16E418B7005B61E1 /* wiimote.h */,
|
||||
966B9CA016E418B7005B61E1 /* WiiMoteHelper.h */,
|
||||
@ -404,7 +399,6 @@
|
||||
963F5AC816CC523B009BBD19 /* RAGameView.m in Sources */,
|
||||
96096DD816D1ABAF00BF4499 /* RAModuleInfoList.m in Sources */,
|
||||
966B9CA216E418B7005B61E1 /* BTDevice.m in Sources */,
|
||||
966B9CA416E418B7005B61E1 /* BTstackManager.m in Sources */,
|
||||
966B9CA616E418B7005B61E1 /* wiimote.c in Sources */,
|
||||
966B9CA716E418B7005B61E1 /* WiiMoteHelper.m in Sources */,
|
||||
966B9CAE16E41C07005B61E1 /* browser.m in Sources */,
|
||||
|
@ -1,188 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <stdint.h>
|
||||
#import "btstack/btstack.h"
|
||||
|
||||
#define PREFS_REMOTE_NAME @"RemoteName"
|
||||
#define PREFS_LINK_KEY @"LinkKey"
|
||||
#define BTstackManagerID @"ch.ringwald.btstack"
|
||||
|
||||
@class BTDevice;
|
||||
|
||||
/*
|
||||
* Information on devices is stored in a system-wide plist
|
||||
* it is maintained by BTstackManager
|
||||
* this includes the link keys
|
||||
*/
|
||||
|
||||
// TODO enumerate BTstackError type
|
||||
typedef int BTstackError;
|
||||
|
||||
typedef enum {
|
||||
kDeactivated = 1,
|
||||
kW4SysBTState,
|
||||
kW4SysBTDisabled,
|
||||
kW4Activated,
|
||||
kActivated,
|
||||
kW4Deactivated,
|
||||
kSleeping,
|
||||
#if 0
|
||||
kW4DisoveryStopped,
|
||||
kW4AuthenticationEnableCommand
|
||||
#endif
|
||||
} ManagerState;
|
||||
|
||||
typedef enum {
|
||||
kInactive = 1,
|
||||
kW4InquiryMode,
|
||||
kInquiry,
|
||||
kRemoteName,
|
||||
// stopping
|
||||
kW4InquiryModeBeforeStop,
|
||||
kW4InquiryStop,
|
||||
kW4RemoteNameBeforeStop,
|
||||
} DiscoveryState;
|
||||
|
||||
@protocol BTstackManagerDelegate;
|
||||
@protocol BTstackManagerListener;
|
||||
|
||||
@interface BTstackManager : NSObject {
|
||||
@private
|
||||
NSObject<BTstackManagerDelegate>* _delegate;
|
||||
NSMutableArray *discoveredDevices;
|
||||
NSMutableSet *listeners;
|
||||
BOOL connectedToDaemon;
|
||||
ManagerState state;
|
||||
DiscoveryState discoveryState;
|
||||
int discoveryDeviceIndex;
|
||||
#if 0
|
||||
// current connection - kind a ugly
|
||||
uint8_t connType; // 0 = L2CAP, 1 = RFCOMM
|
||||
bd_addr_t connAddr;
|
||||
uint16_t connPSM;
|
||||
uint16_t connChan;
|
||||
uint8_t connAuth;
|
||||
#endif
|
||||
}
|
||||
|
||||
// shared instance
|
||||
+(BTstackManager *) sharedInstance;
|
||||
|
||||
// listeners
|
||||
-(void) addListener:(id<BTstackManagerListener>)listener;
|
||||
-(void) removeListener:(id<BTstackManagerListener>)listener;
|
||||
|
||||
// Activation
|
||||
-(BTstackError) activate;
|
||||
-(BTstackError) deactivate;
|
||||
-(BOOL) isActivating;
|
||||
-(BOOL) isActive;
|
||||
|
||||
// Discovery
|
||||
-(BTstackError) startDiscovery;
|
||||
-(BTstackError) stopDiscovery;
|
||||
-(int) numberOfDevicesFound;
|
||||
-(BTDevice*) deviceAtIndex:(int)index;
|
||||
-(BOOL) isDiscoveryActive;
|
||||
|
||||
// Link Key Management
|
||||
-(void) dropLinkKeyForAddress:(bd_addr_t*) address;
|
||||
|
||||
// Connections
|
||||
-(BTstackError) createL2CAPChannelAtAddress:(bd_addr_t*) address withPSM:(uint16_t)psm authenticated:(BOOL)authentication;
|
||||
-(BTstackError) closeL2CAPChannelWithID:(uint16_t) channelID;
|
||||
-(BTstackError) sendL2CAPPacketForChannelID:(uint16_t)channelID;
|
||||
|
||||
-(BTstackError) createRFCOMMConnectionAtAddress:(bd_addr_t*) address withChannel:(uint16_t)channel authenticated:(BOOL)authentication;
|
||||
-(BTstackError) closeRFCOMMConnectionWithID:(uint16_t) connectionID;
|
||||
-(BTstackError) sendRFCOMMPacketForChannelID:(uint16_t)connectionID;
|
||||
|
||||
|
||||
// TODO add l2cap and rfcomm incoming commands
|
||||
@property (nonatomic, assign) NSObject<BTstackManagerDelegate>* delegate;
|
||||
@property (nonatomic, retain) NSMutableArray *discoveredDevices;
|
||||
@property (nonatomic, retain) NSMutableSet *listeners;
|
||||
@end
|
||||
|
||||
|
||||
@protocol BTstackManagerDelegate
|
||||
@optional
|
||||
|
||||
// Activation callbacks
|
||||
-(BOOL) disableSystemBluetoothBTstackManager:(BTstackManager*) manager; // default: YES
|
||||
|
||||
// Connection events
|
||||
-(NSString*) btstackManager:(BTstackManager*) manager pinForAddress:(bd_addr_t)addr; // default: "0000"
|
||||
|
||||
// direct access
|
||||
-(void) btstackManager:(BTstackManager*) manager
|
||||
handlePacketWithType:(uint8_t) packet_type
|
||||
forChannel:(uint16_t) channel
|
||||
andData:(uint8_t *)packet
|
||||
withLen:(uint16_t) size;
|
||||
@end
|
||||
|
||||
|
||||
@protocol BTstackManagerListener
|
||||
@optional
|
||||
|
||||
// Activation events
|
||||
-(void) activatedBTstackManager:(BTstackManager*) manager;
|
||||
-(void) btstackManager:(BTstackManager*)manager activationFailed:(BTstackError)error;
|
||||
-(void) deactivatedBTstackManager:(BTstackManager*) manager;
|
||||
|
||||
// Power management events
|
||||
-(void) sleepModeEnterBTstackManager:(BTstackManager*) manager;
|
||||
-(void) sleepModeExtitBTstackManager:(BTstackManager*) manager;
|
||||
|
||||
// Discovery events: general
|
||||
-(void) btstackManager:(BTstackManager*)manager deviceInfo:(BTDevice*)device;
|
||||
-(void) btstackManager:(BTstackManager*)manager discoveryQueryRemoteName:(int)deviceIndex;
|
||||
-(void) discoveryStoppedBTstackManager:(BTstackManager*) manager;
|
||||
-(void) discoveryInquiryBTstackManager:(BTstackManager*) manager;
|
||||
|
||||
// Connection
|
||||
-(void) l2capChannelCreatedAtAddress:(bd_addr_t)addr withPSM:(uint16_t)psm asID:(uint16_t)channelID;
|
||||
-(void) l2capChannelCreateFailedAtAddress:(bd_addr_t)addr withPSM:(uint16_t)psm error:(BTstackError)error;
|
||||
-(void) l2capChannelClosedForChannelID:(uint16_t)channelID;
|
||||
-(void) l2capDataReceivedForChannelID:(uint16_t)channelID withData:(uint8_t *)packet ofLen:(uint16_t)size;
|
||||
|
||||
-(void) rfcommConnectionCreatedAtAddress:(bd_addr_t)addr forChannel:(uint16_t)channel asID:(uint16_t)connectionID;
|
||||
-(void) rfcommConnectionCreateFailedAtAddress:(bd_addr_t)addr forChannel:(uint16_t)channel error:(BTstackError)error;
|
||||
-(void) rfcommConnectionClosedForConnectionID:(uint16_t)connectionID;
|
||||
-(void) rfcommDataReceivedForConnectionID:(uint16_t)connectionID withData:(uint8_t *)packet ofLen:(uint16_t)size;
|
||||
|
||||
// TODO add l2cap and rfcomm incoming events
|
||||
@end
|
@ -1,592 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "btdynamic.h"
|
||||
|
||||
#import "BTstackManager.h"
|
||||
|
||||
#import "btstack/btstack.h"
|
||||
#import "BTDevice.h"
|
||||
|
||||
#define INQUIRY_INTERVAL 3
|
||||
|
||||
static BTstackManager * btstackManager = nil;
|
||||
|
||||
@interface BTstackManager (privat)
|
||||
- (void)handlePacketWithType:(uint8_t) packet_type forChannel:(uint16_t) channel andData:(uint8_t *)packet withLen:(uint16_t) size;
|
||||
@end
|
||||
|
||||
// needed for libBTstack
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
[btstackManager handlePacketWithType:packet_type forChannel:channel andData:packet withLen:size];
|
||||
}
|
||||
|
||||
@implementation BTstackManager
|
||||
|
||||
@synthesize delegate = _delegate;
|
||||
@synthesize listeners;
|
||||
@synthesize discoveredDevices;
|
||||
|
||||
-(BTstackManager *) init {
|
||||
self = [super init];
|
||||
if (!self) return self;
|
||||
|
||||
state = kDeactivated;
|
||||
discoveryState = kInactive;
|
||||
connectedToDaemon = NO;
|
||||
|
||||
// device discovery
|
||||
[self setDiscoveredDevices: [[NSMutableArray alloc] init]];
|
||||
|
||||
// delegate and listener
|
||||
_delegate = nil;
|
||||
[self setListeners:[[NSMutableSet alloc] init]];
|
||||
|
||||
// Use Cocoa run loop
|
||||
run_loop_init_ptr(RUN_LOOP_COCOA);
|
||||
|
||||
// our packet handler
|
||||
bt_register_packet_handler_ptr(packet_handler);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+(BTstackManager *) sharedInstance {
|
||||
if (!btstackManager) {
|
||||
btstackManager = [[BTstackManager alloc] init];
|
||||
}
|
||||
return btstackManager;
|
||||
}
|
||||
|
||||
// listeners
|
||||
-(void) addListener:(id<BTstackManagerListener>)listener{
|
||||
[listeners addObject:listener];
|
||||
}
|
||||
|
||||
-(void) removeListener:(id<BTstackManagerListener>)listener{
|
||||
[listeners removeObject:listener];
|
||||
}
|
||||
|
||||
// send events
|
||||
-(void) sendActivated {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(activatedBTstackManager:)]){
|
||||
[listener activatedBTstackManager:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendActivationFailed:(BTstackError)error {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(btstackManager:activationFailed:)]){
|
||||
[listener btstackManager:self activationFailed:error];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendDeactivated {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(deactivatedBTstackManager:)]){
|
||||
[listener deactivatedBTstackManager:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendSleepEnter {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(sleepModeEnterBTstackManager:)]){
|
||||
[listener sleepModeEnterBTstackManager:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendSleepExit {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(sleepModeExtitBTstackManager:)]){
|
||||
[listener sleepModeExtitBTstackManager:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendDiscoveryStoppedEvent {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(discoveryStoppedBTstackManager:)]){
|
||||
[listener discoveryStoppedBTstackManager:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendDiscoveryInquiry{
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(discoveryInquiryBTstackManager:)]){
|
||||
[listener discoveryInquiryBTstackManager:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendDiscoveryQueryRemoteName:(int)index {
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(btstackManager:discoveryQueryRemoteName:)]){
|
||||
[listener btstackManager:self discoveryQueryRemoteName:index];
|
||||
}
|
||||
}
|
||||
}
|
||||
-(void) sendDeviceInfo:(BTDevice*) device{
|
||||
for (NSObject<BTstackManagerListener>* listener in listeners) {
|
||||
if ([listener respondsToSelector:@selector(btstackManager:deviceInfo:)]){
|
||||
[listener btstackManager:self deviceInfo:device];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Activation
|
||||
-(BTstackError) activate {
|
||||
|
||||
BTstackError err = 0;
|
||||
if (!connectedToDaemon) {
|
||||
err = bt_open_ptr();
|
||||
if (err) return BTSTACK_CONNECTION_TO_BTDAEMON_FAILED;
|
||||
}
|
||||
connectedToDaemon = YES;
|
||||
|
||||
// check system BT
|
||||
state = kW4SysBTState;
|
||||
bt_send_cmd_ptr(btstack_get_system_bluetooth_enabled_ptr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
-(BTstackError) deactivate {
|
||||
if (!connectedToDaemon) return BTSTACK_CONNECTION_TO_BTDAEMON_FAILED;
|
||||
state = kW4Deactivated;
|
||||
bt_send_cmd_ptr(btstack_set_power_mode_ptr, HCI_POWER_OFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
-(BOOL) isActive {
|
||||
return state == kActivated;
|
||||
}
|
||||
|
||||
-(BOOL) isActivating {
|
||||
switch (state){
|
||||
case kW4SysBTState:
|
||||
case kW4SysBTDisabled:
|
||||
case kW4Activated:
|
||||
return YES;
|
||||
default:
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
-(BOOL) isDiscoveryActive {
|
||||
return state == kActivated && (discoveryState != kInactive);
|
||||
}
|
||||
|
||||
// Discovery
|
||||
-(BTstackError) startDiscovery {
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
|
||||
discoveryState = kW4InquiryMode;
|
||||
bt_send_cmd_ptr(hci_write_inquiry_mode_ptr, 0x01); // with RSSI
|
||||
return 0;
|
||||
};
|
||||
|
||||
-(BTstackError) stopDiscovery{
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
switch (discoveryState){
|
||||
case kInactive:
|
||||
[self sendDiscoveryStoppedEvent];
|
||||
break;
|
||||
case kW4InquiryMode:
|
||||
discoveryState = kW4InquiryModeBeforeStop;
|
||||
break;
|
||||
case kInquiry:
|
||||
discoveryState = kW4InquiryStop;
|
||||
bt_send_cmd_ptr(hci_inquiry_cancel_ptr);
|
||||
break;
|
||||
case kRemoteName: {
|
||||
discoveryState = kW4RemoteNameBeforeStop;
|
||||
BTDevice *device = [discoveredDevices objectAtIndex:discoveryDeviceIndex];
|
||||
bt_send_cmd_ptr(hci_remote_name_request_cancel_ptr, [device address]);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NSLog(@"[BTstackManager stopDiscovery] invalid discoveryState %u", discoveryState);
|
||||
[self sendDiscoveryStoppedEvent];
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
-(int) numberOfDevicesFound{
|
||||
return [discoveredDevices count];
|
||||
};
|
||||
|
||||
-(BTDevice*) deviceAtIndex:(int)index{
|
||||
return (BTDevice*) [discoveredDevices objectAtIndex:index];
|
||||
};
|
||||
|
||||
-(BTDevice*) deviceForAddress:(bd_addr_t*) address{
|
||||
for (BTDevice *device in discoveredDevices){
|
||||
// NSLog(@"compare %@ to %@", [BTDevice stringForAddress:address], [device addressString]);
|
||||
if ( BD_ADDR_CMP(address, [device address]) == 0){
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) activationHandleEvent:(uint8_t *)packet withLen:(uint16_t) size {
|
||||
switch (state) {
|
||||
|
||||
case kW4SysBTState:
|
||||
case kW4SysBTDisabled:
|
||||
|
||||
// BTSTACK_EVENT_SYSTEM_BLUETOOTH_ENABLED
|
||||
if ( packet[0] == BTSTACK_EVENT_SYSTEM_BLUETOOTH_ENABLED){
|
||||
if (packet[2]){
|
||||
// system bt on - first time try to disable it
|
||||
if ( state == kW4SysBTState) {
|
||||
if (_delegate == nil
|
||||
|| ![_delegate respondsToSelector:@selector(disableSystemBluetoothBTstackManager:)]
|
||||
|| [_delegate disableSystemBluetoothBTstackManager:self]){
|
||||
state = kW4SysBTDisabled;
|
||||
bt_send_cmd_ptr(btstack_set_system_bluetooth_enabled_ptr, 0);
|
||||
} else {
|
||||
state = kDeactivated;
|
||||
[self sendActivationFailed:BTSTACK_ACTIVATION_FAILED_SYSTEM_BLUETOOTH];
|
||||
}
|
||||
} else {
|
||||
state = kDeactivated;
|
||||
[self sendActivationFailed:BTSTACK_ACTIVATION_FAILED_UNKNOWN];
|
||||
}
|
||||
} else {
|
||||
state = kW4Activated;
|
||||
bt_send_cmd_ptr(btstack_set_power_mode_ptr, HCI_POWER_ON);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kW4Activated:
|
||||
switch (packet[0]){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
if (packet[2] == HCI_STATE_WORKING) {
|
||||
state = kActivated;
|
||||
[self sendActivated];
|
||||
}
|
||||
break;
|
||||
case BTSTACK_EVENT_POWERON_FAILED:
|
||||
state = kDeactivated;
|
||||
[self sendActivationFailed:BTSTACK_ACTIVATION_POWERON_FAILED];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case kW4Deactivated:
|
||||
if (packet[0] != BTSTACK_EVENT_STATE && packet[2] == HCI_STATE_OFF){
|
||||
state = kDeactivated;
|
||||
[self sendDeactivated];
|
||||
}
|
||||
break;
|
||||
|
||||
case kActivated:
|
||||
if (packet[0] != BTSTACK_EVENT_STATE && packet[2] == HCI_STATE_FALLING_ASLEEP){
|
||||
state = kSleeping;
|
||||
[self sendSleepEnter];
|
||||
}
|
||||
break;
|
||||
|
||||
case kSleeping:
|
||||
if (packet[0] != BTSTACK_EVENT_STATE && packet[2] == HCI_STATE_WORKING){
|
||||
state = kActivated;
|
||||
[self sendSleepExit];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) discoveryRemoteName{
|
||||
BOOL found = NO;
|
||||
while ( discoveryDeviceIndex < [discoveredDevices count]){
|
||||
BTDevice *device = [discoveredDevices objectAtIndex:discoveryDeviceIndex];
|
||||
if (device.name) {
|
||||
discoveryDeviceIndex ++;
|
||||
continue;
|
||||
}
|
||||
bt_send_cmd_ptr(hci_remote_name_request_ptr, [device address], device.pageScanRepetitionMode,
|
||||
0, device.clockOffset | 0x8000);
|
||||
[self sendDiscoveryQueryRemoteName:discoveryDeviceIndex];
|
||||
found = YES;
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
// printf("Queried all devices, restart.\n");
|
||||
discoveryState = kInquiry;
|
||||
bt_send_cmd_ptr(hci_inquiry_ptr, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
|
||||
[self sendDiscoveryInquiry];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *) createRemoteNameFromRemoteNameEvent:(uint8_t *) packet {
|
||||
// get lenght: first null byte or max 248 chars
|
||||
int nameLen = 0;
|
||||
while (nameLen < 248 && packet[9+nameLen]) nameLen++;
|
||||
// Bluetooth specification mandates UTF-8 encoding...
|
||||
NSString *name = [[NSString alloc] initWithBytes:&packet[9] length:nameLen encoding:NSUTF8StringEncoding];
|
||||
// but fallback to latin-1 for non-standard products like old Microsoft Wireless Presenter
|
||||
if (!name){
|
||||
name = [[NSString alloc] initWithBytes:&packet[9] length:nameLen encoding:NSISOLatin1StringEncoding];
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
- (void) handleRemoteNameCached: (uint8_t *) packet {
|
||||
bd_addr_t addr;
|
||||
bt_flip_addr_ptr(addr, &packet[3]);
|
||||
// NSLog(@"Get remote name done for %@", [BTDevice stringForAddress:&addr]);
|
||||
BTDevice* device = [self deviceForAddress:&addr];
|
||||
if (!device) return;
|
||||
|
||||
[device setName:[self createRemoteNameFromRemoteNameEvent:packet]];
|
||||
[self sendDeviceInfo:device];
|
||||
}
|
||||
|
||||
- (void) handleRemoteName: (uint8_t *) packet {
|
||||
bd_addr_t addr;
|
||||
bt_flip_addr_ptr(addr, &packet[3]);
|
||||
// NSLog(@"Get remote name done for %@", [BTDevice stringForAddress:&addr]);
|
||||
BTDevice* device = [self deviceForAddress:&addr];
|
||||
if (!device) return;
|
||||
|
||||
[device setName:[self createRemoteNameFromRemoteNameEvent:packet]];
|
||||
[self sendDeviceInfo:device];
|
||||
|
||||
discoveryDeviceIndex++;
|
||||
[self discoveryRemoteName];
|
||||
}
|
||||
|
||||
-(void) discoveryHandleEvent:(uint8_t *)packet withLen:(uint16_t) size {
|
||||
bd_addr_t addr;
|
||||
int i;
|
||||
int numResponses;
|
||||
|
||||
switch (discoveryState) {
|
||||
|
||||
case kInactive:
|
||||
break;
|
||||
|
||||
case kW4InquiryMode:
|
||||
if (packet[0] == HCI_EVENT_COMMAND_COMPLETE && COMMAND_COMPLETE_EVENT(packet, (*hci_write_inquiry_mode_ptr)) ) {
|
||||
discoveryState = kInquiry;
|
||||
bt_send_cmd_ptr(hci_inquiry_ptr, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
|
||||
[self sendDiscoveryInquiry];
|
||||
}
|
||||
break;
|
||||
|
||||
case kInquiry:
|
||||
|
||||
switch (packet[0]){
|
||||
case HCI_EVENT_INQUIRY_RESULT:
|
||||
numResponses = packet[2];
|
||||
for (i=0; i<numResponses ; i++){
|
||||
bt_flip_addr_ptr(addr, &packet[3+i*6]);
|
||||
// NSLog(@"found %@", [BTDevice stringForAddress:&addr]);
|
||||
BTDevice* device = [self deviceForAddress:&addr];
|
||||
if (!device) {
|
||||
device = [[BTDevice alloc] init];
|
||||
[discoveredDevices addObject:device];
|
||||
[device setAddress:&addr];
|
||||
}
|
||||
// update
|
||||
device.pageScanRepetitionMode = packet [3 + numResponses*(6) + i*1];
|
||||
device.classOfDevice = READ_BT_24(packet, 3 + numResponses*(6+1+1+1) + i*3);
|
||||
device.clockOffset = READ_BT_16(packet, 3 + numResponses*(6+1+1+1+3) + i*2) & 0x7fff;
|
||||
device.rssi = 0;
|
||||
[self sendDeviceInfo:device];
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:
|
||||
numResponses = packet[2];
|
||||
for (i=0; i<numResponses ;i++){
|
||||
bt_flip_addr_ptr(addr, &packet[3+i*6]);
|
||||
// NSLog(@"found %@", [BTDevice stringForAddress:&addr]);
|
||||
BTDevice* device = [self deviceForAddress:&addr];
|
||||
if (!device) {
|
||||
device = [[BTDevice alloc] init];
|
||||
[discoveredDevices addObject:device];
|
||||
[device setAddress:&addr];
|
||||
}
|
||||
device.pageScanRepetitionMode = packet [3 + numResponses*(6) + i*1];
|
||||
device.classOfDevice = READ_BT_24(packet, 3 + numResponses*(6+1+1) + i*3);
|
||||
device.clockOffset = READ_BT_16(packet, 3 + numResponses*(6+1+1+3) + i*2) & 0x7fff;
|
||||
device.rssi = packet [3 + numResponses*(6+1+1+3+2) + i*1];
|
||||
[self sendDeviceInfo:device];
|
||||
}
|
||||
break;
|
||||
|
||||
case BTSTACK_EVENT_REMOTE_NAME_CACHED:
|
||||
[self handleRemoteNameCached:packet];
|
||||
break;
|
||||
|
||||
case HCI_EVENT_INQUIRY_COMPLETE:
|
||||
// printf("Inquiry scan done.\n");
|
||||
discoveryState = kRemoteName;
|
||||
discoveryDeviceIndex = 0;
|
||||
[self discoveryRemoteName];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case kRemoteName:
|
||||
if (packet[0] == HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE){
|
||||
[self handleRemoteName:packet];
|
||||
}
|
||||
break;
|
||||
|
||||
case kW4InquiryModeBeforeStop:
|
||||
if (packet[0] == HCI_EVENT_COMMAND_COMPLETE && COMMAND_COMPLETE_EVENT(packet, (*hci_write_inquiry_mode_ptr)) ) {
|
||||
discoveryState = kInactive;
|
||||
[self sendDiscoveryStoppedEvent];
|
||||
}
|
||||
break;
|
||||
|
||||
case kW4InquiryStop:
|
||||
if (packet[0] == HCI_EVENT_INQUIRY_COMPLETE
|
||||
|| COMMAND_COMPLETE_EVENT(packet, (*hci_inquiry_cancel_ptr))) {
|
||||
discoveryState = kInactive;
|
||||
[self sendDiscoveryStoppedEvent];
|
||||
}
|
||||
break;
|
||||
|
||||
case kW4RemoteNameBeforeStop:
|
||||
if (packet[0] == HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE
|
||||
|| COMMAND_COMPLETE_EVENT(packet, (*hci_remote_name_request_cancel_ptr))){
|
||||
discoveryState = kInactive;
|
||||
[self sendDiscoveryStoppedEvent];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) dropLinkKeyForAddress:(bd_addr_t*) address {
|
||||
bt_send_cmd_ptr(hci_delete_stored_link_key_ptr, address, 0);
|
||||
// NSLog(@"Removing link key for %@", devAddress);
|
||||
}
|
||||
|
||||
-(void) handlePacketWithType:(uint8_t)packet_type forChannel:(uint16_t)channel andData:(uint8_t *)packet withLen:(uint16_t) size {
|
||||
switch (state) {
|
||||
|
||||
case kDeactivated:
|
||||
break;
|
||||
|
||||
// Activation
|
||||
case kW4SysBTState:
|
||||
case kW4SysBTDisabled:
|
||||
case kW4Activated:
|
||||
case kW4Deactivated:
|
||||
case kSleeping:
|
||||
if (packet_type != HCI_EVENT_PACKET) break;
|
||||
[self activationHandleEvent:packet withLen:size];
|
||||
break;
|
||||
|
||||
// Pairing + Discovery
|
||||
case kActivated:
|
||||
if (packet_type != HCI_EVENT_PACKET) break;
|
||||
switch (packet[0]){
|
||||
case BTSTACK_EVENT_STATE:
|
||||
[self activationHandleEvent:packet withLen:size];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
[self discoveryHandleEvent:packet withLen:size];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ([_delegate respondsToSelector:@selector(btstackManager:handlePacketWithType:forChannel:andData:withLen:)]){
|
||||
[_delegate btstackManager:self handlePacketWithType:packet_type forChannel:channel andData:packet withLen:size];
|
||||
}
|
||||
}
|
||||
|
||||
// Connections
|
||||
-(BTstackError) createL2CAPChannelAtAddress:(bd_addr_t*) address withPSM:(uint16_t)psm authenticated:(BOOL)authentication {
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
if (state != kActivated) return BTSTACK_BUSY;
|
||||
#if 0
|
||||
// ...f (state
|
||||
// store params
|
||||
connType = 0;
|
||||
BD_ADDR_COPY(&connAddr, address);
|
||||
connPSM = psm;
|
||||
connAuth = authentication;
|
||||
|
||||
// send write authentication enabled
|
||||
bt_send_cmd_ptr(&hci_write_authentication_enable, authentication);
|
||||
state = kW4AuthenticationEnableCommand;
|
||||
#endif
|
||||
return 0;
|
||||
};
|
||||
-(BTstackError) sendL2CAPPacketForChannelID:(uint16_t)channelID {
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
return 0;
|
||||
};
|
||||
-(BTstackError) closeL2CAPChannelWithID:(uint16_t) channelID {
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
return 0;
|
||||
};
|
||||
|
||||
-(BTstackError) createRFCOMMConnectionAtAddress:(bd_addr_t*) address withChannel:(uint16_t)channel authenticated:(BOOL)authentication {
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
if (state != kActivated) return BTSTACK_BUSY;
|
||||
#if 0
|
||||
// store params
|
||||
connType = 1;
|
||||
BD_ADDR_COPY(&connAddr, address);
|
||||
connChan = channel;
|
||||
connAuth = authentication;
|
||||
#endif
|
||||
return 0;
|
||||
};
|
||||
-(BTstackError) sendRFCOMMPacketForChannelID:(uint16_t)connectionID {
|
||||
if (state < kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
return 0;
|
||||
};
|
||||
-(BTstackError) closeRFCOMMConnectionWithID:(uint16_t) connectionID {
|
||||
if (state <kActivated) return BTSTACK_NOT_ACTIVATED;
|
||||
return 0;
|
||||
};
|
||||
|
||||
@end
|
@ -31,9 +31,7 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "BTstackManager.h"
|
||||
|
||||
@interface WiiMoteHelper : NSObject<BTstackManagerDelegate, BTstackManagerListener>
|
||||
@interface WiiMoteHelper : NSObject
|
||||
+ (BOOL)haveBluetooth;
|
||||
+ (void)startBluetooth;
|
||||
+ (BOOL)isBluetoothRunning;
|
||||
|
@ -38,198 +38,105 @@
|
||||
#import "WiiMoteHelper.h"
|
||||
|
||||
#import "BTDevice.h"
|
||||
#import "BTstackManager.h"
|
||||
|
||||
static WiiMoteHelper* instance;
|
||||
static BTDevice *device;
|
||||
static bool btstackOpen;
|
||||
static bool btOK;
|
||||
|
||||
@implementation WiiMoteHelper
|
||||
+ (BOOL)haveBluetooth
|
||||
{
|
||||
if (!btstackOpen)
|
||||
btstackOpen = load_btstack();
|
||||
|
||||
return btstackOpen;
|
||||
}
|
||||
static BTDevice* discoveredDevice;
|
||||
|
||||
+ (void)startBluetooth
|
||||
{
|
||||
if (btstackOpen)
|
||||
{
|
||||
instance = instance ? instance : [WiiMoteHelper new];
|
||||
|
||||
if (!btOK)
|
||||
{
|
||||
BTstackManager* bt = [BTstackManager sharedInstance];
|
||||
[bt setDelegate:instance];
|
||||
[bt addListener:instance];
|
||||
|
||||
btOK = [bt activate] == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)isBluetoothRunning
|
||||
{
|
||||
return btstackOpen && btOK;
|
||||
}
|
||||
|
||||
+ (void)stopBluetooth
|
||||
{
|
||||
if (btstackOpen)
|
||||
{
|
||||
myosd_num_of_joys = 0;
|
||||
|
||||
if (btOK)
|
||||
{
|
||||
BTstackManager* bt = [BTstackManager sharedInstance];
|
||||
|
||||
[bt deactivate];
|
||||
[bt setDelegate:nil];
|
||||
[bt removeListener:instance];
|
||||
btOK = false;
|
||||
}
|
||||
|
||||
instance = nil;
|
||||
}
|
||||
}
|
||||
|
||||
// BTStackManagerListener
|
||||
-(void) activatedBTstackManager:(BTstackManager*) manager
|
||||
{
|
||||
[[BTstackManager sharedInstance] startDiscovery];
|
||||
}
|
||||
|
||||
-(void) btstackManager:(BTstackManager*)manager deviceInfo:(BTDevice*)newDevice
|
||||
{
|
||||
if ([newDevice name] && [[newDevice name] hasPrefix:@"Nintendo RVL-CNT-01"])
|
||||
{
|
||||
device = newDevice;
|
||||
[[BTstackManager sharedInstance] stopDiscovery];
|
||||
}
|
||||
}
|
||||
|
||||
-(void) discoveryStoppedBTstackManager:(BTstackManager*) manager
|
||||
{
|
||||
bt_send_cmd_ptr(hci_write_authentication_enable_ptr, 0);
|
||||
}
|
||||
|
||||
// BTStackManagerDelegate
|
||||
-(void) btstackManager:(BTstackManager*) manager
|
||||
handlePacketWithType:(uint8_t)packet_type
|
||||
forChannel:(uint16_t)channel
|
||||
andData:(uint8_t*)packet
|
||||
withLen:(uint16_t)size
|
||||
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 = wiimote_get_by_source_cid(channel);
|
||||
|
||||
if (wm != NULL)
|
||||
{
|
||||
byte* msg = packet + 2;
|
||||
byte event = packet[1];
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case WM_RPT_BTN:
|
||||
{
|
||||
wiimote_pressed_buttons(wm, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RPT_READ:
|
||||
{
|
||||
/* data read */
|
||||
wiimote_pressed_buttons(wm, msg);
|
||||
|
||||
byte len = ((msg[2] & 0xF0) >> 4) + 1;
|
||||
byte *data = (msg + 5);
|
||||
|
||||
if(wiimote_handshake(wm, WM_RPT_READ, data, len))
|
||||
{
|
||||
if (device != nil)
|
||||
{
|
||||
[device setConnectionState:kBluetoothConnectionConnected];
|
||||
device = nil;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case WM_RPT_CTRL_STATUS:
|
||||
{
|
||||
wiimote_pressed_buttons(wm, msg);
|
||||
|
||||
//handshake stuff!
|
||||
if(wiimote_handshake(wm,WM_RPT_CTRL_STATUS,msg,-1))
|
||||
{
|
||||
[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
|
||||
// Connection
|
||||
case HCI_EVENT_PACKET:
|
||||
{
|
||||
switch (packet[0])
|
||||
{
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
// Bluetooth is active, search for remote
|
||||
case BTSTACK_EVENT_STATE:
|
||||
{
|
||||
if (COMMAND_COMPLETE_EVENT(packet, (*hci_write_authentication_enable_ptr)))
|
||||
bt_send_cmd_ptr(l2cap_create_channel_ptr, [device address], PSM_HID_INTERRUPT);
|
||||
break;
|
||||
if (packet[2] == HCI_STATE_WORKING)
|
||||
bt_send_cmd_ptr(hci_inquiry_ptr, HCI_INQUIRY_LAP, 3, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case HCI_EVENT_PIN_CODE_REQUEST:
|
||||
// Identifies devices found during inquiry, does not signal the end of the inquiry.
|
||||
case HCI_EVENT_INQUIRY_RESULT:
|
||||
{
|
||||
bt_flip_addr_ptr(event_addr, &packet[2]);
|
||||
if (BD_ADDR_CMP([device address], event_addr)) break;
|
||||
|
||||
// inform about pin code request
|
||||
NSLog(@"HCI_EVENT_PIN_CODE_REQUEST\n");
|
||||
bt_send_cmd_ptr(hci_pin_code_request_reply_ptr, event_addr, 6, &packet[2]); // use inverse bd_addr as PIN
|
||||
for (int i = 0; i != packet[2]; i ++)
|
||||
{
|
||||
if (!discoveredDevice)
|
||||
{
|
||||
bt_flip_addr_ptr(event_addr, &packet[3 + i * 6]);
|
||||
discoveredDevice = [[BTDevice alloc] init];
|
||||
[discoveredDevice setAddress:&event_addr];
|
||||
}
|
||||
|
||||
// update
|
||||
discoveredDevice.pageScanRepetitionMode = packet [3 + packet[2] * (6) + i*1];
|
||||
discoveredDevice.classOfDevice = READ_BT_24(packet, 3 + packet[2] * (6+1+1+1) + i*3);
|
||||
discoveredDevice.clockOffset = READ_BT_16(packet, 3 + packet[2] * (6+1+1+1+3) + i*2) & 0x7fff;
|
||||
discoveredDevice.rssi = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// The inquiry has ended
|
||||
case HCI_EVENT_INQUIRY_COMPLETE:
|
||||
{
|
||||
// If we a device, ask for its name
|
||||
if (discoveredDevice)
|
||||
bt_send_cmd_ptr(hci_remote_name_request_ptr, [discoveredDevice address], discoveredDevice.pageScanRepetitionMode,
|
||||
0, discoveredDevice.clockOffset | 0x8000);
|
||||
// Keep looking
|
||||
else
|
||||
bt_send_cmd_ptr(hci_inquiry_ptr, HCI_INQUIRY_LAP, 3, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Received the name of a device
|
||||
case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
|
||||
{
|
||||
bt_flip_addr_ptr(event_addr, &packet[3]);
|
||||
|
||||
if (discoveredDevice && BD_ADDR_CMP(event_addr, discoveredDevice.address) == 0)
|
||||
{
|
||||
char cname[249];
|
||||
strncpy(cname, (const char*)&packet[9], 248);
|
||||
cname[248] = 0;
|
||||
|
||||
NSString* name = [NSString stringWithUTF8String:cname];
|
||||
[discoveredDevice setName:name];
|
||||
|
||||
// We found a WiiMote, pair with it
|
||||
if ([name hasPrefix:@"Nintendo RVL-CNT-01"])
|
||||
bt_send_cmd_ptr(l2cap_create_channel_ptr, [discoveredDevice address], PSM_HID_INTERRUPT);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Send PIN for pairing
|
||||
case HCI_EVENT_PIN_CODE_REQUEST:
|
||||
{
|
||||
bt_flip_addr_ptr(event_addr, &packet[2]);
|
||||
|
||||
if (discoveredDevice && BD_ADDR_CMP(event_addr, discoveredDevice.address) == 0)
|
||||
{
|
||||
// WiiMote: Use inverse bd_addr as PIN
|
||||
if (discoveredDevice.name && [discoveredDevice.name hasPrefix:@"Nintendo RVL-CNT-01"])
|
||||
bt_send_cmd_ptr(hci_pin_code_request_reply_ptr, event_addr, 6, &packet[2]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// WiiMote connections
|
||||
case L2CAP_EVENT_CHANNEL_OPENED:
|
||||
{
|
||||
// data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16)
|
||||
@ -273,11 +180,117 @@ static bool btOK;
|
||||
uint16_t source_cid = READ_BT_16(packet, 2);
|
||||
|
||||
bd_addr_t addr;
|
||||
wiimote_remove(source_cid,&addr);
|
||||
wiimote_remove(source_cid, &addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WiiMote handling
|
||||
case L2CAP_DATA_PACKET:
|
||||
{
|
||||
struct wiimote_t *wm = wiimote_get_by_source_cid(channel);
|
||||
if (wm)
|
||||
{
|
||||
byte* msg = packet + 2;
|
||||
|
||||
switch (packet[1])
|
||||
{
|
||||
case WM_RPT_BTN:
|
||||
{
|
||||
wiimote_pressed_buttons(wm, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RPT_READ:
|
||||
{
|
||||
wiimote_pressed_buttons(wm, msg);
|
||||
|
||||
byte len = ((msg[2] & 0xF0) >> 4) + 1;
|
||||
byte *data = (msg + 5);
|
||||
|
||||
wiimote_handshake(wm, WM_RPT_READ, data, len);
|
||||
return;
|
||||
}
|
||||
|
||||
case WM_RPT_CTRL_STATUS:
|
||||
{
|
||||
wiimote_pressed_buttons(wm, msg);
|
||||
wiimote_handshake(wm,WM_RPT_CTRL_STATUS,msg,-1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case WM_RPT_BTN_EXP:
|
||||
{
|
||||
wiimote_pressed_buttons(wm, msg);
|
||||
wiimote_handle_expansion(wm, msg+2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@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
|
||||
|
Loading…
x
Reference in New Issue
Block a user