mirror of
https://github.com/libretro/RetroArch
synced 2025-02-06 00:39:53 +00:00
ios: Update WiiMote code using newer features from BTstack. Probably some bugs, so I recommend sticking with the nobtstack builds for now.
This commit is contained in:
parent
bd088a3332
commit
f73511baa0
@ -8,10 +8,11 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
96096DD816D1ABAF00BF4499 /* RAModuleInfoList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */; };
|
||||
960DB2C416E0193D00F977E3 /* BTstackManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 960DB2C216E0193D00F977E3 /* BTstackManager.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
960DB2C716E0197600F977E3 /* BTDiscoveryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 960DB2C616E0197600F977E3 /* BTDiscoveryViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
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"; }; };
|
||||
9614C6BE16DD7C00000B36EF /* WiiMoteHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 9614C6BA16DD7C00000B36EF /* WiiMoteHelper.m */; };
|
||||
9614C6C116DD7D54000B36EF /* wiimote.c in Sources */ = {isa = PBXBuildFile; fileRef = 9614C6BF16DD7D54000B36EF /* wiimote.c */; };
|
||||
9614C6C416DDC018000B36EF /* autosave.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAE9D16C1D9A9009DE44C /* autosave.c */; };
|
||||
9614C6C516DDC018000B36EF /* cheats.c in Sources */ = {isa = PBXBuildFile; fileRef = 96AFAEA016C1D9A9009DE44C /* cheats.c */; };
|
||||
@ -176,10 +177,12 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAModuleInfoList.m; sourceTree = "<group>"; };
|
||||
960DB2C216E0193D00F977E3 /* BTstackManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTstackManager.m; sourceTree = "<group>"; };
|
||||
960DB2C316E0193D00F977E3 /* BTstackManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTstackManager.h; sourceTree = "<group>"; };
|
||||
960DB2C516E0197500F977E3 /* BTDiscoveryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTDiscoveryViewController.h; sourceTree = "<group>"; };
|
||||
960DB2C616E0197600F977E3 /* BTDiscoveryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTDiscoveryViewController.m; sourceTree = "<group>"; };
|
||||
9614C6AD16DD7C00000B36EF /* BTDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTDevice.h; sourceTree = "<group>"; };
|
||||
9614C6AE16DD7C00000B36EF /* BTDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTDevice.m; sourceTree = "<group>"; };
|
||||
9614C6AF16DD7C00000B36EF /* BTInquiryViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTInquiryViewController.h; sourceTree = "<group>"; };
|
||||
9614C6B016DD7C00000B36EF /* BTInquiryViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTInquiryViewController.m; sourceTree = "<group>"; };
|
||||
9614C6B216DD7C00000B36EF /* btstack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = btstack.h; sourceTree = "<group>"; };
|
||||
9614C6B316DD7C00000B36EF /* hci_cmds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hci_cmds.h; sourceTree = "<group>"; };
|
||||
9614C6B416DD7C00000B36EF /* linked_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = linked_list.h; sourceTree = "<group>"; };
|
||||
@ -382,8 +385,10 @@
|
||||
9614C6B116DD7C00000B36EF /* btstack */,
|
||||
9614C6AD16DD7C00000B36EF /* BTDevice.h */,
|
||||
9614C6AE16DD7C00000B36EF /* BTDevice.m */,
|
||||
9614C6AF16DD7C00000B36EF /* BTInquiryViewController.h */,
|
||||
9614C6B016DD7C00000B36EF /* BTInquiryViewController.m */,
|
||||
960DB2C516E0197500F977E3 /* BTDiscoveryViewController.h */,
|
||||
960DB2C616E0197600F977E3 /* BTDiscoveryViewController.m */,
|
||||
960DB2C216E0193D00F977E3 /* BTstackManager.m */,
|
||||
960DB2C316E0193D00F977E3 /* BTstackManager.h */,
|
||||
9614C6B816DD7C00000B36EF /* libBTstack.dylib */,
|
||||
9614C6B916DD7C00000B36EF /* WiiMoteHelper.h */,
|
||||
9614C6BA16DD7C00000B36EF /* WiiMoteHelper.m */,
|
||||
@ -957,9 +962,10 @@
|
||||
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 */,
|
||||
960DB2C416E0193D00F977E3 /* BTstackManager.m in Sources */,
|
||||
960DB2C716E0197600F977E3 /* BTDiscoveryViewController.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
//
|
||||
// BTDevice.h
|
||||
// BT-Keyboard
|
||||
//
|
||||
// Created by Matthias Ringwald on 3/30/09.
|
||||
//
|
||||
@ -59,25 +58,35 @@ typedef enum {
|
||||
} BluetoothConnectionState;
|
||||
|
||||
@interface BTDevice : NSObject {
|
||||
bd_addr_t address;
|
||||
|
||||
bd_addr_t _address;
|
||||
|
||||
NSString * name;
|
||||
uint32_t classOfDevice;
|
||||
|
||||
uint8_t pageScanRepetitionMode;
|
||||
uint16_t clockOffset;
|
||||
uint32_t classOfDevice;
|
||||
BluetoothConnectionState connectionState;
|
||||
|
||||
uint8_t rssi;
|
||||
|
||||
// deprecated
|
||||
BluetoothConnectionState connectionState;
|
||||
}
|
||||
|
||||
- (void) setAddress:(bd_addr_t *)addr;
|
||||
- (bd_addr_t *) address;
|
||||
- (void) setAddress:(bd_addr_t*)addr;
|
||||
- (BOOL) setAddressFromString:(NSString *) addressString;
|
||||
- (bd_addr_t*) address;
|
||||
- (NSString *) toString;
|
||||
+ (NSString *) stringForAddress:(bd_addr_t *) address;
|
||||
|
||||
- (NSString *) addressString;
|
||||
+ (NSString *) stringForAddress:(bd_addr_t*) address;
|
||||
+ (BOOL) address:(bd_addr_t *) address fromString:(NSString *) addressString;
|
||||
@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) uint8_t rssi;
|
||||
@property (nonatomic, assign) BluetoothConnectionState connectionState;
|
||||
|
||||
@end
|
||||
|
@ -44,32 +44,67 @@
|
||||
@synthesize connectionState;
|
||||
@synthesize pageScanRepetitionMode;
|
||||
@synthesize clockOffset;
|
||||
@synthesize rssi;
|
||||
|
||||
- (BTDevice *)init {
|
||||
name = NULL;
|
||||
bzero(&address, 6);
|
||||
memset(&_address, 0, 6);
|
||||
classOfDevice = kCODInvalid;
|
||||
connectionState = kBluetoothConnectionNotConnected;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) setAddress:(bd_addr_t *)newAddr{
|
||||
BD_ADDR_COPY( &address, newAddr);
|
||||
- (void) setAddress:(bd_addr_t*)newAddr{
|
||||
BD_ADDR_COPY( &_address, newAddr);
|
||||
}
|
||||
|
||||
- (bd_addr_t *) address{
|
||||
return &address;
|
||||
- (BOOL) setAddressFromString:(NSString *) addressString{
|
||||
return [BTDevice address:&_address fromString:addressString];
|
||||
}
|
||||
|
||||
+ (NSString *) stringForAddress:(bd_addr_t *) address {
|
||||
uint8_t * addr = (uint8_t*) address;
|
||||
- (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]];
|
||||
}
|
||||
|
||||
+ (BOOL) address:(bd_addr_t *)address fromString:(NSString *) addressString{
|
||||
// support both : and - or NOTHING as separator
|
||||
addressString = [addressString stringByReplacingOccurrencesOfString:@":" withString:@""];
|
||||
addressString = [addressString stringByReplacingOccurrencesOfString:@"-" withString:@""];
|
||||
if ([addressString length] != 12) return NO;
|
||||
|
||||
unsigned int bd_addr_buffer[BD_ADDR_LEN]; //for sscanf, integer needed
|
||||
// reset result buffer
|
||||
int i;
|
||||
for (i = 0; i < BD_ADDR_LEN; i++) {
|
||||
bd_addr_buffer[i] = 0;
|
||||
}
|
||||
|
||||
// parse
|
||||
int result = sscanf([addressString UTF8String], "%2x%2x%2x%2x%2x%2x", &bd_addr_buffer[0], &bd_addr_buffer[1], &bd_addr_buffer[2],
|
||||
&bd_addr_buffer[3], &bd_addr_buffer[4], &bd_addr_buffer[5]);
|
||||
// store
|
||||
if (result == 6){
|
||||
for (i = 0; i < BD_ADDR_LEN; i++) {
|
||||
(*address)[i] = (uint8_t) bd_addr_buffer[i];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSString *) nameOrAddress{
|
||||
if (name) return name;
|
||||
return [BTDevice stringForAddress:&address];
|
||||
return [self addressString];
|
||||
}
|
||||
|
||||
- (NSString *) addressString{
|
||||
return [BTDevice stringForAddress:&_address];
|
||||
}
|
||||
|
||||
- (BluetoothDeviceType) deviceType{
|
||||
@ -83,7 +118,7 @@
|
||||
}
|
||||
}
|
||||
- (NSString *) toString{
|
||||
return [NSString stringWithFormat:@"Device addr %@ name %@ COD %x", [BTDevice stringForAddress:&address], name, classOfDevice];
|
||||
return [NSString stringWithFormat:@"Device addr %@ name %@ COD %x", [BTDevice stringForAddress:&_address], name, classOfDevice];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
|
@ -28,20 +28,11 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// BTInquiryViewController.h
|
||||
//
|
||||
// Created by Matthias Ringwald on 10/8/09.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "BTstackManager.h"
|
||||
|
||||
#include "btstack/hci_cmds.h" // for HCI_STATE
|
||||
#include "btstack/utils.h"
|
||||
|
||||
@class BTDevice;
|
||||
@protocol BTInquiryDelegate;
|
||||
@class BTstackManager;
|
||||
@protocol BTDiscoveryDelegate;
|
||||
|
||||
typedef enum {
|
||||
kInquiryInactive,
|
||||
@ -49,46 +40,28 @@ typedef enum {
|
||||
kInquiryRemoteName
|
||||
} InquiryState;
|
||||
|
||||
@interface BTInquiryViewController : UITableViewController
|
||||
@interface BTDiscoveryViewController : UITableViewController<BTstackManagerListener>
|
||||
{
|
||||
NSMutableArray *devices;
|
||||
HCI_STATE bluetoothState;
|
||||
InquiryState inquiryState;
|
||||
BTstackManager *bt;
|
||||
NSObject<BTDiscoveryDelegate> * _delegate;
|
||||
UIActivityIndicatorView *deviceActivity;
|
||||
UIActivityIndicatorView *bluetoothActivity;
|
||||
UIFont * deviceNameFont;
|
||||
UIFont * macAddressFont;
|
||||
id<BTInquiryDelegate> delegate;
|
||||
bool allowSelection;
|
||||
bool showIcons;
|
||||
|
||||
// hacks
|
||||
bool stopRemoteNameGathering;
|
||||
bool restartInquiry;
|
||||
BTDevice *remoteNameDevice; // device for which remote name request is pending
|
||||
BTDevice *remoteDevice; // device for which connection is pending
|
||||
BTDevice *connectedDevice; // device to which we're connected
|
||||
bool notifyDelegateOnInquiryStopped;
|
||||
|
||||
InquiryState inquiryState;
|
||||
int remoteNameIndex;
|
||||
BOOL showIcons;
|
||||
int connectingIndex;
|
||||
NSString *customActivityText;
|
||||
}
|
||||
|
||||
- (void) startInquiry;
|
||||
- (void) stopInquiry;
|
||||
|
||||
- (void) showConnecting:(BTDevice *) device;
|
||||
- (void) showConnected:(BTDevice *) device;
|
||||
|
||||
- (void) removeDeviceForAddress:(bd_addr_t *)addr;
|
||||
|
||||
@property (nonatomic, assign) bool allowSelection;
|
||||
@property (nonatomic, assign) bool showIcons;
|
||||
@property (nonatomic, retain) NSMutableArray *devices;
|
||||
@property (nonatomic, retain) id<BTInquiryDelegate> delegate;
|
||||
-(void) markConnecting:(int)index; // use -1 for no connection active
|
||||
@property (nonatomic, assign) NSObject<BTDiscoveryDelegate> * delegate;
|
||||
@property (nonatomic, assign) BOOL showIcons;
|
||||
@property (nonatomic, retain) NSString *customActivityText;
|
||||
@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;
|
||||
@protocol BTDiscoveryDelegate
|
||||
@optional
|
||||
-(BOOL) discoveryView:(BTDiscoveryViewController*)discoveryView willSelectDeviceAtIndex:(int)deviceIndex; // returns NO to ignore selection
|
||||
-(void) statusCellSelectedDiscoveryView:(BTDiscoveryViewController*)discoveryView;
|
||||
@end
|
351
ios/RetroArch/BTStack/BTDiscoveryViewController.m
Normal file
351
ios/RetroArch/BTStack/BTDiscoveryViewController.m
Normal file
@ -0,0 +1,351 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#import "BTDiscoveryViewController.h"
|
||||
#import "BTDevice.h"
|
||||
|
||||
// fix compare for 3.0
|
||||
#ifndef __IPHONE_3_0
|
||||
#define __IPHONE_3_0 30000
|
||||
#endif
|
||||
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_0
|
||||
// SDK 30 defines missing in SDK 20
|
||||
@interface UITableViewCell (NewIn30)
|
||||
- (id)initWithStyle:(int)style reuseIdentifier:(NSString *)reuseIdentifier;
|
||||
@end
|
||||
#endif
|
||||
@interface UIDevice (privateAPI)
|
||||
-(BOOL) isWildcat;
|
||||
@end
|
||||
|
||||
@implementation BTDiscoveryViewController
|
||||
@synthesize showIcons;
|
||||
@synthesize delegate = _delegate;
|
||||
@synthesize customActivityText;
|
||||
|
||||
- (id) init {
|
||||
self = [super initWithStyle:UITableViewStyleGrouped];
|
||||
macAddressFont = [UIFont fontWithName:@"Courier New" size:[UIFont labelFontSize]];
|
||||
deviceNameFont = [UIFont boldSystemFontOfSize:[UIFont labelFontSize]];
|
||||
inquiryState = kInquiryInactive;
|
||||
connectingIndex = -1;
|
||||
|
||||
deviceActivity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
|
||||
[deviceActivity startAnimating];
|
||||
bluetoothActivity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
|
||||
[bluetoothActivity startAnimating];
|
||||
|
||||
bt = [BTstackManager sharedInstance];
|
||||
_delegate = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void) reload{
|
||||
[[self tableView] reloadData];
|
||||
}
|
||||
|
||||
/*
|
||||
- (id)initWithStyle:(UITableViewStyle)style {
|
||||
// Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
|
||||
if (self = [super initWithStyle:style]) {
|
||||
}
|
||||
return self;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (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 for supported orientations
|
||||
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.
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// BTstackManagerListenerDelegate
|
||||
-(void) activatedBTstackManager:(BTstackManager*) manager{
|
||||
[self reload];
|
||||
}
|
||||
-(void) btstackManager:(BTstackManager*)manager activationFailed:(BTstackError)error {
|
||||
[self reload];
|
||||
}
|
||||
-(void) discoveryInquiryBTstackManager:(BTstackManager*) manager {
|
||||
inquiryState = kInquiryActive;
|
||||
[self reload];
|
||||
}
|
||||
-(void) btstackManager:(BTstackManager*)manager discoveryQueryRemoteName:(int)deviceIndex {
|
||||
inquiryState = kInquiryRemoteName;
|
||||
remoteNameIndex = deviceIndex;
|
||||
[self reload];
|
||||
}
|
||||
-(void) discoveryStoppedBTstackManager:(BTstackManager*) manager {
|
||||
inquiryState = kInquiryInactive;
|
||||
[self reload];
|
||||
}
|
||||
-(void) btstackManager:(BTstackManager*)manager deviceInfo:(BTDevice*)device {
|
||||
[self reload];
|
||||
}
|
||||
|
||||
-(void) markConnecting:(int)index; {
|
||||
connectingIndex = index;
|
||||
[self reload];
|
||||
}
|
||||
|
||||
-(void) setCustomActivityText:(NSString*) text{
|
||||
[text retain];
|
||||
[customActivityText release];
|
||||
customActivityText = text;
|
||||
[self reload];
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return 1 + [bt numberOfDevicesFound];
|
||||
}
|
||||
|
||||
|
||||
// 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) {
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_0
|
||||
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
|
||||
#else
|
||||
cell = [[[UITableViewCell alloc] initWithFrame:CGRectNull reuseIdentifier:(NSString *)CellIdentifier] autorelease];
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set up the cell...
|
||||
NSString *theLabel = nil;
|
||||
UIImage *theImage = nil;
|
||||
UIFont *theFont = nil;
|
||||
|
||||
int idx = [indexPath indexAtPosition:1];
|
||||
if (idx >= [bt numberOfDevicesFound]) {
|
||||
if (customActivityText) {
|
||||
theLabel = customActivityText;
|
||||
cell.accessoryView = bluetoothActivity;
|
||||
} else if ([bt isActivating]){
|
||||
theLabel = @"Activating BTstack...";
|
||||
cell.accessoryView = bluetoothActivity;
|
||||
} else if (![bt isActive]){
|
||||
theLabel = @"Bluetooth not accessible!";
|
||||
cell.accessoryView = nil;
|
||||
} else {
|
||||
|
||||
#if 0
|
||||
if (connectedDevice) {
|
||||
theLabel = @"Disconnect";
|
||||
cell.accessoryView = nil;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (connectingIndex >= 0) {
|
||||
theLabel = @"Connecting...";
|
||||
cell.accessoryView = bluetoothActivity;
|
||||
} else {
|
||||
switch (inquiryState){
|
||||
case kInquiryInactive:
|
||||
if ([bt numberOfDevicesFound] > 0){
|
||||
theLabel = @"Find more devices...";
|
||||
} else {
|
||||
theLabel = @"Find devices...";
|
||||
}
|
||||
cell.accessoryView = nil;
|
||||
break;
|
||||
case kInquiryActive:
|
||||
theLabel = @"Searching...";
|
||||
cell.accessoryView = bluetoothActivity;
|
||||
break;
|
||||
case kInquiryRemoteName:
|
||||
theLabel = @"Query device names...";
|
||||
cell.accessoryView = bluetoothActivity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
BTDevice *dev = [bt deviceAtIndex:idx];
|
||||
|
||||
// pick font
|
||||
theLabel = [dev nameOrAddress];
|
||||
if ([dev name]){
|
||||
theFont = deviceNameFont;
|
||||
} else {
|
||||
theFont = macAddressFont;
|
||||
}
|
||||
|
||||
// pick an icon for the devices
|
||||
if (showIcons) {
|
||||
NSString *imageName = @"bluetooth.png";
|
||||
// check major device class
|
||||
switch (([dev classOfDevice] & 0x1f00) >> 8) {
|
||||
case 0x01:
|
||||
imageName = @"computer.png";
|
||||
break;
|
||||
case 0x02:
|
||||
imageName = @"smartphone.png";
|
||||
break;
|
||||
case 0x05:
|
||||
switch ([dev classOfDevice] & 0xff){
|
||||
case 0x40:
|
||||
imageName = @"keyboard.png";
|
||||
break;
|
||||
case 0x80:
|
||||
imageName = @"mouse.png";
|
||||
break;
|
||||
case 0xc0:
|
||||
imageName = @"keyboard.png";
|
||||
break;
|
||||
default:
|
||||
imageName = @"HID.png";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LASER_KB
|
||||
if ([dev name] && [[dev name] isEqualToString:@"CL800BT"]){
|
||||
imageName = @"keyboard.png";
|
||||
}
|
||||
|
||||
if ([dev name] && [[dev name] isEqualToString:@"CL850"]){
|
||||
imageName = @"keyboard.png";
|
||||
}
|
||||
|
||||
// Celluon CL800BT, CL850 have 00-0b-24-aa-bb-cc, COD 0x400210
|
||||
uint8_t *addr = (uint8_t *) [dev address];
|
||||
if (addr[0] == 0x00 && addr[1] == 0x0b && addr[2] == 0x24){
|
||||
imageName = @"keyboard.png";
|
||||
}
|
||||
#endif
|
||||
theImage = [UIImage imageNamed:imageName];
|
||||
}
|
||||
|
||||
// set accessory view
|
||||
if (idx == connectingIndex){
|
||||
cell.accessoryView = deviceActivity;
|
||||
} else {
|
||||
cell.accessoryView = nil;
|
||||
}
|
||||
}
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_3_0
|
||||
if (theLabel) cell.textLabel.text = theLabel;
|
||||
if (theFont) cell.textLabel.font = theFont;
|
||||
if (theImage) cell.imageView.image = theImage;
|
||||
#else
|
||||
if (theLabel) cell.text = theLabel;
|
||||
if (theFont) cell.font = theFont;
|
||||
if (theImage) cell.image = theImage;
|
||||
#endif
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
||||
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (!_delegate) return nil;
|
||||
int index = [indexPath indexAtPosition:1];
|
||||
if (index >= [bt numberOfDevicesFound]){
|
||||
if ([_delegate respondsToSelector:@selector(statusCellSelectedDiscoveryView:)]){
|
||||
[_delegate statusCellSelectedDiscoveryView:self];
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
if ([_delegate respondsToSelector:@selector(discoveryView:willSelectDeviceAtIndex:)] && [_delegate discoveryView:self willSelectDeviceAtIndex:index]){
|
||||
return indexPath;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Override to allow orientations other than the default portrait orientation.
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
||||
UIDevice * uiDevice = [UIDevice currentDevice];
|
||||
return [uiDevice respondsToSelector:@selector(isWildcat)] && [uiDevice isWildcat];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
@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.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// BTInquiryViewController.m
|
||||
//
|
||||
// Created by Matthias Ringwald on 10/8/09.
|
||||
//
|
||||
|
||||
#import "BTInquiryViewController.h"
|
||||
#import "BTDevice.h"
|
||||
#import <UIKit/UIToolbar.h>
|
||||
|
||||
#include "btstack/btstack.h"
|
||||
//#include "wiimote.h"
|
||||
|
||||
#define INQUIRY_INTERVAL 3
|
||||
|
||||
unsigned myosd_num_of_joys = 0;
|
||||
|
||||
static BTInquiryViewController *inqView;
|
||||
static btstack_packet_handler_t clientHandler;
|
||||
static uint8_t remoteNameIndex;
|
||||
|
||||
@interface BTInquiryViewController (Private)
|
||||
- (void) handlePacket:(uint8_t) packet_type channel:(uint16_t) channel packet:(uint8_t*) packet size:(uint16_t) size;
|
||||
- (BTDevice *) getDeviceForAddress:(bd_addr_t *)addr;
|
||||
- (void) getNextRemoteName;
|
||||
- (void) startInquiry;
|
||||
@end
|
||||
|
||||
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
if (inqView) {
|
||||
[inqView handlePacket:packet_type channel:channel packet:packet size:size];
|
||||
}
|
||||
}
|
||||
|
||||
@implementation BTInquiryViewController
|
||||
|
||||
|
||||
@synthesize devices;
|
||||
@synthesize delegate;
|
||||
@synthesize allowSelection;
|
||||
@synthesize showIcons;
|
||||
|
||||
- (id) init {
|
||||
self = [super initWithStyle:UITableViewStyleGrouped];
|
||||
bluetoothState = HCI_STATE_OFF;
|
||||
inquiryState = kInquiryInactive;
|
||||
allowSelection = false;
|
||||
showIcons = false;
|
||||
remoteDevice = nil;
|
||||
restartInquiry = true;
|
||||
notifyDelegateOnInquiryStopped = false;
|
||||
|
||||
macAddressFont = [UIFont fontWithName:@"Courier New" size:[UIFont labelFontSize]];
|
||||
deviceNameFont = [UIFont boldSystemFontOfSize:[UIFont labelFontSize]];
|
||||
|
||||
deviceActivity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
|
||||
[deviceActivity startAnimating];
|
||||
bluetoothActivity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
|
||||
[bluetoothActivity startAnimating];
|
||||
|
||||
devices = [[NSMutableArray alloc] init];
|
||||
inqView = self;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) myStartInquiry{
|
||||
if (inquiryState != kInquiryInactive) {
|
||||
NSLog(@"Inquiry already active");
|
||||
return;
|
||||
}
|
||||
NSLog(@"Inquiry started");
|
||||
|
||||
stopRemoteNameGathering = false;
|
||||
restartInquiry = true;
|
||||
|
||||
inquiryState = kInquiryActive;
|
||||
[[self tableView] reloadData];
|
||||
|
||||
bt_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
|
||||
}
|
||||
|
||||
- (void) handlePacket:(uint8_t) packet_type channel:(uint16_t) channel packet:(uint8_t*) packet size:(uint16_t) size {
|
||||
bd_addr_t event_addr;
|
||||
switch (packet_type) {
|
||||
|
||||
case HCI_EVENT_PACKET:
|
||||
|
||||
switch (packet[0]){
|
||||
|
||||
case BTSTACK_EVENT_STATE:
|
||||
{
|
||||
// bt stack activated
|
||||
bluetoothState = (HCI_STATE)packet[2];
|
||||
[[self tableView] reloadData];
|
||||
|
||||
// set BT state
|
||||
/*
|
||||
if (bluetoothState == HCI_STATE_WORKING) {
|
||||
[self myStartInquiry];
|
||||
}
|
||||
*/
|
||||
break;
|
||||
}
|
||||
case BTSTACK_EVENT_POWERON_FAILED:
|
||||
{
|
||||
bluetoothState = HCI_STATE_OFF;
|
||||
[[self tableView] reloadData];
|
||||
|
||||
UIAlertView* alertView = [[UIAlertView alloc] init];
|
||||
alertView.title = @"Bluetooth not accessible!";
|
||||
alertView.message = @"Hardware initialization failed!\n"
|
||||
"Make sure you have turned off Bluetooth in the System Settings.";
|
||||
NSLog(@"Alert: %@ - %@", alertView.title, alertView.message);
|
||||
[alertView addButtonWithTitle:@"Dismiss"];
|
||||
[alertView show];
|
||||
break;
|
||||
}
|
||||
case HCI_EVENT_INQUIRY_RESULT:
|
||||
case HCI_EVENT_INQUIRY_RESULT_WITH_RSSI:
|
||||
{
|
||||
int numResponses = packet[2];
|
||||
int i;
|
||||
for (i=0; i<numResponses;i++){
|
||||
bd_addr_t addr;
|
||||
bt_flip_addr(addr, &packet[3+i*6]);
|
||||
if ([inqView getDeviceForAddress:&addr]) {
|
||||
NSLog(@"Device %@ already in list", [BTDevice stringForAddress:&addr]);
|
||||
continue;
|
||||
}
|
||||
BTDevice *dev = [[BTDevice alloc] init];
|
||||
[dev setAddress:&addr];
|
||||
[dev setPageScanRepetitionMode:packet[3 + numResponses*6 + i]];
|
||||
[dev setClassOfDevice:READ_BT_24(packet, 3 + numResponses*(6+1+1+1) + i*3)];
|
||||
[dev setClockOffset:(READ_BT_16(packet, 3 + numResponses*(6+1+1+1+3) + i*2) & 0x7fff)];
|
||||
// hexdump(packet, size);
|
||||
NSLog(@"--> adding %@", [dev toString] );
|
||||
[devices addObject:dev];
|
||||
if (delegate) {
|
||||
[delegate deviceDetected:self device:dev];
|
||||
}
|
||||
}
|
||||
|
||||
[[inqView tableView] reloadData];
|
||||
NSLog(@"bye" );
|
||||
break;
|
||||
}
|
||||
case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE:
|
||||
{
|
||||
bt_flip_addr(event_addr, &packet[3]);
|
||||
BTDevice *dev = [inqView getDeviceForAddress:&event_addr];
|
||||
if (!dev) break;
|
||||
[dev setConnectionState:kBluetoothConnectionNotConnected];
|
||||
if (packet[2] == 0) {
|
||||
[dev setName:[NSString stringWithUTF8String:(const char *) &packet[9]]];
|
||||
if (delegate) {
|
||||
[delegate deviceDetected:self device:dev];
|
||||
}
|
||||
}
|
||||
[[self tableView] reloadData];
|
||||
remoteNameIndex++;
|
||||
[self getNextRemoteName];
|
||||
break;
|
||||
}
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
{
|
||||
if (COMMAND_COMPLETE_EVENT(packet, hci_inquiry_cancel)){
|
||||
// inquiry canceled
|
||||
NSLog(@"Inquiry cancelled successfully");
|
||||
inquiryState = kInquiryInactive;
|
||||
[[self tableView] reloadData];
|
||||
if (notifyDelegateOnInquiryStopped){
|
||||
notifyDelegateOnInquiryStopped = false;
|
||||
if (delegate) {
|
||||
[delegate inquiryStopped];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (COMMAND_COMPLETE_EVENT(packet, hci_remote_name_request_cancel)){
|
||||
// inquiry canceled
|
||||
NSLog(@"Remote name request cancelled successfully");
|
||||
inquiryState = kInquiryInactive;
|
||||
[[self tableView] reloadData];
|
||||
if (notifyDelegateOnInquiryStopped){
|
||||
notifyDelegateOnInquiryStopped = false;
|
||||
if (delegate) {
|
||||
[delegate inquiryStopped];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case HCI_EVENT_INQUIRY_COMPLETE:
|
||||
{
|
||||
NSLog(@"Inquiry complete");
|
||||
// reset name check
|
||||
remoteNameIndex = 0;
|
||||
[self getNextRemoteName];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
|
||||
// hexdump(packet, size);
|
||||
//break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// forward to client app
|
||||
(*clientHandler)(packet_type, channel, packet, size);
|
||||
}
|
||||
|
||||
- (BTDevice *) getDeviceForAddress:(bd_addr_t *)addr {
|
||||
uint8_t j;
|
||||
for (j=0; j<[devices count]; j++){
|
||||
BTDevice *dev = [devices objectAtIndex:j];
|
||||
if (BD_ADDR_CMP(addr, [dev address]) == 0){
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
- (void) removeDeviceForAddress:(bd_addr_t *)addr {
|
||||
uint8_t j;
|
||||
for (j=0; j<[devices count]; j++){
|
||||
BTDevice *dev = [devices objectAtIndex:j];
|
||||
if (BD_ADDR_CMP(addr, [dev address]) == 0){
|
||||
NSLog(@"--> removed %@", [dev toString] );
|
||||
[devices removeObject:dev];
|
||||
[[self tableView] reloadData];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void) getNextRemoteName{
|
||||
|
||||
// stopped?
|
||||
if (stopRemoteNameGathering) {
|
||||
inquiryState = kInquiryInactive;
|
||||
[[self tableView] reloadData];
|
||||
|
||||
if (notifyDelegateOnInquiryStopped){
|
||||
notifyDelegateOnInquiryStopped = false;
|
||||
if (delegate) {
|
||||
[delegate inquiryStopped];
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
remoteNameDevice = nil;
|
||||
|
||||
for (remoteNameIndex = 0; remoteNameIndex < [devices count]; remoteNameIndex++){
|
||||
BTDevice *dev = [devices objectAtIndex:remoteNameIndex];
|
||||
if (![dev name]){
|
||||
remoteNameDevice = dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (remoteNameDevice) {
|
||||
inquiryState = kInquiryRemoteName;
|
||||
[remoteNameDevice setConnectionState:kBluetoothConnectionRemoteName];
|
||||
bt_send_cmd(&hci_remote_name_request, [remoteNameDevice address], [remoteNameDevice pageScanRepetitionMode], 0, [remoteNameDevice clockOffset] | 0x8000);
|
||||
} else {
|
||||
inquiryState = kInquiryInactive;
|
||||
// inquiry done.
|
||||
if (restartInquiry) {
|
||||
[self myStartInquiry];
|
||||
}
|
||||
}
|
||||
[[self tableView] reloadData];
|
||||
}
|
||||
|
||||
- (void) startInquiry {
|
||||
//static int b = 0;
|
||||
//if(!b)
|
||||
//{
|
||||
//b=1;
|
||||
// put into loop
|
||||
|
||||
// @TODO: cannot be called a second time!
|
||||
clientHandler = bt_register_packet_handler(packet_handler);
|
||||
|
||||
bluetoothState = HCI_STATE_INITIALIZING;
|
||||
[[self tableView] reloadData];
|
||||
|
||||
stopRemoteNameGathering = false;
|
||||
restartInquiry = true;
|
||||
|
||||
bt_send_cmd(&btstack_set_power_mode, HCI_POWER_ON );
|
||||
//}
|
||||
}
|
||||
|
||||
- (void) stopInquiry {
|
||||
|
||||
NSLog(@"stop inquiry called, state %u", inquiryState);
|
||||
restartInquiry = false;
|
||||
stopRemoteNameGathering = true;
|
||||
bool immediateNotify = true;
|
||||
|
||||
switch (inquiryState) {
|
||||
case kInquiryActive:
|
||||
// just stop inquiry
|
||||
immediateNotify = false;
|
||||
bt_send_cmd(&hci_inquiry_cancel);
|
||||
break;
|
||||
case kInquiryInactive:
|
||||
NSLog(@"stop inquiry called although inquiry inactive?");
|
||||
break;
|
||||
case kInquiryRemoteName:
|
||||
if (remoteNameDevice) {
|
||||
// just stop remote name request
|
||||
immediateNotify = false;
|
||||
bt_send_cmd(&hci_remote_name_request_cancel, [remoteNameDevice address]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (immediateNotify && delegate){
|
||||
[delegate inquiryStopped];
|
||||
} else {
|
||||
notifyDelegateOnInquiryStopped = true;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) showConnecting:(BTDevice *) device {
|
||||
remoteDevice = device;
|
||||
[[self tableView] reloadData];
|
||||
}
|
||||
|
||||
- (void) showConnected:(BTDevice *) device {
|
||||
connectedDevice = device;
|
||||
[[self tableView] reloadData];
|
||||
}
|
||||
|
||||
/*
|
||||
- (void)loadView {
|
||||
|
||||
[super loadView];
|
||||
|
||||
}
|
||||
*/
|
||||
/*
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
|
||||
//self.navigationItem.rightBarButtonItem = self.editButtonItem;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
}
|
||||
*/
|
||||
/*
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
[super viewDidAppear:animated];
|
||||
}
|
||||
*/
|
||||
/*
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
}
|
||||
*/
|
||||
/*
|
||||
- (void)viewDidDisappear:(BOOL)animated {
|
||||
[super viewDidDisappear:animated];
|
||||
}
|
||||
*/
|
||||
|
||||
// Override to allow orientations other than the default portrait orientation.
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
||||
return YES;
|
||||
//return NO;
|
||||
//return (interfaceOrientation == UIInterfaceOrientationPortrait);
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
// Releases the view if it doesn't have a superview.
|
||||
[super didReceiveMemoryWarning];
|
||||
|
||||
// Release any cached data, images, etc that aren't in use.
|
||||
}
|
||||
|
||||
- (void)viewDidUnload {
|
||||
// Release any retained subviews of the main view.
|
||||
// e.g. self.myOutlet = nil;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
// unregister self
|
||||
bt_register_packet_handler(clientHandler);
|
||||
// done
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Table view methods
|
||||
|
||||
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
|
||||
return @"Devices";
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Customize the number of rows in the table view.
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
int rows = 1; // 1 for status line
|
||||
if (bluetoothState == HCI_STATE_WORKING) {
|
||||
rows += [devices count];
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
|
||||
// Customize the appearance of table view cells.
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
|
||||
static NSString *CellIdentifier = @"Cell";
|
||||
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
|
||||
if (cell == nil) {
|
||||
cell = [[[UITableViewCell alloc] initWithStyle:/* UITableViewCellStyleDefault = */(UITableViewCellStyle)0 reuseIdentifier:CellIdentifier] autorelease];
|
||||
// cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
}
|
||||
|
||||
// Set up the cell...
|
||||
NSString *label = nil;
|
||||
int idx = [indexPath indexAtPosition:1];
|
||||
if (bluetoothState != HCI_STATE_WORKING || idx >= [devices count]) {
|
||||
if (bluetoothState == HCI_STATE_INITIALIZING){
|
||||
label = @"Activating BTstack...";
|
||||
cell.accessoryView = bluetoothActivity;
|
||||
} else if (bluetoothState == HCI_STATE_OFF){
|
||||
label = @"Bluetooth not accessible!";
|
||||
cell.accessoryView = nil;
|
||||
} else {
|
||||
if (connectedDevice) {
|
||||
label = @"Disconnect";
|
||||
cell.accessoryView = nil;
|
||||
} else if (remoteDevice) {
|
||||
label = @"Connecting...";
|
||||
cell.accessoryView = bluetoothActivity;
|
||||
} else {
|
||||
switch (inquiryState){
|
||||
case kInquiryInactive:
|
||||
if (myosd_num_of_joys==4)
|
||||
{
|
||||
label = @"Maximun devices connected!";
|
||||
}
|
||||
else if ([devices count] > 0){
|
||||
label = @"Press here to find more devices...";
|
||||
} else {
|
||||
label = @"Press here to find first device...";
|
||||
}
|
||||
cell.accessoryView = nil;
|
||||
break;
|
||||
case kInquiryActive:
|
||||
//label = @"Searching...";
|
||||
label = @"Press 1 and 2 on the WiiMote to sync";
|
||||
cell.accessoryView = bluetoothActivity;
|
||||
break;
|
||||
case kInquiryRemoteName:
|
||||
label = @"Query device names...";
|
||||
cell.accessoryView = bluetoothActivity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BTDevice *dev = [devices objectAtIndex:idx];
|
||||
label = [dev nameOrAddress];
|
||||
if ([dev name]){
|
||||
cell.font = deviceNameFont;
|
||||
} else {
|
||||
cell.font = macAddressFont;
|
||||
}
|
||||
// pick an icon for the devices
|
||||
if (showIcons) {
|
||||
int major = ([dev classOfDevice] & 0x1f00) >> 8;
|
||||
if (major == 0x01) {
|
||||
cell.image = [UIImage imageNamed:@"computer.png"];
|
||||
} else if (major == 0x02) {
|
||||
cell.image = [UIImage imageNamed:@"smartphone.png"];
|
||||
} else if ( major == 0x05 && ([dev classOfDevice] & 0xff) == 0x40){
|
||||
cell.image = [UIImage imageNamed:@"keyboard.png"];
|
||||
} else {
|
||||
cell.image = [UIImage imageNamed:@"bluetooth.png"];
|
||||
}
|
||||
}
|
||||
switch ([dev connectionState]) {
|
||||
case kBluetoothConnectionNotConnected:
|
||||
case kBluetoothConnectionConnected:
|
||||
cell.accessoryView = nil;
|
||||
break;
|
||||
case kBluetoothConnectionConnecting:
|
||||
case kBluetoothConnectionRemoteName:
|
||||
cell.accessoryView = deviceActivity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cell.text = label;
|
||||
return cell;
|
||||
}
|
||||
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
NSLog(@"didSelectRowAtIndexPath %@", indexPath);
|
||||
// Navigation logic may go here. Create and push another view controller.
|
||||
// AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
|
||||
// [self.navigationController pushViewController:anotherViewController];
|
||||
// [anotherViewController release];
|
||||
|
||||
// valid selection?
|
||||
|
||||
|
||||
int idx = [indexPath indexAtPosition:1];
|
||||
//printf("sleccion %d\n",idx);
|
||||
if (bluetoothState == HCI_STATE_WORKING) {
|
||||
if (delegate) {
|
||||
if (idx < [devices count]){
|
||||
[delegate deviceChoosen:self device:[devices objectAtIndex:idx]];
|
||||
} else if (idx == [devices count]) {
|
||||
//printf("seleccionado %d %d\n",idx,connectedDevice);
|
||||
if (connectedDevice) {
|
||||
// DISCONNECT button
|
||||
[delegate disconnectDevice:self device:connectedDevice];
|
||||
} else if (myosd_num_of_joys<4){
|
||||
// Find more devices
|
||||
[self myStartInquiry];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:TRUE];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (allowSelection) {
|
||||
return indexPath;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
188
ios/RetroArch/BTStack/BTstackManager.h
Normal file
188
ios/RetroArch/BTStack/BTstackManager.h
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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
|
590
ios/RetroArch/BTStack/BTstackManager.m
Normal file
590
ios/RetroArch/BTStack/BTstackManager.m
Normal file
@ -0,0 +1,590 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#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(RUN_LOOP_COCOA);
|
||||
|
||||
// our packet handler
|
||||
bt_register_packet_handler(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();
|
||||
if (err) return BTSTACK_CONNECTION_TO_BTDAEMON_FAILED;
|
||||
}
|
||||
connectedToDaemon = YES;
|
||||
|
||||
// check system BT
|
||||
state = kW4SysBTState;
|
||||
bt_send_cmd(&btstack_get_system_bluetooth_enabled);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
-(BTstackError) deactivate {
|
||||
if (!connectedToDaemon) return BTSTACK_CONNECTION_TO_BTDAEMON_FAILED;
|
||||
state = kW4Deactivated;
|
||||
bt_send_cmd(&btstack_set_power_mode, 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(&hci_write_inquiry_mode, 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(&hci_inquiry_cancel);
|
||||
break;
|
||||
case kRemoteName: {
|
||||
discoveryState = kW4RemoteNameBeforeStop;
|
||||
BTDevice *device = [discoveredDevices objectAtIndex:discoveryDeviceIndex];
|
||||
bt_send_cmd(&hci_remote_name_request_cancel, [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(&btstack_set_system_bluetooth_enabled, 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(&btstack_set_power_mode, 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(&hci_remote_name_request, [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(&hci_inquiry, 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(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(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) ) {
|
||||
discoveryState = kInquiry;
|
||||
bt_send_cmd(&hci_inquiry, 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(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(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) ) {
|
||||
discoveryState = kInactive;
|
||||
[self sendDiscoveryStoppedEvent];
|
||||
}
|
||||
break;
|
||||
|
||||
case kW4InquiryStop:
|
||||
if (packet[0] == HCI_EVENT_INQUIRY_COMPLETE
|
||||
|| COMMAND_COMPLETE_EVENT(packet, hci_inquiry_cancel)) {
|
||||
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)){
|
||||
discoveryState = kInactive;
|
||||
[self sendDiscoveryStoppedEvent];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
-(void) dropLinkKeyForAddress:(bd_addr_t*) address {
|
||||
bt_send_cmd(&hci_delete_stored_link_key, 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(&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,19 +31,10 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "BTInquiryViewController.h"
|
||||
|
||||
@interface WiiMoteHelper : NSObject<BTInquiryDelegate>
|
||||
{
|
||||
}
|
||||
|
||||
+ (void)startwiimote:(UIViewController *)controller;
|
||||
+ (void)endwiimote;
|
||||
+ (void)cancelWiiMoteSearch;
|
||||
#import "BTDiscoveryViewController.h"
|
||||
|
||||
@interface WiiMoteHelper : NSObject<BTDiscoveryDelegate, BTstackManagerDelegate, BTstackManagerListener>
|
||||
+ (WiiMoteHelper*)get;
|
||||
- (void)showDiscovery;
|
||||
@end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -37,391 +37,241 @@
|
||||
#import "WiiMoteHelper.h"
|
||||
|
||||
#import "BTDevice.h"
|
||||
#import "BTInquiryViewController.h"
|
||||
#import "BTstackManager.h"
|
||||
#import "BTDiscoveryViewController.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;
|
||||
}
|
||||
}
|
||||
static BTDevice *device;
|
||||
static uint16_t wiiMoteConHandle = 0;
|
||||
static bool btOK;
|
||||
static WiiMoteHelper* instance;
|
||||
|
||||
@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
|
||||
+ (WiiMoteHelper*)get
|
||||
{
|
||||
|
||||
if(buttonIndex == 0 )
|
||||
{
|
||||
[inqViewControl setDelegate:self];
|
||||
[inqViewControl setAllowSelection:true];
|
||||
activated = true;
|
||||
[inqViewControl startInquiry];
|
||||
}
|
||||
else
|
||||
{
|
||||
[inqViewControl dismissModalViewControllerAnimated:YES];
|
||||
}
|
||||
if (!instance)
|
||||
{
|
||||
instance = [WiiMoteHelper new];
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
+(void) cancelWiiMoteSearch {
|
||||
[inqViewControl stopInquiry];
|
||||
[inqViewControl dismissModalViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
|
||||
+(void) deviceChoosen:(BTInquiryViewController *) inqView device:(BTDevice*) deviceChoosen;
|
||||
- (id)init
|
||||
{
|
||||
NSLog(@"deviceChoosen %@", [device toString]);
|
||||
if (!btOK)
|
||||
{
|
||||
BTstackManager* bt = [BTstackManager sharedInstance];
|
||||
[bt setDelegate:self];
|
||||
[bt addListener:self];
|
||||
|
||||
btOK = [bt activate] == 0;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (void) deviceDetected:(BTInquiryViewController *) inqView device:(BTDevice*) selectedDevice {
|
||||
- (void)dealloc
|
||||
{
|
||||
// TODO: Any other cleanup needed
|
||||
[[BTstackManager sharedInstance] deactivate];
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
- (void)showDiscovery
|
||||
{
|
||||
BTDiscoveryViewController* vc = [BTDiscoveryViewController new];
|
||||
[vc setDelegate:self];
|
||||
|
||||
[[BTstackManager sharedInstance] addListener:vc];
|
||||
|
||||
[[RetroArch_iOS get] pushViewController:vc isGame:NO];
|
||||
}
|
||||
|
||||
// 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(&hci_write_authentication_enable, 0);
|
||||
}
|
||||
|
||||
// BTStackManagerDelegate
|
||||
-(void) btstackManager:(BTstackManager*) manager
|
||||
handlePacketWithType:(uint8_t) packet_type
|
||||
forChannel:(uint16_t) channel
|
||||
andData:(uint8_t *)packet
|
||||
withLen:(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);
|
||||
|
||||
[inqViewControl stopInquiry];
|
||||
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;
|
||||
}
|
||||
|
||||
[inqViewControl showConnecting:device];
|
||||
case WM_RPT_WRITE:
|
||||
{
|
||||
/* write feedback - safe to skip */
|
||||
break;
|
||||
}
|
||||
|
||||
// connect to device
|
||||
[device setConnectionState:kBluetoothConnectionConnecting];
|
||||
[[inqViewControl tableView] reloadData];
|
||||
bt_send_cmd(&l2cap_create_channel, [device address], 0x13);
|
||||
|
||||
|
||||
}
|
||||
default:
|
||||
{
|
||||
printf("Unknown event, can not handle it [Code 0x%x].", event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case HCI_EVENT_PACKET://0x04
|
||||
{
|
||||
switch (packet[0])
|
||||
{
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
{
|
||||
if (COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable))
|
||||
bt_send_cmd(&l2cap_create_channel, [device address], PSM_HID_INTERRUPT);
|
||||
break;
|
||||
}
|
||||
|
||||
case HCI_EVENT_PIN_CODE_REQUEST:
|
||||
{
|
||||
bt_flip_addr(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(&hci_pin_code_request_reply, event_addr, 6, &packet[2]); // use inverse bd_addr as PIN
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (psm == 0x13)
|
||||
{
|
||||
// interupt channel openedn succesfully, now open control channel, too.
|
||||
bt_send_cmd(&l2cap_create_channel, event_addr, 0x11);
|
||||
struct wiimote_t *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);
|
||||
wm->exp.type = EXP_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//inicializamos el wiimote!
|
||||
struct wiimote_t *wm = &joys[myosd_num_of_joys];
|
||||
wm->wiiMoteConHandle = wiiMoteConHandle;
|
||||
wm->c_source_cid = source_cid;
|
||||
wm->state = WIIMOTE_STATE_CONNECTED;
|
||||
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);
|
||||
|
||||
bd_addr_t addr;
|
||||
wiimote_remove(source_cid,&addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (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
|
||||
|
||||
|
@ -64,10 +64,10 @@ typedef void (*btstack_packet_handler_t) (uint8_t packet_type, uint16_t channel,
|
||||
void bt_use_tcp(const char * address, uint16_t port);
|
||||
|
||||
// init BTstack library
|
||||
int bt_open();
|
||||
int bt_open(void);
|
||||
|
||||
// stop using BTstack library
|
||||
int bt_close();
|
||||
int bt_close(void);
|
||||
|
||||
// send hci cmd packet
|
||||
int bt_send_cmd(const hci_cmd_t *cmd, ...);
|
||||
@ -79,6 +79,7 @@ btstack_packet_handler_t bt_register_packet_handler(btstack_packet_handler_t han
|
||||
void bt_send_acl(uint8_t * data, uint16_t len);
|
||||
|
||||
void bt_send_l2cap(uint16_t local_cid, uint8_t *data, uint16_t len);
|
||||
void bt_send_rfcomm(uint16_t rfcom_cid, uint8_t *data, uint16_t len);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
|
@ -53,13 +53,23 @@ extern "C" {
|
||||
|
||||
// extension for client/server communication
|
||||
#define DAEMON_EVENT_PACKET 0x05
|
||||
|
||||
|
||||
// L2CAP data
|
||||
#define L2CAP_DATA_PACKET 0x06
|
||||
|
||||
// RFCOMM data
|
||||
#define RFCOMM_DATA_PACKET 0x07
|
||||
#define RFCOMM_DATA_PACKET 0x07
|
||||
|
||||
// Attribute protocol data
|
||||
#define ATT_DATA_PACKET 0x08
|
||||
|
||||
// Security Manager protocol data
|
||||
#define SM_DATA_PACKET 0x09
|
||||
|
||||
// debug log messages
|
||||
#define LOG_MESSAGE_PACKET 0xfc
|
||||
|
||||
|
||||
// Fixed PSM numbers
|
||||
#define PSM_SDP 0x01
|
||||
#define PSM_RFCOMM 0x03
|
||||
@ -74,7 +84,7 @@ extern "C" {
|
||||
#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_ENCRYPTION_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
|
||||
@ -97,12 +107,21 @@ extern "C" {
|
||||
#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_LE_META 0x3E
|
||||
#define HCI_EVENT_VENDOR_SPECIFIC 0xFF
|
||||
|
||||
#define HCI_SUBEVENT_LE_CONNECTION_COMPLETE 0x01
|
||||
#define HCI_SUBEVENT_LE_ADVERTISING_REPORT 0x02
|
||||
#define HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE 0x03
|
||||
#define HCI_SUBEVENT_LE_READ_REMOTE_USED_FEATURES_COMPLETE 0x04
|
||||
#define HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST 0x05
|
||||
|
||||
// last used HCI_EVENT in 2.1 is 0x3d
|
||||
|
||||
// events 0x50-0x5f are used internally
|
||||
|
||||
// BTSTACK DAEMON EVENTS
|
||||
|
||||
// events from BTstack for application/client lib
|
||||
#define BTSTACK_EVENT_STATE 0x60
|
||||
|
||||
@ -118,25 +137,61 @@ extern "C" {
|
||||
// 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)
|
||||
// data: event (8), len(8), status (8) == 0, address (48), name (1984 bits = 248 bytes)
|
||||
#define BTSTACK_EVENT_REMOTE_NAME_CACHED 0x65
|
||||
|
||||
// data: discoverable enabled (bool)
|
||||
#define BTSTACK_EVENT_DISCOVERABLE_ENABLED 0x66
|
||||
|
||||
// L2CAP EVENTS
|
||||
|
||||
// data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16), local_mtu(16), remote_mtu(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)
|
||||
// data: event (8), len(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)
|
||||
// data: event(8), len(8), local_cid(16), credits(8)
|
||||
#define L2CAP_EVENT_CREDITS 0x74
|
||||
|
||||
// data: event(8), len(8), service_record_handle(32)
|
||||
#define SDP_SERVICE_REGISTERED 0x80
|
||||
// data: event(8), len(8), status (8), psm (16)
|
||||
#define L2CAP_EVENT_SERVICE_REGISTERED 0x75
|
||||
|
||||
|
||||
// RFCOMM EVENTS
|
||||
|
||||
// data: event(8), len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16)
|
||||
#define RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE 0x80
|
||||
|
||||
// data: event(8), len(8), rfcomm_cid(16)
|
||||
#define RFCOMM_EVENT_CHANNEL_CLOSED 0x81
|
||||
|
||||
// data: event (8), len(8), address(48), channel (8), rfcomm_cid (16)
|
||||
#define RFCOMM_EVENT_INCOMING_CONNECTION 0x82
|
||||
|
||||
// data: event (8), len(8), rfcommid (16), ...
|
||||
#define RFCOMM_EVENT_REMOTE_LINE_STATUS 0x83
|
||||
|
||||
// data: event(8), len(8), rfcomm_cid(16), credits(8)
|
||||
#define RFCOMM_EVENT_CREDITS 0x84
|
||||
|
||||
// data: event(8), len(8), status (8), rfcomm server channel id (8)
|
||||
#define RFCOMM_EVENT_SERVICE_REGISTERED 0x85
|
||||
|
||||
// data: event(8), len(8), status (8), rfcomm server channel id (8)
|
||||
#define RFCOMM_EVENT_PERSISTENT_CHANNEL 0x86
|
||||
|
||||
|
||||
// data: event(8), len(8), status(8), service_record_handle(32)
|
||||
#define SDP_SERVICE_REGISTERED 0x90
|
||||
|
||||
|
||||
// last error code in 2.1 is 0x38 - we start with 0x50 for BTstack errors
|
||||
|
||||
#define BTSTACK_CONNECTION_TO_BTDAEMON_FAILED 0x50
|
||||
@ -145,6 +200,8 @@ extern "C" {
|
||||
#define BTSTACK_ACTIVATION_FAILED_UNKNOWN 0x53
|
||||
#define BTSTACK_NOT_ACTIVATED 0x54
|
||||
#define BTSTACK_BUSY 0x55
|
||||
#define BTSTACK_MEMORY_ALLOC_FAILED 0x56
|
||||
#define BTSTACK_ACL_BUFFERS_FULL 0x57
|
||||
|
||||
// l2cap errors - enumeration by the command that created them
|
||||
#define L2CAP_COMMAND_REJECT_REASON_COMMAND_NOT_UNDERSTOOD 0x60
|
||||
@ -161,7 +218,14 @@ extern "C" {
|
||||
#define L2CAP_CONFIG_RESPONSE_RESULT_UNACCEPTABLE_PARAMS 0x67
|
||||
#define L2CAP_CONFIG_RESPONSE_RESULT_REJECTED 0x68
|
||||
#define L2CAP_CONFIG_RESPONSE_RESULT_UNKNOWN_OPTIONS 0x69
|
||||
#define L2CAP_SERVICE_ALREADY_REGISTERED 0x6a
|
||||
|
||||
#define RFCOMM_MULTIPLEXER_STOPPED 0x70
|
||||
#define RFCOMM_CHANNEL_ALREADY_REGISTERED 0x71
|
||||
#define RFCOMM_NO_OUTGOING_CREDITS 0x72
|
||||
|
||||
#define SDP_HANDLE_ALREADY_REGISTERED 0x80
|
||||
|
||||
/**
|
||||
* Default INQ Mode
|
||||
*/
|
||||
@ -171,7 +235,8 @@ extern "C" {
|
||||
*/
|
||||
typedef enum {
|
||||
HCI_POWER_OFF = 0,
|
||||
HCI_POWER_ON
|
||||
HCI_POWER_ON,
|
||||
HCI_POWER_SLEEP
|
||||
} HCI_POWER_MODE;
|
||||
|
||||
/**
|
||||
@ -181,7 +246,9 @@ typedef enum {
|
||||
HCI_STATE_OFF = 0,
|
||||
HCI_STATE_INITIALIZING,
|
||||
HCI_STATE_WORKING,
|
||||
HCI_STATE_HALTING
|
||||
HCI_STATE_HALTING,
|
||||
HCI_STATE_SLEEPING,
|
||||
HCI_STATE_FALLING_ASLEEP
|
||||
} HCI_STATE;
|
||||
|
||||
/**
|
||||
@ -200,9 +267,12 @@ 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 btstack_set_discoverable;
|
||||
extern const hci_cmd_t btstack_set_bluetooth_enabled; // only used by btstack config
|
||||
|
||||
extern const hci_cmd_t hci_accept_connection_request;
|
||||
extern const hci_cmd_t hci_authentication_requested;
|
||||
extern const hci_cmd_t hci_change_connection_link_key;
|
||||
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;
|
||||
@ -217,25 +287,64 @@ 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_le_host_supported;
|
||||
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_read_local_supported_features;
|
||||
extern const hci_cmd_t hci_read_num_broadcast_retransmissions;
|
||||
extern const hci_cmd_t hci_reject_connection_request;
|
||||
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_set_connection_encryption;
|
||||
extern const hci_cmd_t hci_sniff_mode;
|
||||
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_le_host_supported;
|
||||
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_num_broadcast_retransmissions;
|
||||
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 hci_le_add_device_to_whitelist;
|
||||
extern const hci_cmd_t hci_le_clear_white_list;
|
||||
extern const hci_cmd_t hci_le_connection_update;
|
||||
extern const hci_cmd_t hci_le_create_connection;
|
||||
extern const hci_cmd_t hci_le_create_connection_cancel;
|
||||
extern const hci_cmd_t hci_le_encrypt;
|
||||
extern const hci_cmd_t hci_le_long_term_key_negative_reply;
|
||||
extern const hci_cmd_t hci_le_long_term_key_request_reply;
|
||||
extern const hci_cmd_t hci_le_rand;
|
||||
extern const hci_cmd_t hci_le_read_advertising_channel_tx_power;
|
||||
extern const hci_cmd_t hci_le_read_buffer_size ;
|
||||
extern const hci_cmd_t hci_le_read_channel_map;
|
||||
extern const hci_cmd_t hci_le_read_remote_used_features;
|
||||
extern const hci_cmd_t hci_le_read_supported_features;
|
||||
extern const hci_cmd_t hci_le_read_supported_states;
|
||||
extern const hci_cmd_t hci_le_read_white_list_size;
|
||||
extern const hci_cmd_t hci_le_receiver_test;
|
||||
extern const hci_cmd_t hci_le_remove_device_from_whitelist;
|
||||
extern const hci_cmd_t hci_le_set_advertise_enable;
|
||||
extern const hci_cmd_t hci_le_set_advertising_data;
|
||||
extern const hci_cmd_t hci_le_set_advertising_parameters;
|
||||
extern const hci_cmd_t hci_le_set_event_mask;
|
||||
extern const hci_cmd_t hci_le_set_host_channel_classification;
|
||||
extern const hci_cmd_t hci_le_set_random_address;
|
||||
extern const hci_cmd_t hci_le_set_scan_enable;
|
||||
extern const hci_cmd_t hci_le_set_scan_parameters;
|
||||
extern const hci_cmd_t hci_le_set_scan_response_data;
|
||||
extern const hci_cmd_t hci_le_start_encryption;
|
||||
extern const hci_cmd_t hci_le_test_end;
|
||||
extern const hci_cmd_t hci_le_transmitter_test;
|
||||
|
||||
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;
|
||||
@ -247,7 +356,25 @@ 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;
|
||||
|
||||
|
||||
// accept connection @param bd_addr(48), rfcomm_cid (16)
|
||||
extern const hci_cmd_t rfcomm_accept_connection;
|
||||
// create rfcomm channel: @param bd_addr(48), channel (8)
|
||||
extern const hci_cmd_t rfcomm_create_channel;
|
||||
// create rfcomm channel: @param bd_addr(48), channel (8), mtu (16), credits (8)
|
||||
extern const hci_cmd_t rfcomm_create_channel_with_initial_credits;
|
||||
// decline rfcomm disconnect,@param bd_addr(48), rfcomm cid (16), reason(8)
|
||||
extern const hci_cmd_t rfcomm_decline_connection;
|
||||
// disconnect rfcomm disconnect, @param rfcomm_cid(8), reason(8)
|
||||
extern const hci_cmd_t rfcomm_disconnect;
|
||||
// register rfcomm service: @param channel(8), mtu (16)
|
||||
extern const hci_cmd_t rfcomm_register_service;
|
||||
// register rfcomm service: @param channel(8), mtu (16), initial credits (8)
|
||||
extern const hci_cmd_t rfcomm_register_service_with_initial_credits;
|
||||
// unregister rfcomm service, @param service_channel(16)
|
||||
extern const hci_cmd_t rfcomm_unregister_service;
|
||||
// request persisten rfcomm channel for service name: serive name (char*)
|
||||
extern const hci_cmd_t rfcomm_persistent_channel_for_service;
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -54,8 +54,9 @@ 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
|
||||
linked_item_t * linked_list_get_last_item(linked_list_t * list); // <-- find the last item in the list
|
||||
|
||||
void test_linked_list();
|
||||
void test_linked_list(void);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
|
@ -37,9 +37,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
//#include "config.h"
|
||||
#define HAVE_TIME
|
||||
|
||||
#include "linked_list.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_TIME
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
@ -59,27 +66,56 @@ typedef struct data_source {
|
||||
|
||||
typedef struct timer {
|
||||
linked_item_t item;
|
||||
#ifdef HAVE_TIME
|
||||
struct timeval timeout; // <-- next timeout
|
||||
#endif
|
||||
#ifdef HAVE_TICK
|
||||
uint32_t timeout; // timeout in system ticks
|
||||
#endif
|
||||
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 in milliseconds.
|
||||
void run_loop_set_timer(timer_source_t *a, uint32_t timeout_in_ms);
|
||||
|
||||
// set timer based on current time
|
||||
void run_loop_set_timer(timer_source_t *a, int timeout_in_ms);
|
||||
// Set callback that will be executed when timer expires.
|
||||
void run_loop_set_timer_handler(timer_source_t *ts, void (*process)(timer_source_t *_ts));
|
||||
|
||||
// add/remove timer_source
|
||||
// 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();
|
||||
// Init must be called before any other run_loop call.
|
||||
// Use RUN_LOOP_EMBEDDED for embedded devices.
|
||||
void run_loop_init(RUN_LOOP_TYPE type);
|
||||
|
||||
// Set data source callback.
|
||||
void run_loop_set_data_source_handler(data_source_t *ds, int (*process)(data_source_t *_ds));
|
||||
|
||||
|
||||
// Add/Remove data source.
|
||||
void run_loop_add_data_source(data_source_t *dataSource);
|
||||
int run_loop_remove_data_source(data_source_t *dataSource);
|
||||
|
||||
|
||||
// Execute configured run loop. This function does not return.
|
||||
void run_loop_execute(void);
|
||||
|
||||
// hack to fix HCI timer handling
|
||||
#ifdef HAVE_TICK
|
||||
// Sets how many miliseconds has one tick.
|
||||
uint32_t embedded_ticks_for_ms(uint32_t time_in_ms);
|
||||
// Queries the current time in ticks.
|
||||
uint32_t embedded_get_ticks(void);
|
||||
#endif
|
||||
#ifdef EMBEDDED
|
||||
// Sets an internal flag that is checked in the critical section
|
||||
// just before entering sleep mode. Has to be called by the interupt
|
||||
// handler of a data source to signal the run loop that a new data
|
||||
// is available.
|
||||
void embedded_trigger(void);
|
||||
#endif
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -79,30 +79,59 @@ typedef enum {
|
||||
#define SDP_ClientExecutableURL 0x000b
|
||||
#define SDP_IconURL 0x000c
|
||||
#define SDP_AdditionalProtocolDescriptorList 0x000d
|
||||
#define SDP_SupportedFormatsList 0x0303
|
||||
|
||||
// SERVICE CLASSES
|
||||
#define SDP_OBEXObjectPush 0x1105
|
||||
#define SDP_OBEXFileTransfer 0x1106
|
||||
#define SDP_PublicBrowseGroup 0x1002
|
||||
|
||||
// PROTOCOLS
|
||||
#define SDP_SDPProtocol 0x0001
|
||||
#define SDP_UDPProtocol 0x0002
|
||||
#define SDP_RFCOMMProtocol 0x0003
|
||||
#define SDP_OBEXProtocol 0x0008
|
||||
#define SDP_L2CAPProtocol 0x0100
|
||||
|
||||
// OFFSETS FOR LOCALIZED ATTRIBUTES - SDP_LanguageBaseAttributeIDList
|
||||
#define SDP_Offest_ServiceName 0x0000
|
||||
#define SDP_Offest_ServiceDescription 0x0001
|
||||
#define SDP_Offest_ProviderName 0x0002
|
||||
|
||||
// OBEX
|
||||
#define SDP_vCard_2_1 0x01
|
||||
#define SDP_vCard_3_0 0x02
|
||||
#define SDP_vCal_1_0 0x03
|
||||
#define SDP_iCal_2_0 0x04
|
||||
#define SDP_vNote 0x05
|
||||
#define SDP_vMessage 0x06
|
||||
#define SDP_OBEXFileTypeAny 0xFF
|
||||
|
||||
#pragma mark DateElement
|
||||
// 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);
|
||||
int de_get_header_size(uint8_t * header);
|
||||
void de_create_sequence(uint8_t *header);
|
||||
void de_store_descriptor_with_len(uint8_t * header, de_type_t type, de_size_t size, uint32_t len);
|
||||
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);
|
||||
void de_add_uuid128(uint8_t * seq, uint8_t * uuid);
|
||||
|
||||
#pragma mark SDP
|
||||
int sdp_append_attributes_in_attributeIDList(uint8_t *record, uint8_t *attributeIDList, uint16_t startIndex, uint16_t maxBytes, uint8_t *buffer);
|
||||
// MARK: SDP
|
||||
uint16_t sdp_append_attributes_in_attributeIDList(uint8_t *record, uint8_t *attributeIDList, uint16_t startOffset, 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);
|
||||
uint8_t sdp_set_attribute_value_for_attribute_id(uint8_t * record, uint16_t attributeID, uint32_t value);
|
||||
int sdp_record_matches_service_search_pattern(uint8_t *record, uint8_t *serviceSearchPattern);
|
||||
int spd_get_filtered_size(uint8_t *record, uint8_t *attributeIDList);
|
||||
int sdp_filter_attributes_in_attributeIDList(uint8_t *record, uint8_t *attributeIDList, uint16_t startOffset, uint16_t maxBytes, uint16_t *usedBytes, uint8_t *buffer);
|
||||
|
||||
void sdp_create_spp_service(uint8_t *service, int service_id, const char *name);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
|
@ -39,12 +39,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief hci connection handle type
|
||||
*/
|
||||
@ -62,6 +63,13 @@ typedef uint8_t bd_addr_t[BD_ADDR_LEN];
|
||||
#define LINK_KEY_LEN 16
|
||||
typedef uint8_t link_key_t[LINK_KEY_LEN];
|
||||
|
||||
/**
|
||||
* @brief The device name type
|
||||
*/
|
||||
#define DEVICE_NAME_LEN 248
|
||||
typedef uint8_t device_name_t[DEVICE_NAME_LEN+1];
|
||||
|
||||
|
||||
// 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))
|
||||
@ -77,6 +85,10 @@ typedef uint8_t link_key_t[LINK_KEY_LEN];
|
||||
|
||||
// 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)
|
||||
#define COMMAND_STATUS_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_STATUS && READ_BT_16(event,4) == cmd.opcode)
|
||||
|
||||
// Code+Len=2, Pkts+Opcode=3; total=5
|
||||
#define OFFSET_OF_DATA_IN_COMMAND_COMPLETE 5
|
||||
|
||||
// ACL Packet
|
||||
#define READ_ACL_CONNECTION_HANDLE( buffer ) ( READ_BT_16(buffer,0) & 0x0fff)
|
||||
@ -96,19 +108,19 @@ 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);
|
||||
|
||||
// @deprecated please use more convenient bd_addr_to_str
|
||||
void print_bd_addr( bd_addr_t addr);
|
||||
char * bd_addr_to_str(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
|
||||
|
@ -47,7 +47,7 @@
|
||||
#include "btstack/btstack.h"
|
||||
#include "wiimote.h"
|
||||
|
||||
//int num_of_joys = 0;
|
||||
int myosd_num_of_joys = 0;
|
||||
struct wiimote_t joys[4];
|
||||
extern int g_pref_wii_DZ_value;
|
||||
#define STICK4WAY (myosd_waysStick == 4 && myosd_inGame)
|
||||
@ -506,7 +506,6 @@ void calc_joystick_state(struct joystick_t* js, float x, float y);
|
||||
* @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;
|
||||
@ -581,7 +580,7 @@ int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, byte
|
||||
* @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;
|
||||
int lx, ly, rx, ry;
|
||||
byte l, r;
|
||||
|
||||
/* decrypt data */
|
||||
@ -691,200 +690,3 @@ void calc_joystick_state(struct joystick_t* js, float x, float y) {
|
||||
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
|
||||
|
@ -276,8 +276,6 @@ extern "C" {
|
||||
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);
|
||||
|
@ -353,7 +353,7 @@
|
||||
- (IBAction)showWiiRemoteConfig
|
||||
{
|
||||
#ifdef WIIMOTE
|
||||
[WiiMoteHelper startwiimote:_navigator];
|
||||
[[WiiMoteHelper get] showDiscovery];
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -165,10 +165,10 @@ static int16_t ios_input_state(void *data, const struct retro_keybind **binds, u
|
||||
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);
|
||||
case RETRO_DEVICE_ID_JOYPAD_UP: return IS_PRESSED(wm, WIIMOTE_BUTTON_RIGHT);
|
||||
case RETRO_DEVICE_ID_JOYPAD_DOWN: return IS_PRESSED(wm, WIIMOTE_BUTTON_LEFT);
|
||||
case RETRO_DEVICE_ID_JOYPAD_LEFT: return IS_PRESSED(wm, WIIMOTE_BUTTON_UP);
|
||||
case RETRO_DEVICE_ID_JOYPAD_RIGHT: return IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user