add function to allow custom BT module initialization

This commit is contained in:
matthias.ringwald 2010-08-05 20:04:03 +00:00
parent 866d626ba4
commit 77c915711e
2 changed files with 149 additions and 65 deletions

View File

@ -40,9 +40,17 @@
#pragma once
#include <stdint.h>
typedef struct {
int (*on)(void *config); // <-- turn BT module on and configure
int (*off)(void *config); // <-- turn BT module off
int (*valid)(void *config); // <-- test if hardware can be supported
const char * (*name)(void *config); // <-- return hardware name
/** support custom init sequences after RESET command
* @return pointer do next command packet used during init
*/
uint8_t (*next_command)(void *config);
} bt_control_t;

View File

@ -60,11 +60,13 @@
// minimal IOKit
#ifdef __APPLE__
#include <Availability.h>
#include <Foundation/Foundation.h>
#include <CoreFoundation/CoreFoundation.h>
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_2_0
#include <mach/mach.h>
#define IOKIT
#include <device/device_types.h>
#include <CoreFoundation/CoreFoundation.h>
#include <UIKit/UIKit.h>
kern_return_t IOMasterPort( mach_port_t bootstrapPort, mach_port_t * masterPort );
CFMutableDictionaryRef IOServiceNameMatching(const char * name );
CFTypeRef IORegistryEntrySearchCFProperty(mach_port_t entry, const io_name_t plane,
@ -75,7 +77,8 @@ kern_return_t IOObjectRelease(mach_port_t object);
#endif
int iphone_system_bt_enabled(){
return SBA_getBluetoothEnabled();
// return SBA_getBluetoothEnabled();
return false;
}
void iphone_system_bt_set_enabled(int enabled)
@ -108,7 +111,6 @@ static char *get_machine_name(void){
*/
static int iphone_valid(void *config){
char * machine = get_machine_name();
if (!strncmp("iPhone", machine, strlen("iPhone" ))) return 1; // iPhone OK
if (!strncmp("iPod1", machine, strlen("iPod1"))) return 0; // 1st gen touch no BT
return 1;
}
@ -136,31 +138,60 @@ static void ioregistry_get_bd_addr() {
#endif
}
static void iphone_set_pskey(int fd, int key, int value){
sprintf(buffer, "csr -p 0x%04x=0x%04x\n", key, value);
write(fd, buffer, 21);
static int iphone_has_csr(){
// construct script path from device name
char *machine = get_machine_name();
if (strncmp(machine, "iPhone1,", strlen("iPhone1,")) == 0) {
return 1;
}
return 0;
}
static int iphone_write_initscript (hci_uart_config_t *uart_config, int output){
static void iphone_write_string(int fd, char *string){
int len = strlen(string);
write(fd, string, len);
}
static void iphone_csr_set_pskey(int fd, int key, int value){
int len = sprintf(buffer, "csr -p 0x%04x=0x%04x\n", key, value);
write(fd, buffer, len);
}
static void iphone_csr_set_bd_addr(int fd){
int len = sprintf(buffer,"\ncsr -p 0x0001=0x00%.2x,0x%.2x%.2x,0x00%.2x,0x%.2x%.2x\n",
ioRegAddr[3], ioRegAddr[4], ioRegAddr[5], ioRegAddr[2], ioRegAddr[0], ioRegAddr[1]);
write(fd, buffer, len);
}
static void iphone_csr_set_baud(int fd, int baud){
// calculate baud rate (assume rate is multiply of 100)
uint32_t baud_key = (4096 * (uart_config->baudrate/100) + 4999) / 10000;
uint32_t baud_key = (4096 * (baud/100) + 4999) / 10000;
iphone_csr_set_pskey(fd, 0x01be, baud_key);
}
static void iphone_bcm_set_bd_addr(int fd){
int len = sprintf(buffer, "bcm -a %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", ioRegAddr[0], ioRegAddr[1],
ioRegAddr[2], ioRegAddr[3], ioRegAddr[4], ioRegAddr[5]);
write(fd, buffer, len);
}
static void iphone_bcm_set_baud(int fd, int baud){
int len = sprintf(buffer, "bcm -b %u\n", baud);
write(fd, buffer, len);
}
static int iphone_write_initscript (int output, int baudrate){
// construct script path from device name
strcpy(buffer, "/etc/bluetool/");
char *machine = get_machine_name();
strcat(buffer, machine);
if (strncmp(machine, "iPhone1,", strlen("iPhone1,")) == 0) {
// It's an iPhone 2G or 3G
if (iphone_has_csr()){
strcat(buffer, ".init.script");
} else {
// It's an iPod Touch (2G) or an iPhone 3GS
} else {
strcat(buffer, ".boot.script");
}
// get bd_addr from IORegistry
ioregistry_get_bd_addr();
}
// open script
int input = open(buffer, O_RDONLY);
@ -203,9 +234,7 @@ static int iphone_write_initscript (hci_uart_config_t *uart_config, int output){
if (store == 1 && pos == 6 && strncmp(buffer, "csr -i", 6) == 0) {
store = 0;
write(output, buffer, pos); // "csr -i"
sprintf(buffer,"\ncsr -p 0x0001=0x00%.2x,0x%.2x%.2x,0x00%.2x,0x%.2x%.2x\n",
ioRegAddr[3], ioRegAddr[4], ioRegAddr[5], ioRegAddr[2], ioRegAddr[0], ioRegAddr[1]);
write(output, buffer, 42);
iphone_csr_set_bd_addr(output);
}
// iPod2,1
@ -215,22 +244,16 @@ static int iphone_write_initscript (hci_uart_config_t *uart_config, int output){
store = 0;
switch (buffer[5]){
case 'a': // BT Address
write(output, buffer, pos); // "bcm -a"
sprintf(buffer, " %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", ioRegAddr[0], ioRegAddr[1],
ioRegAddr[2], ioRegAddr[3], ioRegAddr[4], ioRegAddr[5]);
write(output, buffer, 18);
iphone_bcm_set_bd_addr(output);
mirror = 0;
break;
case 'b': // baud rate command OS 2.x
case 'B': // baud rate command OS 3.x
buffer[5] = 'b';
write(output, buffer, pos); // "bcm -b"
sprintf(buffer, " %u\n", uart_config->baudrate);
write(output, buffer, strlen(buffer));
iphone_bcm_set_baud(output, baudrate);
mirror = 0;
break;
case 's': // sleep mode - replace with "wake" command?
write(output,"wake on\n", strlen("wake on\n"));
iphone_write_string(output, "wake on\n");
mirror = 0;
break;
default: // other "bcm -X" command
@ -249,7 +272,7 @@ static int iphone_write_initscript (hci_uart_config_t *uart_config, int output){
store = 0;
break;
case 'B': // Baud rate
iphone_set_pskey(output, 0x01be, baud_key);
iphone_csr_set_baud(output, baudrate);
store = 0;
break;
default: // wait for full command
@ -270,7 +293,7 @@ static int iphone_write_initscript (hci_uart_config_t *uart_config, int output){
mirror = 0;
break;
case 0x01be: // PSKET_UART_BAUD_RATE
iphone_set_pskey(output, 0x01be, baud_key);
iphone_csr_set_baud(output, baudrate);
mirror = 0;
break;
default:
@ -290,15 +313,95 @@ static int iphone_write_initscript (hci_uart_config_t *uart_config, int output){
return 0;
}
static void iphone_write_configscript(int fd, int baudrate){
iphone_write_string(fd, "device -D -S\n");
if (iphone_has_csr()) {
iphone_csr_set_baud(fd, baudrate);
iphone_csr_set_bd_addr(fd);
iphone_write_string(fd, "csr -r\n");
} else {
iphone_bcm_set_baud(fd, baudrate);
iphone_write_string(fd, "msleep 200\n");
iphone_bcm_set_bd_addr(fd);
iphone_write_string(fd, "msleep 50\n");
}
iphone_write_string(fd, "quit\n");
}
static char *os3xBlueTool = "BlueTool";
static char *os4xBlueTool = "/usr/local/bin/BlueToolH4";
static int iphone_on (void *transport_config){
int err = 0;
hci_uart_config_t * hci_uart_config = (hci_uart_config_t*) transport_config;
// get bd_addr from IORegistry
ioregistry_get_bd_addr();
#ifdef USE_BLUETOOL
if (iphone_system_bt_enabled()){
perror("iphone_on: System Bluetooth enabled!");
return 1;
}
#if 0
// use tmp file for testing on os 3.x
int output = open("/tmp/bt.init", O_WRONLY | O_CREAT | O_TRUNC);
iphone_write_initscript(hci_uart_config, output);
close(output);
err = system ("BlueTool < /tmp/bt.init");
#else
// check for os version >= 4.0
int os4x = 1;
NSAutoreleasePool * pool =[[NSAutoreleasePool alloc] init];
NSString * systemVersion = [[UIDevice currentDevice] systemVersion];
if ([systemVersion hasPrefix:@"2."]) os4x = 0;
if ([systemVersion hasPrefix:@"3."]) os4x = 0;
// NSLog(@"OS Version: %@, ox4x = %u", systemVersion, os4x);
[pool release];
// OS 4.0
char * bluetool = os3xBlueTool;
if (os4x) {
bluetool = os4xBlueTool;
// basic config
sprintf(buffer, "%s -F boot", bluetool);
system(buffer);
sprintf(buffer, "%s -F init", bluetool);
system(buffer);
}
// advanced config
FILE * outputFile = popen(bluetool, "r+");
setvbuf(outputFile, NULL, _IONBF, 0);
int output = fileno(outputFile);
if (os4x) {
// 4.x - send custom config
iphone_write_configscript(output, hci_uart_config->baudrate);
} else {
// 3.x - modify original script on the fly
iphone_write_initscript(output, hci_uart_config->baudrate);
}
// log output
fflush(outputFile);
int singlechar;
while (1) {
singlechar = fgetc(outputFile);
if (singlechar == EOF) break;
printf("%c", singlechar);
};
err = pclose(outputFile);
#endif
// if we sleep for about 3 seconds, we miss a strage packet... but we don't care
// sleep(3);
#else
// quick test if Bluetooth UART can be opened
int fd = open(hci_uart_config->device_name, O_RDWR | O_NOCTTY | O_NDELAY);
@ -310,33 +413,6 @@ static int iphone_on (void *transport_config){
close(fd);
#endif
int err = 0;
#if 0
// use tmp file for testing
int output = open("/tmp/bt.init", O_WRONLY | O_CREAT | O_TRUNC);
iphone_write_initscript(hci_uart_config, output);
close(output);
err = system ("BlueTool < /tmp/bt.init");
#else
// modify original script on the fly
FILE * outputFile = popen("BlueTool", "r+");
setvbuf(outputFile, NULL, _IONBF, 0);
int output = fileno(outputFile);
iphone_write_initscript(hci_uart_config, output);
// log output
fflush(outputFile);
int singlechar;
while (1) {
singlechar = fgetc(outputFile);
if (singlechar == EOF) break;
printf("%c", singlechar);
};
err = pclose(outputFile);
#endif
// if we sleep for about 3 seconds, we miss a strage packet... but we don't care
// sleep(3);
return err;
}
@ -347,14 +423,13 @@ static int iphone_off (void *config){
if (strncmp(machine, "iPad", strlen("iPad")) == 0) {
// put iPad Bluetooth into deep sleep
system ("echo \"wake off\n quit\" | BlueTool");
// kill Apple BTServer as it gets confused and fails to start anyway
system("killall BTServer");
} else {
// power off for iPhone and iPod
system ("echo \"power off\n quit\" | BlueTool");
}
// kill Apple BTServer as it gets confused and fails to start anyway
system("killall BTServer");
return 0;
}
@ -364,5 +439,6 @@ bt_control_t bt_control_iphone = {
iphone_on,
iphone_off,
iphone_valid,
iphone_name
iphone_name,
NULL
};