mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-20 18:40:31 +00:00
automatic turn off Bluetooth after 1 minutes idle
This commit is contained in:
parent
ee091cf1fd
commit
555971d7f5
1
TODO.txt
1
TODO.txt
@ -3,7 +3,6 @@
|
||||
Last milestone reached: Restart client app without restarting BTdaemon possible
|
||||
|
||||
NEXT:
|
||||
- automatic turn off Bluetooth after X minutes idle
|
||||
- turn off Bluetooth on ctrl-c
|
||||
- automatic start/stop of BTdaemon
|
||||
- start BTdaemon by client lib
|
||||
|
29
src/daemon.c
29
src/daemon.c
@ -34,9 +34,18 @@
|
||||
#include "hci_transport_usb.h"
|
||||
#endif
|
||||
|
||||
#define DAEMON_NO_CONNECTION_TIMEOUT 60
|
||||
|
||||
static hci_transport_t * transport;
|
||||
static hci_uart_config_t config;
|
||||
|
||||
static timer_t timeout;
|
||||
|
||||
static void daemon_no_connections_timeout(){
|
||||
printf("No connection for %u secondes -> POWER OFF\n", DAEMON_NO_CONNECTION_TIMEOUT);
|
||||
hci_power_control( HCI_POWER_OFF);
|
||||
}
|
||||
|
||||
static int btstack_command_handler(connection_t *connection, uint8_t *packet, uint16_t size){
|
||||
// BTstack Commands
|
||||
hci_dump_packet( HCI_COMMAND_DATA_PACKET, 1, packet, size);
|
||||
@ -86,8 +95,22 @@ static int daemon_client_handler(connection_t *connection, uint16_t packet_type,
|
||||
l2cap_send_internal(channel, data, length);
|
||||
break;
|
||||
case DAEMON_EVENT_PACKET:
|
||||
switch (data[0]) {
|
||||
case DAEMON_CONNECTION_CLOSED:
|
||||
l2cap_close_channels_for_connection(connection);
|
||||
break;
|
||||
case DAEMON_NR_CONNECTIONS_CHANGED:
|
||||
// printf("Nr Connections changed, new %u\n", data[1]);
|
||||
if (data[1]) {
|
||||
run_loop_remove_timer(&timeout);
|
||||
} else {
|
||||
run_loop_set_timer(&timeout, DAEMON_NO_CONNECTION_TIMEOUT);
|
||||
run_loop_add_timer(&timeout);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// only one event so far: client connection died
|
||||
l2cap_close_channels_for_connection(connection);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@ -123,7 +146,9 @@ int main (int argc, const char * argv[]){
|
||||
|
||||
// init L2CAP
|
||||
l2cap_init();
|
||||
|
||||
|
||||
timeout.process = daemon_no_connections_timeout;
|
||||
|
||||
// @TODO: make choice of socket server configurable (TCP and/or Unix Domain Socket)
|
||||
// @TODO: make port and/or socket configurable per config.h
|
||||
|
||||
|
@ -72,7 +72,7 @@
|
||||
#define HCI_EVENT_DATA_BUFFER_OVERFLOW 0x1A
|
||||
#define HCI_EVENT_MAX_SLOTS_CHANGED 0x1B
|
||||
#define HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE 0x1C
|
||||
#define NECTEVENT_ION_PACKET_TYPE_CHANGED 0x1D
|
||||
#define HCI_EVENT_PACKET_TYPE_CHANGED 0x1D
|
||||
#define HCI_EVENT_INQUIRY_RESULT_WITH_RSSI 0x22
|
||||
#define HCI_EVENT_VENDOR_SPECIFIC 0xFF
|
||||
|
||||
@ -90,6 +90,12 @@
|
||||
#define HCI_EVENT_L2CAP_TIMEOUT_CHECK 0x84
|
||||
|
||||
|
||||
// data: event(8)
|
||||
#define DAEMON_CONNECTION_CLOSED 0xc0
|
||||
|
||||
// data: event(8), nr_connections(8)
|
||||
#define DAEMON_NR_CONNECTIONS_CHANGED 0xc1
|
||||
|
||||
#define COMMAND_COMPLETE_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_COMPLETE && READ_BT_16(event,3) == cmd.opcode)
|
||||
|
||||
#define IS_COMMAND(packet, command) (READ_BT_16(packet,0) == command.opcode)
|
||||
|
@ -36,6 +36,7 @@
|
||||
|
||||
// extension for client/server communication
|
||||
#define L2CAP_DATA_PACKET 0x05
|
||||
|
||||
#define DAEMON_EVENT_PACKET 0x06
|
||||
|
||||
typedef struct {
|
||||
|
@ -114,15 +114,31 @@ connection_t * socket_connection_register_new_connection(int fd){
|
||||
return conn;
|
||||
}
|
||||
|
||||
void static socket_connection_emit_nr_connections(){
|
||||
linked_item_t *it;
|
||||
uint8_t nr_connections = 0;
|
||||
for (it = (linked_item_t *) connections; it != NULL ; it = it->next, nr_connections++);
|
||||
|
||||
uint8_t event[2];
|
||||
event[0] = DAEMON_NR_CONNECTIONS_CHANGED;
|
||||
event[1] = nr_connections;
|
||||
(*socket_connection_packet_callback)(NULL, DAEMON_EVENT_PACKET, 0, (uint8_t *) &event, 2);
|
||||
// printf("Nr connections changed,.. new %u\n", nr_connections);
|
||||
}
|
||||
|
||||
int socket_connection_hci_process(struct data_source *ds) {
|
||||
connection_t *conn = (connection_t *) ds;
|
||||
int bytes_read = read(ds->fd, &conn->buffer[conn->bytes_read], conn->bytes_to_read);
|
||||
if (bytes_read <= 0){
|
||||
// connection broken (no particular channel, no date yet)
|
||||
(*socket_connection_packet_callback)(conn, DAEMON_EVENT_PACKET, 0, NULL, 0);
|
||||
uint8_t event[1];
|
||||
event[0] = DAEMON_CONNECTION_CLOSED;
|
||||
(*socket_connection_packet_callback)(conn, DAEMON_EVENT_PACKET, 0, (uint8_t *) &event, 1);
|
||||
|
||||
// free connection
|
||||
socket_connection_free_connection(linked_item_get_user(&ds->item));
|
||||
|
||||
socket_connection_emit_nr_connections();
|
||||
return 0;
|
||||
}
|
||||
conn->bytes_read += bytes_read;
|
||||
@ -161,6 +177,7 @@ static int socket_connection_accept(struct data_source *socket_ds) {
|
||||
printf("socket_connection_accept new connection %u\n", fd);
|
||||
|
||||
socket_connection_register_new_connection(fd);
|
||||
socket_connection_emit_nr_connections();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user