add, track, and handle btstack_set_disoverable

This commit is contained in:
matthias.ringwald 2011-01-10 21:11:58 +00:00
parent bc2af4fc4b
commit 381fbed89a
5 changed files with 88 additions and 41 deletions

View File

@ -12,25 +12,16 @@
2010-xxxx: Release 0.2 - revions xxx
- limit size of /tmp/hci_dump.pklg to 1000 packets (max 1 MB)
- power handling: handle power changes in all states, receive and handle power notifications, keep track of individual clients
- fixed bugs in cocoa run loop implementation
- automate scan enable management: hci_set_discoverable(bool) sets inquiry scan, page scan is always active
NEXT:
- DONE: provide per client information: connection, power mode
- DONE: fix bug with run_loop_cocoa, after client disconnects
- power handling
- DONE: add wake() to bt_control.h: OFF<->ON<->SLEEP (SLEEP -> OFF is possible)
- DONE: check if Bluetooth module can be woken up instantly with BlueTool on Broadcom chipsets -> yes
- check if Bluetooth module can be woken up instantly with BlueTool on CSR chipsets
- check apps for sleep mode compatibility - see what happens on ACTIVATED event
- Keyboard
- Mouse
- WeBe++
- WiiMote example
- BTstackManager
- automate scan enable management
- provide new "set discoverable (on/off)" command and store in per client information
- keep track of page scan enable -> active if l2cap services exist
- check apps for sleep mode/reactivated compatibility - see what happens on ACTIVATED event
- WiiMote example
- BTstackManager
- Keyboard
- Mouse
- WeBe++
- clean up components
- consolidate iOS code in port_ios.m (bt_control_iphone.m, platform_iphone.m)
@ -39,15 +30,13 @@ NEXT:
- add control of status bar icon to bt_control.h, too.
- decide on configure flags
- dynamic link BTdaemon against libBTstack.dylist
- decide what to do with the CocoaTouch code. Options:
- do nothing (potential problem with multiple dylibs in same process)
- add it to libBTstack.dylib
- provide a libBTstackCocoaTouch.dylib (less memory usage)
- move RFCOMM code into BTdaemon
- have a look at External Accessory interface by Apple - it's quite similar in function to BTstack
- HCI CMD packet is limited to 1024 bytes payload. SDP records could be larger than that. Options:
- provide a way to transfer SDP records in segments

View File

