handle HCI_POWER_ON and HCI_POWER_OFF in existing 4 states

This commit is contained in:
matthias.ringwald 2011-01-07 19:36:05 +00:00
parent c7e0c5f6bb
commit 8d213e1a0d
2 changed files with 136 additions and 37 deletions

View File

@ -17,8 +17,11 @@ NEXT:
- power handling
- DONE: figure out how to receive iPhone System Power IONotifications (in BTdaemon) to detect, when phone gets locked and wakes up
- DONE: introduce HCI states SLEEPING and FALLING_ASLEEP
- DONE: introduce HCI power mode command SLEEP
- stop all baseband connections on HCI_POWER_OFF and HCI_POWER_SLEEP
- DONE: introduce HCI power mode command SLEEPING
- DONE: stop all baseband connections on HCI_POWER_OFF
- DONE: handle HCI_POWER_ON and HCI_POWER_OFF in existing 4 states
- stop all baseband connections on HCI_POWER_SLEEP
- handle power-off and power-on for states SLEEPING and FALLING_ASLEEP
- for now, treat sleep/wake the same as power off/on
- decide on configure flags
- clean up components

166
src/hci.c
View File

@ -547,8 +547,42 @@ void hci_close(){
}
}
// State-Module-Driver overview
// state module low-level
// HCI_STATE_OFF off close
// HCI_STATE_INITIALIZING, on open
// HCI_STATE_WORKING, on open
// HCI_STATE_HALTING, on open
// HCI_STATE_SLEEPING, ?? ??
// HCI_STATE_FALLING_ASLEEP ?? ??
static int hci_power_control_on(){
// power on
int err = 0;
if (hci_stack.control && hci_stack.control->on){
err = (*hci_stack.control->on)(hci_stack.config);
}
if (err){
log_err( "POWER_ON failed\n");
hci_emit_hci_open_failed();
return err;
}
// open low-level device
err = hci_stack.hci_transport->open(hci_stack.config);
if (err){
log_err( "HCI_INIT failed, turning Bluetooth off again\n");
if (hci_stack.control && hci_stack.control->off){
(*hci_stack.control->off)(hci_stack.config);
}
hci_emit_hci_open_failed();
return err;
}
return 0;
}
static void hci_power_control_off(){
// close all open connections
// close low-level device
hci_stack.hci_transport->close(hci_stack.config);
@ -560,42 +594,104 @@ static void hci_power_control_off(){
}
int hci_power_control(HCI_POWER_MODE power_mode){
if (power_mode == HCI_POWER_ON && hci_stack.state == HCI_STATE_OFF) {
// power on
int err = 0;
if (hci_stack.control && hci_stack.control->on){
err = (*hci_stack.control->on)(hci_stack.config);
}
if (err){
log_err( "POWER_ON failed\n");
hci_emit_hci_open_failed();
return err;
}
// open low-level device
err = hci_stack.hci_transport->open(hci_stack.config);
if (err){
log_err( "HCI_INIT failed, turning Bluetooth off again\n");
if (hci_stack.control && hci_stack.control->off){
(*hci_stack.control->off)(hci_stack.config);
int err = 0;
switch (hci_stack.state){
case HCI_STATE_OFF:
switch (power_mode){
case HCI_POWER_ON:
err = hci_power_control_on();
if (err) return err;
// set up state machine
hci_stack.num_cmd_packets = 1; // assume that one cmd can be sent
hci_stack.state = HCI_STATE_INITIALIZING;
hci_stack.substate = 0;
break;
case HCI_POWER_OFF:
// do nothing
break;
case HCI_POWER_SLEEP:
// TODO ...
break;
}
hci_emit_hci_open_failed();
return err;
}
// set up state machine
hci_stack.num_cmd_packets = 1; // assume that one cmd can be sent
hci_stack.state = HCI_STATE_INITIALIZING;
hci_stack.substate = 0;
} else if (power_mode == HCI_POWER_OFF && hci_stack.state == HCI_STATE_WORKING){
// see hci_run
hci_stack.state = HCI_STATE_HALTING;
break;
case HCI_STATE_INITIALIZING:
switch (power_mode){
case HCI_POWER_ON:
// do nothing
break;
case HCI_POWER_OFF:
// no connections yet, just turn it off
hci_power_control_off();
hci_stack.state = HCI_STATE_OFF;
break;
case HCI_POWER_SLEEP:
// TODO ...
break;
}
break;
case HCI_STATE_WORKING:
switch (power_mode){
case HCI_POWER_ON:
// do nothing
break;
case HCI_POWER_OFF:
// see hci_run
hci_stack.state = HCI_STATE_HALTING;
break;
case HCI_POWER_SLEEP:
// TODO ...
break;
}
break;
case HCI_STATE_HALTING:
switch (power_mode){
case HCI_POWER_ON:
// set up state machine
hci_stack.state = HCI_STATE_INITIALIZING;
hci_stack.substate = 0;
break;
case HCI_POWER_OFF:
// do nothing
break;
case HCI_POWER_SLEEP:
// TODO ...
break;
}
break;
case HCI_STATE_FALLING_ASLEEP:
switch (power_mode){
case HCI_POWER_ON:
// TODO ...
break;
case HCI_POWER_OFF:
// TODO ...
break;
case HCI_POWER_SLEEP:
// TODO ...
break;
}
break;
case HCI_STATE_SLEEPING:
switch (power_mode){
case HCI_POWER_ON:
// TODO ...
break;
case HCI_POWER_OFF:
// TODO ...
break;
case HCI_POWER_SLEEP:
// TODO ...
break;
}
break;
}
// create internal event
hci_emit_state();