From 0ff3056bc7a362257b41110cc378a5b2a7a1b0cb Mon Sep 17 00:00:00 2001 From: "matthias.ringwald" Date: Thu, 4 Aug 2011 21:25:43 +0000 Subject: [PATCH] add advanced power management for iOS by Jens David (and bump version) --- configure.in | 8 ++++- package.sh | 2 +- src/bt_control_iphone.m | 58 +++++++++++++++++++++++++++++----- src/get_version.sh | 2 +- src/hci_transport_h4.c | 70 ++++++++++++++++++++++++++++++++++++++--- 5 files changed, 125 insertions(+), 15 deletions(-) diff --git a/configure.in b/configure.in index 03d2d750b..f7b538848 100644 --- a/configure.in +++ b/configure.in @@ -9,6 +9,7 @@ AM_INIT_AUTOMAKE(BTstack,0.1) AC_ARG_WITH(hci-transport, [AS_HELP_STRING([--with-hci-transport=transportType], [Specify BT type to use: h4, usb (not supported yet])], HCI_TRANSPORT=$withval, HCI_TRANSPORT="h4") AC_ARG_WITH(uart-device, [AS_HELP_STRING([--with-uart-device=uartDevice], [Specify BT UART device to use])], UART_DEVICE=$withval, UART_DEVICE="DEFAULT") AC_ARG_WITH(uart-speed, [AS_HELP_STRING([--with-uart-speed=uartSpeed], [Specify BT UART speed to use])], UART_SPEED=$withval, UART_SPEED="115200") +AC_ARG_ENABLE(powermanagement, [AS_HELP_STRING([--disable-powermanagement],[Disable powermanagement])], USE_POWERMANAGEMENT=$enableval, USE_POWERMANAGEMENT="yes") AC_ARG_ENABLE(bluetool, [AS_HELP_STRING([--disable-bluetool],[Disable init of Bluetooth module by BlueTool])], USE_BLUETOOL=$enableval, USE_BLUETOOL="DEFAULT") AC_ARG_ENABLE(springboard, [AS_HELP_STRING([--disable-springboard],[Disable display of BTstack status in SpringBoard])], USE_SPRINGBOARD=$enableval, USE_SPRINGBOARD="DEFAULT") AC_ARG_ENABLE(launchd, [AS_HELP_STRING([--enable-launchd],[Compiles BTdaemon for use by launchd])], USE_LAUNCHD=$enableval, USE_LAUNCHD="no") @@ -155,7 +156,7 @@ if test "x$target" = xiphone; then USE_BLUETOOL="yes" echo "USE_BLUETOOL: $USE_BLUETOOL" fi - + if test "x$USE_SPRINGBOARD" = xDEFAULT ; then USE_SPRINGBOARD="yes" fi @@ -192,6 +193,7 @@ CPPFLAGS="$CPPFLAGS -Werror -Wall -Wpointer-arith" AM_CONDITIONAL(USE_SPRINGBOARD, [test "x$USE_SPRINGBOARD" == "xyes"]) AM_CONDITIONAL(USE_BLUETOOL, [test "x$USE_BLUETOOL" == "xyes"]) +AM_CONDITIONAL(USE_POWERMANAGEMENT, [test "x$USE_POWERMANAGEMENT" == "xyes"]) AM_CONDITIONAL(USE_PREFSBUNDLE, [test "x$USE_PREFSBUNDLE" == "xyes"]) # summary @@ -215,6 +217,7 @@ echo "PLATFORM_SOURCES: $PLATFORM_SOURCES" echo "USE_LAUNCHD: $USE_LAUNCHD" echo "USE_SPRINGBOARD: $USE_SPRINGBOARD" echo "USE_PREFSBUNDLE: $USE_PREFSBUNDLE" +echo "USE_POWERMANAGEMENT: $USE_POWERMANAGEMENT" echo "USE_COCOA_RUN_LOOP: $USE_COCOA_RUN_LOOP" echo "REMOTE_DEVICE_DB: $REMOTE_DEVICE_DB" echo "HAVE_SO_NOSIGPIPE: $HAVE_SO_NOSIGPIPE" @@ -235,6 +238,9 @@ else if test "x$USE_BLUETOOL" = xyes; then echo "#define USE_BLUETOOL" >> config.h fi + if test "x$USE_POWERMANAGEMENT" = xyes; then + echo "#define USE_POWERMANAGEMENT" >> config.h + fi fi if test "x$USE_SPRINGBOARD" = xyes; then SPRINGBOARD_ACCESS_SOURCES="../SpringBoardAccess/SpringBoardAccess.c" diff --git a/package.sh b/package.sh index e845433c3..540142254 100755 --- a/package.sh +++ b/package.sh @@ -4,7 +4,7 @@ PACKAGE=BTstack svn update -VERSION=0.3 +VERSION=0.4 REVISION=`svn info | grep Revision | cut -d " " -f 2` ARCHIVE=$PACKAGE-$VERSION-$REVISION.deb diff --git a/src/bt_control_iphone.m b/src/bt_control_iphone.m index 32a27d16a..7c81704f7 100644 --- a/src/bt_control_iphone.m +++ b/src/bt_control_iphone.m @@ -35,6 +35,7 @@ * control Bluetooth module using BlueTool * * Created by Matthias Ringwald on 5/19/09. + * PowerManagement implementation by Jens David, DG1KJD on 20110801. * * Bluetooth Toggle by BigBoss */ @@ -126,7 +127,6 @@ static data_source_t power_notification_ds; #endif #endif - int iphone_system_bt_enabled(){ return SBA_getBluetoothEnabled(); } @@ -148,6 +148,10 @@ static char buffer[BUFF_LEN+1]; static bd_addr_t local_mac_address; static uint32_t transport_speed; +static int power_management_active = 0; +static char *os3xBlueTool = "BlueTool"; +static char *os4xBlueTool = "/usr/local/bin/BlueToolH4"; + /** * get machine name */ @@ -373,6 +377,23 @@ static int iphone_write_initscript (int output, int baudrate){ } // close input close(input); + +#ifdef USE_POWERMANAGEMENT + if (iphone_has_csr()) { + /* CSR BT module */ + iphone_write_string(output, "msleep 50\n"); + iphone_write_string(output, "csr -p 0x01ca=0x0031\n"); + iphone_write_string(output, "msleep 50\n"); + iphone_write_string(output, "csr -p 0x01c7=0x0001,0x01f4,0x0005,0x0020\n"); + power_management_active = 1; + } else { + /* BCM BT module, deactivated since untested for now */ + // iphone_write_string(output, "bcm -s 0x01,0x00,0x00,0x01,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x01\n"); + // iphone_write_string(output, "msleep 50\n"); + power_management_active = 0; + } +#endif + return 0; } @@ -382,18 +403,27 @@ static void iphone_write_configscript(int fd, int baudrate){ iphone_csr_set_baud(fd, baudrate); iphone_csr_set_bd_addr(fd); iphone_write_string(fd, "csr -r\n"); +#ifdef USE_POWERMANAGEMENT + iphone_write_string(fd, "msleep 50\n"); + iphone_write_string(fd, "csr -p 0x01ca=0x0031\n"); + iphone_write_string(fd, "msleep 50\n"); + iphone_write_string(fd, "csr -p 0x01c7=0x0001,0x01f4,0x0005,0x0020\n"); + power_management_active = 1; +#endif } 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"); +#ifdef USE_POWERMANAGEMENT + iphone_write_string(fd, "bcm -s 0x01,0x00,0x00,0x01,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x01\n"); + iphone_write_string(fd, "msleep 50\n"); + power_management_active = 1; +#endif } iphone_write_string(fd, "quit\n"); } -static char *os3xBlueTool = "BlueTool"; -static char *os4xBlueTool = "/usr/local/bin/BlueToolH4"; - static int iphone_on (void *transport_config){ log_info("iphone_on: entered\n"); @@ -558,12 +588,20 @@ static int iphone_off (void *config){ } static int iphone_sleep(void *config){ + + // will sleep by itself + if (power_management_active) return 0; + // put Bluetooth into deep sleep system ("echo \"wake off\nquit\" | BlueTool"); return 0; } static int iphone_wake(void *config){ + + // will wake by itself + if (power_management_active) return 0; + // wake up Bluetooth module system ("echo \"wake on\nquit\" | BlueTool"); return 0; @@ -604,9 +642,11 @@ static void MySleepCallBack( void * refCon, io_service_t service, natural_t mess data = POWER_WILL_SLEEP; write(power_notification_pipe_fds[1], &data, 1); - // don't allow power change to get the 30 second delay - // IOAllowPowerChange( root_port, (long)messageArgument ); - + // only allow power change when power management active (and BT goes to sleep alone) + if (!power_management_active) break; + + IOAllowPowerChange( root_port, (long)messageArgument ); + break; case kIOMessageSystemWillPowerOn: @@ -635,8 +675,10 @@ static int power_notification_process(struct data_source *ds) { if (bytes_read != 1) return -1; log_info("power_notification_process: %u\n", token); + + if (power_management_active) return 0; - power_notification_callback( (POWER_NOTIFICATION_t) token ); + power_notification_callback( (POWER_NOTIFICATION_t) token ); return 0; } diff --git a/src/get_version.sh b/src/get_version.sh index 43522ebd2..d398b225c 100755 --- a/src/get_version.sh +++ b/src/get_version.sh @@ -2,7 +2,7 @@ FILE=../include/btstack/version.h REVISION=`svnversion | sed "s/\([0-9]*\).*/\1/"` MAJOR=0 -MINOR=3 +MINOR=4 DATE=`date "+%Y-%m-%d_%H:%M:%S"` printf "// BTstack - version.h\n" > $FILE printf "// - generated by %s\n" $0>> $FILE diff --git a/src/hci_transport_h4.c b/src/hci_transport_h4.c index 6d3aaa9d6..c938b5263 100644 --- a/src/hci_transport_h4.c +++ b/src/hci_transport_h4.c @@ -36,6 +36,14 @@ * * Created by Matthias Ringwald on 4/29/09. */ + +#include "../config.h" + +#undef USE_NETGRAPH +#undef USE_HCI_READER_THREAD +// go back to sleep in 3s +#define HCI_WAKE_TIMER_MS 3000 + #include /* POSIX terminal control definitions */ #include /* File control definitions */ #include /* UNIX standard function definitions */ @@ -48,7 +56,11 @@ #include "hci_transport.h" #include "hci_dump.h" -// #define USE_HCI_READER_THREAD +#if defined (USE_BLUETOOL) && defined (USE_POWERMANAGEMENT) +/* iPhone power management support */ +#define BT_WAKE_DEVICE "/dev/btwake" +static int fd_wake = 0; +#endif typedef enum { H4_W4_PACKET_TYPE, @@ -69,6 +81,9 @@ typedef struct hci_transport_h4 { pthread_mutex_t mutex; pthread_cond_t cond; #endif +#if defined (USE_BLUETOOL) && defined (USE_POWERMANAGEMENT) + timer_source_t sleep_timer; +#endif } hci_transport_h4_t; // single instance @@ -82,7 +97,11 @@ static hci_uart_config_t *hci_uart_config; static void *h4_reader(void *context); static int h4_reader_process(struct data_source *ds); #endif - +#if defined (USE_BLUETOOL) && defined (USE_POWERMANAGEMENT) +static void h4_wake_on(void); +static void h4_wake_off(void); +static void h4_wake_timeout(struct timer *ts); +#endif static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler; @@ -93,6 +112,38 @@ static int read_pos; static uint8_t hci_packet[1+HCI_PACKET_BUFFER_SIZE]; // packet type + max(acl header + acl payload, event header + event data) +#if defined (USE_BLUETOOL) && defined (USE_POWERMANAGEMENT) +static void h4_wake_on(void) +{ + if (!fd_wake) { + fd_wake = open(BT_WAKE_DEVICE, O_RDWR); + usleep(10000); + } + run_loop_remove_timer(&hci_transport_h4->sleep_timer); + run_loop_set_timer(&hci_transport_h4->sleep_timer, HCI_WAKE_TIMER_MS); + hci_transport_h4->sleep_timer.process = h4_wake_timeout; + run_loop_add_timer(&hci_transport_h4->sleep_timer); + + return; +} + +static void h4_wake_off(void) +{ + run_loop_remove_timer(&hci_transport_h4->sleep_timer); + if (fd_wake) { + close(fd_wake); + fd_wake = 0; + } + return; +} + +static void h4_wake_timeout(struct timer *ts) +{ + h4_wake_off(); +} + +#endif /* defined (USE_BLUETOOL) && defined (USE_POWERMANAGEMENT) */ + // prototypes static int h4_open(void *transport_config){ hci_uart_config = (hci_uart_config_t*) transport_config; @@ -191,13 +242,18 @@ static int h4_open(void *transport_config){ return 0; } -static int h4_close(void *transport_config){ +static int h4_close(void *transport_config){ // first remove run loop handler run_loop_remove_data_source(hci_transport_h4->ds); // close device close(hci_transport_h4->ds->fd); - + +#if defined (USE_BLUETOOL) && defined (USE_POWERMANAGEMENT) + // let module sleep + h4_wake_off(); +#endif + // free struct free(hci_transport_h4->ds); hci_transport_h4->ds = NULL; @@ -207,6 +263,12 @@ static int h4_close(void *transport_config){ static int h4_send_packet(uint8_t packet_type, uint8_t * packet, int size){ if (hci_transport_h4->ds == NULL) return -1; if (hci_transport_h4->uart_fd == 0) return -1; + +#if defined (USE_BLUETOOL) && defined (USE_POWERMANAGEMENT) + // wake Bluetooth module + h4_wake_on(); +#endif + hci_dump_packet( (uint8_t) packet_type, 0, packet, size); char *data = (char*) packet; int bytes_written = write(hci_transport_h4->uart_fd, &packet_type, 1);