@ -118,9 +118,12 @@ extern "C" {
// data: system bluetooth on/off (bool)
#define BTSTACK_EVENT_SYSTEM_BLUETOOTH_ENABLED 0x64
// data: event (8), len(8), status (8) == 0, address (48), name (1984 = 248 bytes)
// 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
// data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16)
#define L2CAP_EVENT_CHANNEL_OPENED 0x70

View File

@ -89,30 +89,30 @@ typedef struct {
} client_state_t;
static hci_transport_t * transport;
static hci_uart_config_t config;
static timer_source_t timeout;
static uint8_t timeout_active = 0;
static int power_management_sleep = 0;
#pragma mark prototypes
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 clients = NULL; // list of connected clients
static client_state_t * client_for_connection(connection_t *connection);
static int clients_requires_power_on();
static int clients_require_power_on();
static int clients_require_discoverable();
static void start_power_off_timer();
static void stop_power_off_timer();
#pragma mark globals
static hci_transport_t * transport;
static hci_uart_config_t config;
static timer_source_t timeout;
static uint8_t timeout_active = 0;
static int power_management_sleep = 0;
static linked_list_t clients = NULL; // list of connected clients
static void (*bluetooth_status_handler)(BLUETOOTH_STATE state) = dummy_bluetooth_status_handler;
static void dummy_bluetooth_status_handler(BLUETOOTH_STATE state){
printf("Bluetooth status: %u\n", state);
};
static void daemon_no_connections_timeout(){
if (clients_requires_power_on()) return; // false alarm :)
if (clients_require_power_on()) 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);
}
@ -140,7 +140,7 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui
if (!client) break;
client->power_mode = packet[3];
// handle merged state
if (!clients_requires_power_on()){
if (!clients_require_power_on()){
start_power_off_timer();
} else if (!power_management_sleep) {
stop_power_off_timer();
@ -153,7 +153,9 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui
#ifdef USE_BLUETOOL
case BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED:
iphone_system_bt_set_enabled(packet[3]);
// fall through .. :)
hci_emit_system_bluetooth_enabled(iphone_system_bt_enabled());
break;
case BTSTACK_GET_SYSTEM_BLUETOOTH_ENABLED:
hci_emit_system_bluetooth_enabled(iphone_system_bt_enabled());
break;
@ -163,6 +165,14 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui
hci_emit_system_bluetooth_enabled(0);
break;
#endif
case BTSTACK_SET_DISCOVERABLE:
// track client discoverable requests
client = client_for_connection(connection);
if (!client) break;
client->discoverable = packet[3];
// merge state
hci_discoverable_control(clients_require_discoverable());
break;
case L2CAP_CREATE_CHANNEL_MTU:
bt_flip_addr(addr, &packet[3]);
psm = READ_BT_16(packet, 9);
@ -252,8 +262,10 @@ static int daemon_client_handler(connection_t *connection, uint16_t packet_type,
if (!client) break;
linked_list_remove(&clients, (linked_item_t *) client);
free(client);
printf("Client connection closed. clients_requires_power_on()=%u\n",clients_requires_power_on());
if (!clients_requires_power_on()){
// update discoverable mode
hci_discoverable_control(clients_require_discoverable());
// start power off, if last active client
if (!clients_require_power_on()){
start_power_off_timer();
}
break;
@ -333,7 +345,7 @@ static void power_notification_callback(POWER_NOTIFICATION_t notification){
case POWER_WILL_WAKE_UP:
// assume that all clients use Bluetooth -> if connection, start Bluetooth
power_management_sleep = 0;
if (clients_requires_power_on()) {
if (clients_require_power_on()) {
hci_power_control(HCI_POWER_ON);
}
break;
@ -528,7 +540,7 @@ static client_state_t * client_for_connection(connection_t *connection) {
return NULL;
}
static int clients_requires_power_on(){
static int clients_require_power_on(){
linked_item_t *it;
for (it = (linked_item_t *) clients; it ; it = it->next){
client_state_t * client_state = (client_state_t *) it;
@ -538,3 +550,14 @@ static int clients_requires_power_on(){
}
return 0;
}
static int clients_require_discoverable(){
linked_item_t *it;
for (it = (linked_item_t *) clients; it ; it = it->next){
client_state_t * client_state = (client_state_t *) it;
if (client_state->discoverable) {
return 1;
}
}
return 0;
}

View File

@ -344,6 +344,9 @@ static void event_handler(uint8_t *packet, int size){
log_dbg("hci_read_buffer_size: size %u, count %u\n", hci_stack.acl_data_packet_length, hci_stack.total_num_acl_packets);
}
}
if (COMMAND_COMPLETE_EVENT(packet, hci_write_scan_enable)){
hci_emit_discoverable_enabled(hci_stack.discoverable);
}
break;
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
@ -758,6 +761,18 @@ int hci_power_control(HCI_POWER_MODE power_mode){
return 0;
}
void hci_discoverable_control(uint8_t enable){
if (enable) enable = 1; // normalize argument
if (hci_stack.discoverable == enable){
hci_emit_discoverable_enabled(hci_stack.discoverable);
return;
}
hci_send_cmd(&hci_write_scan_enable, 2 | enable); // 1 = inq scan, 2 = page scan
hci_stack.discoverable = enable;
}
void hci_run(){
if (hci_stack.num_cmd_packets == 0) {
@ -1026,3 +1041,13 @@ void hci_emit_remote_name_cached(bd_addr_t *addr, device_name_t *name){
hci_dump_packet(HCI_EVENT_PACKET, 0, event, len);
hci_stack.packet_handler(HCI_EVENT_PACKET, event, len);
}
void hci_emit_discoverable_enabled(uint8_t enabled){
uint8_t len = 3;
uint8_t event[len];
event[0] = BTSTACK_EVENT_DISCOVERABLE_ENABLED;
event[1] = len - 2;
event[2] = enabled;
hci_dump_packet( HCI_EVENT_PACKET, 0, event, len);
hci_stack.packet_handler(HCI_EVENT_PACKET, event, len);
}

View File

@ -89,6 +89,9 @@ extern "C" {
// set system Bluetooth state
#define BTSTACK_SET_SYSTEM_BLUETOOTH_ENABLED 0x06
// enable inquiry scan for this client
#define BTSTACK_SET_DISCOVERABLE 0x07
// create l2cap channel: @param bd_addr(48), psm (16)
#define L2CAP_CREATE_CHANNEL 0x20
@ -223,6 +226,9 @@ typedef struct {
uint8_t substate;
uint8_t cmds_ready;
/* */
uint8_t discoverable;
} hci_stack_t;
// create and send hci command packets based on a template and a list of parameters
@ -268,6 +274,7 @@ void hci_emit_hci_open_failed();
void hci_emit_btstack_version();
void hci_emit_system_bluetooth_enabled(uint8_t enabled);
void hci_emit_remote_name_cached(bd_addr_t *addr, device_name_t *name);
void hci_emit_discoverable_enabled(uint8_t enabled);
#if defined __cplusplus
}