mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-21 12:40:42 +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
|
Last milestone reached: Restart client app without restarting BTdaemon possible
|
||||||
|
|
||||||
NEXT:
|
NEXT:
|
||||||
- automatic turn off Bluetooth after X minutes idle
|
|
||||||
- turn off Bluetooth on ctrl-c
|
- turn off Bluetooth on ctrl-c
|
||||||
- automatic start/stop of BTdaemon
|
- automatic start/stop of BTdaemon
|
||||||
- start BTdaemon by client lib
|
- start BTdaemon by client lib
|
||||||
|
29
src/daemon.c
29
src/daemon.c
@ -34,9 +34,18 @@
|
|||||||
#include "hci_transport_usb.h"
|
#include "hci_transport_usb.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DAEMON_NO_CONNECTION_TIMEOUT 60
|
||||||
|
|
||||||
static hci_transport_t * transport;
|
static hci_transport_t * transport;
|
||||||
static hci_uart_config_t config;
|
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){
|
static int btstack_command_handler(connection_t *connection, uint8_t *packet, uint16_t size){
|
||||||
// BTstack Commands
|
// BTstack Commands
|
||||||
hci_dump_packet( HCI_COMMAND_DATA_PACKET, 1, packet, size);
|
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);
|
l2cap_send_internal(channel, data, length);
|
||||||
break;
|
break;
|
||||||
case DAEMON_EVENT_PACKET:
|
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
|
// only one event so far: client connection died
|
||||||
l2cap_close_channels_for_connection(connection);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -123,7 +146,9 @@ int main (int argc, const char * argv[]){
|
|||||||
|
|
||||||
// init L2CAP
|
// init L2CAP
|
||||||
l2cap_init();
|
l2cap_init();
|
||||||
|
|
||||||
|
timeout.process = daemon_no_connections_timeout;
|
||||||
|
|
||||||
// @TODO: make choice of socket server configurable (TCP and/or Unix Domain Socket)
|
// @TODO: make choice of socket server configurable (TCP and/or Unix Domain Socket)
|
||||||
// @TODO: make port and/or socket configurable per config.h
|
// @TODO: make port and/or socket configurable per config.h
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
#define HCI_EVENT_DATA_BUFFER_OVERFLOW 0x1A
|
#define HCI_EVENT_DATA_BUFFER_OVERFLOW 0x1A
|
||||||
#define HCI_EVENT_MAX_SLOTS_CHANGED 0x1B
|
#define HCI_EVENT_MAX_SLOTS_CHANGED 0x1B
|
||||||
#define HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE 0x1C
|
#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_INQUIRY_RESULT_WITH_RSSI 0x22
|
||||||
#define HCI_EVENT_VENDOR_SPECIFIC 0xFF
|
#define HCI_EVENT_VENDOR_SPECIFIC 0xFF
|
||||||
|
|
||||||
@ -90,6 +90,12 @@
|
|||||||
#define HCI_EVENT_L2CAP_TIMEOUT_CHECK 0x84
|
#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 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)
|
#define IS_COMMAND(packet, command) (READ_BT_16(packet,0) == command.opcode)
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
// extension for client/server communication
|
// extension for client/server communication
|
||||||
#define L2CAP_DATA_PACKET 0x05
|
#define L2CAP_DATA_PACKET 0x05
|
||||||
|
|
||||||
#define DAEMON_EVENT_PACKET 0x06
|
#define DAEMON_EVENT_PACKET 0x06
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -114,15 +114,31 @@ connection_t * socket_connection_register_new_connection(int fd){
|
|||||||
return conn;
|
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) {
|
int socket_connection_hci_process(struct data_source *ds) {
|
||||||
connection_t *conn = (connection_t *) ds;
|
connection_t *conn = (connection_t *) ds;
|
||||||
int bytes_read = read(ds->fd, &conn->buffer[conn->bytes_read], conn->bytes_to_read);
|
int bytes_read = read(ds->fd, &conn->buffer[conn->bytes_read], conn->bytes_to_read);
|
||||||
if (bytes_read <= 0){
|
if (bytes_read <= 0){
|
||||||
// connection broken (no particular channel, no date yet)
|
// 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
|
// free connection
|
||||||
socket_connection_free_connection(linked_item_get_user(&ds->item));
|
socket_connection_free_connection(linked_item_get_user(&ds->item));
|
||||||
|
|
||||||
|
socket_connection_emit_nr_connections();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
conn->bytes_read += bytes_read;
|
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);
|
printf("socket_connection_accept new connection %u\n", fd);
|
||||||
|
|
||||||
socket_connection_register_new_connection(fd);
|
socket_connection_register_new_connection(fd);
|
||||||
|
socket_connection_emit_nr_connections();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user