mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-16 22:21:21 +00:00
keep list of clients that requested Blueooth to be active, Bluetooth is on iff at least one client did request it. delay off by 10 seconds
This commit is contained in:
parent
e1aafbfb72
commit
a8d66173c1
16
TODO.txt
16
TODO.txt
@ -24,10 +24,20 @@ NEXT:
|
||||
- DONE: don't stop BTdaemon on power down/client disconnect
|
||||
- DONE: handle transition for HCI_POWER_SLEEP and all HCI state transitions
|
||||
- DONE: power down Bluetooth on sleep notifcation / turn on, if clients are connected
|
||||
- decide on configure flags
|
||||
- clean up components
|
||||
- DONE: keep list of clients that requested Blueooth to be active
|
||||
- DONE: Bluetooth is on iff at least one client did request it. delay off by 10 seconds
|
||||
- add enum POWER_EVENTS {POWER_WILL_SLEEP, POWER_WILL_WAKE_UP);
|
||||
- add register_for_power_management_notifictations( void (*callback)(POWER_EVENTS event)); to bt_control.h
|
||||
- move core foundation power event code to bt_control_iphone.m
|
||||
- add sleep() to bt_control.h (assumption: no off -> sleep transition)
|
||||
|
||||
- store HCI_POWER_ON/HCI_POWER_OFF per client, and only turn off when all are turned off
|
||||
- clean up components
|
||||
- consolidate ios code in port_ios.m (bt_control_iphone.m, platform_iphone.m)
|
||||
- consolidate cocoa/corefoundation code in port_corefoundation.c (remote_device_db)
|
||||
- rename bt_control.h -> power_management.h
|
||||
- add control of status bar icon to bt_control.h, too.
|
||||
- decide on configure flags
|
||||
CFMessagePortCreateRemote
|
||||
- decide what to do with the CocoaTouch code.
|
||||
- do nothing
|
||||
- add it to libBTstack.dylib
|
||||
|
104
src/daemon.c
104
src/daemon.c
@ -71,7 +71,7 @@
|
||||
#include <libusb-1.0/libusb.h>
|
||||
#endif
|
||||
|
||||
#define DAEMON_NO_CONNECTION_TIMEOUT 10000
|
||||
#define DAEMON_NO_ACTIVE_CLIENT_TIMEOUT 10000
|
||||
|
||||
#define HANDLE_POWER_NOTIFICATIONS
|
||||
|
||||
@ -82,12 +82,17 @@ static hci_uart_config_t config;
|
||||
static timer_source_t timeout;
|
||||
static uint8_t timeout_active = 0;
|
||||
|
||||
static int num_client_connections = 0;
|
||||
static int power_management_sleep = 0;
|
||||
|
||||
static void dummy_bluetooth_status_handler(BLUETOOTH_STATE state);
|
||||
static void (*bluetooth_status_handler)(BLUETOOTH_STATE state) = dummy_bluetooth_status_handler;
|
||||
|
||||
|
||||
static linked_list_t active_clients = NULL; // list of clients that requested Bluetooth to be active
|
||||
static int active_clients_empty();
|
||||
static void active_clients_remove(connection_t *connection);
|
||||
static void active_clients_add(connection_t *connection);
|
||||
static void active_clients_start_power_off_timer();
|
||||
static void active_clients_stop_power_off_timer();
|
||||
|
||||
#ifdef HANDLE_POWER_NOTIFICATIONS
|
||||
|
||||
@ -178,6 +183,7 @@ void MySleepCallBack( void * refCon, io_service_t service, natural_t messageType
|
||||
*/
|
||||
|
||||
// let's sleep
|
||||
power_management_sleep = 1;
|
||||
hci_power_control(HCI_POWER_SLEEP);
|
||||
|
||||
// power control only starts falling asleep, count on the 30 second delay
|
||||
@ -189,7 +195,8 @@ void MySleepCallBack( void * refCon, io_service_t service, natural_t messageType
|
||||
//System has started the wake up process...
|
||||
|
||||
// assume that all clients use Bluetooth -> if connection, start Bluetooth
|
||||
if (num_client_connections) {
|
||||
power_management_sleep = 0;
|
||||
if (!active_clients_empty()) {
|
||||
hci_power_control(HCI_POWER_ON);
|
||||
}
|
||||
break;
|
||||
@ -211,7 +218,8 @@ static void dummy_bluetooth_status_handler(BLUETOOTH_STATE state){
|
||||
};
|
||||
|
||||
static void daemon_no_connections_timeout(){
|
||||
printf("No connection for %u seconds -> POWER OFF\n", DAEMON_NO_CONNECTION_TIMEOUT/1000);
|
||||
if (!active_clients_empty()) return; // false alarm :)
|
||||
printf("No active client connection for %u seconds -> POWER OFF\n", DAEMON_NO_ACTIVE_CLIENT_TIMEOUT/1000);
|
||||
hci_power_control(HCI_POWER_OFF);
|
||||
}
|
||||
|
||||
@ -231,7 +239,24 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui
|
||||
hci_emit_state();
|
||||
break;
|
||||
case BTSTACK_SET_POWER_MODE:
|
||||
hci_power_control(packet[3]);
|
||||
// track client power requests
|
||||
switch (packet[3]) {
|
||||
case HCI_POWER_ON:
|
||||
active_clients_add(connection);
|
||||
break;
|
||||
case HCI_POWER_OFF:
|
||||
active_clients_remove(connection);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// handle merged state
|
||||
if (active_clients_empty()){
|
||||
active_clients_start_power_off_timer();
|
||||
} else if (!power_management_sleep) {
|
||||
active_clients_stop_power_off_timer();
|
||||
hci_power_control(HCI_POWER_ON);
|
||||
}
|
||||
break;
|
||||
case BTSTACK_GET_VERSION:
|
||||
hci_emit_btstack_version();
|
||||
@ -325,19 +350,15 @@ static int daemon_client_handler(connection_t *connection, uint16_t packet_type,
|
||||
case DAEMON_EVENT_CONNECTION_CLOSED:
|
||||
sdp_unregister_services_for_connection(connection);
|
||||
l2cap_close_connection(connection);
|
||||
active_clients_remove(connection);
|
||||
printf("Client connection closed. active_clients_empty()=%u\n",active_clients_empty());
|
||||
if (active_clients_empty()){
|
||||
active_clients_start_power_off_timer();
|
||||
}
|
||||
break;
|
||||
case DAEMON_NR_CONNECTIONS_CHANGED:
|
||||
num_client_connections = data[1];
|
||||
printf("Nr Connections changed, new %u\n",num_client_connections);
|
||||
if (timeout_active) {
|
||||
run_loop_remove_timer(&timeout);
|
||||
timeout_active = 0;
|
||||
}
|
||||
if (!num_client_connections) {
|
||||
run_loop_set_timer(&timeout, DAEMON_NO_CONNECTION_TIMEOUT);
|
||||
run_loop_add_timer(&timeout);
|
||||
timeout_active = 1;
|
||||
}
|
||||
printf("Nr Connections changed, new %u\n",data[1]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -559,4 +580,51 @@ int main (int argc, char * const * argv){
|
||||
// go!
|
||||
run_loop_execute();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark manage list of active clients
|
||||
static int active_clients_empty(){
|
||||
return linked_list_empty(&active_clients);
|
||||
}
|
||||
|
||||
static void active_clients_add(connection_t *connection){
|
||||
// check if exists -> done
|
||||
linked_item_t *it;
|
||||
for (it = (linked_item_t *) active_clients; it ; it = it->next){
|
||||
if (it->user_data == connection) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// otherwise add new item
|
||||
linked_item_t *item = malloc(sizeof(linked_item_t));
|
||||
if (!item) return;
|
||||
item->user_data = connection;
|
||||
linked_list_add(&active_clients, item);
|
||||
}
|
||||
|
||||
static void active_clients_remove(connection_t *connection){
|
||||
// iterate over list and remove item for connection
|
||||
linked_item_t *it;
|
||||
for (it = (linked_item_t *) &active_clients; it ; it = it->next){
|
||||
linked_item_t *next = it->next;
|
||||
if (next && next->user_data == connection){
|
||||
it->next = next->next;
|
||||
free(next); // free item
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void active_clients_stop_power_off_timer(){
|
||||
if (timeout_active) {
|
||||
run_loop_remove_timer(&timeout);
|
||||
timeout_active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void active_clients_start_power_off_timer(){
|
||||
active_clients_stop_power_off_timer();
|
||||
run_loop_set_timer(&timeout, DAEMON_NO_ACTIVE_CLIENT_TIMEOUT);
|
||||
run_loop_add_timer(&timeout);
|
||||
timeout_active = 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user