From 77c915711e0f69c406d6c95b1b7b4f15b50932bd Mon Sep 17 00:00:00 2001 From: "matthias.ringwald" Date: Thu, 5 Aug 2010 20:04:03 +0000 Subject: [PATCH] add function to allow custom BT module initialization --- src/bt_control.h | 8 ++ src/bt_control_iphone.m | 206 +++++++++++++++++++++++++++------------- 2 files changed, 149 insertions(+), 65 deletions(-) diff --git a/src/bt_control.h b/src/bt_control.h index ca2a8b1ec..c1c48136c 100644 --- a/src/bt_control.h +++ b/src/bt_control.h @@ -40,9 +40,17 @@ #pragma once +#include + 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; diff --git a/src/bt_control_iphone.m b/src/bt_control_iphone.m index 781b658ee..27bb39e32 100644 --- a/src/bt_control_iphone.m +++ b/src/bt_control_iphone.m @@ -60,11 +60,13 @@ // minimal IOKit #ifdef __APPLE__ #include +#include +#include #if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_2_0 #include #define IOKIT #include -#include +#include 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 };