diff --git a/src/daemon.c b/src/daemon.c index 196180bd0..6e5d4a465 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -58,9 +58,10 @@ int main (int argc, const char * argv[]){ // @TODO allow configuration per HCI CMD - // use logger: format HCI_DUMP_PACKETLOGGER or HCI_DUMP_BLUEZ - hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER); - + // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT + // hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER); + hci_dump_open(NULL, HCI_DUMP_STDOUT); + // init HCI hci_init(transport, &config, control); diff --git a/src/hci.c b/src/hci.c index 91d0d4de2..751b8a501 100644 --- a/src/hci.c +++ b/src/hci.c @@ -107,6 +107,11 @@ hci_cmd_t hci_read_bd_addr = { // no params }; +hci_cmd_t hci_get_btstack_state = { + OPCODE(OGF_BTSTACK, HCI_BTSTACK_GET_STATE), "" + // no params -> +}; + // the stack is here static hci_stack_t hci_stack; @@ -319,7 +324,7 @@ uint32_t hci_run(){ case 4: // done. hci_stack.state = HCI_STATE_WORKING; - micro_packet = BTSTACK_EVENT_HCI_WORKING; + micro_packet = HCI_EVENT_BTSTACK_WORKING; hci_stack.event_packet_handler(µ_packet, 1); break; default: @@ -337,7 +342,25 @@ uint32_t hci_run(){ int hci_send_acl_packet(uint8_t *packet, int size){ - return hci_stack.hci_transport->send_acl_packet(packet, size); + if (READ_CMD_OGF(packet) != OGF_BTSTACK) { + return hci_stack.hci_transport->send_acl_packet(packet, size); + } + + // BTstack internal commands + uint8_t event[3]; + switch (READ_CMD_OCF(packet)){ + case HCI_BTSTACK_GET_STATE: + event[0] = HCI_EVENT_BTSTACK_STATE; + event[1] = 1; + event[2] = hci_stack.state; + hci_stack.event_packet_handler(event, 3); + break; + default: + // TODO log into hci dump as vendor specific"event" + printf("Error: command %u not implemented\n:", READ_CMD_OCF(packet)); + break; + } + return 0; } int hci_send_cmd_packet(uint8_t *packet, int size){ diff --git a/src/hci.h b/src/hci.h index 2020d5fea..147716c66 100644 --- a/src/hci.h +++ b/src/hci.h @@ -22,6 +22,10 @@ // calculate combined ogf/ocf value #define OPCODE(ogf, ocf) (ocf | ogf << 10) +// get HCI CMD OGF +#define READ_CMD_OGF(buffer) (buffer[1] >> 2) +#define READ_CMD_OCF(buffer) ((buffer[1] & 0x03) << 8 | buffer[0]) + // packet header lengh #define HCI_CMD_DATA_PKT_HDR 0x03 #define HCI_ACL_DATA_PKT_HDR 0x04 @@ -32,7 +36,8 @@ #define OGF_LINK_CONTROL 0x01 #define OGF_CONTROLLER_BASEBAND 0x03 #define OGF_INFORMATIONAL_PARAMETERS 0x04 -#define OGF_VENDOR_COMMANDS 0x3f +#define OGF_BTSTACK 0x3d +#define OGF_VENDOR 0x3f // Events from host controller to host #define HCI_EVENT_INQUIRY_COMPLETE 0x01 @@ -67,7 +72,11 @@ #define HCI_EVENT_VENDOR_SPECIFIC 0xFF // events from BTstack for application/client lib -#define BTSTACK_EVENT_HCI_WORKING 0x80 +#define HCI_EVENT_BTSTACK_WORKING 0x80 +#define HCI_EVENT_BTSTACK_STATE 0x81 + +// cmds for BTstack +#define HCI_BTSTACK_GET_STATE 0x01 #define COMMAND_COMPLETE_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_COMPLETE && READ_BT_16(event,3) == cmd.opcode) @@ -211,3 +220,6 @@ extern hci_cmd_t hci_accept_connection_request; extern hci_cmd_t hci_write_inquiry_mode; extern hci_cmd_t hci_write_extended_inquiry_response; extern hci_cmd_t hci_write_simple_pairing_mode; + +// BTSTACK client/server commands - see hci.c for info on parameters +extern hci_cmd_t hci_get_btstack_state; \ No newline at end of file diff --git a/src/hci_dump.c b/src/hci_dump.c index 6102d2fb2..b5a4101f6 100644 --- a/src/hci_dump.c +++ b/src/hci_dump.c @@ -15,6 +15,7 @@ #include <strings.h> // bzero #include <unistd.h> // write #include <stdio.h> +#include <time.h> #include <sys/time.h> // for timestamps #include <sys/stat.h> // for mode flags @@ -40,22 +41,54 @@ static int dump_file = -1; static int dump_format; static hcidump_hdr header_bluez; static pktlog_hdr header_packetlogger; +static char time_string[40]; void hci_dump_open(char *filename, hci_dump_format_t format){ - if (dump_file < 0) { + dump_format = format; + if (dump_format == HCI_DUMP_STDOUT) { + dump_file = fileno(stdout); + } else { dump_file = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - dump_format = format; } } + void hci_dump_packet(uint8_t packet_type, uint8_t in, uint8_t *packet, uint16_t len) { if (dump_file < 0) return; // not activated yet // get time struct timeval curr_time; + struct tm* ptm; gettimeofday(&curr_time, NULL); switch (dump_format){ + case HCI_DUMP_STDOUT: + /* Obtain the time of day, and convert it to a tm struct. */ + ptm = localtime (&curr_time.tv_sec); + /* Format the date and time, down to a single second. */ + strftime (time_string, sizeof (time_string), "[%Y-%m-%d %H:%M:%S", ptm); + /* Compute milliseconds from microseconds. */ + uint16_t milliseconds = curr_time.tv_usec / 1000; + /* Print the formatted time, in seconds, followed by a decimal point + and the milliseconds. */ + printf ("%s.%03u] ", time_string, milliseconds); + switch (packet_type){ + case HCI_COMMAND_DATA_PACKET: + printf("CMD => "); + break; + case HCI_EVENT_PACKET: + printf("EVT <= "); + break; + case HCI_ACL_DATA_PACKET: + if (in) { + printf("ACL <= "); + } else { + printf("ACL => "); + } + break; + } + hexdump(packet, len); + break; case HCI_DUMP_BLUEZ: bt_store_16( (uint8_t *) &header_bluez.len, 0, 1 + len); header_bluez.in = in; diff --git a/src/hci_dump.h b/src/hci_dump.h index 496a756b8..3f8dbeef8 100644 --- a/src/hci_dump.h +++ b/src/hci_dump.h @@ -10,7 +10,8 @@ typedef enum { HCI_DUMP_BLUEZ = 0, - HCI_DUMP_PACKETLOGGER + HCI_DUMP_PACKETLOGGER, + HCI_DUMP_STDOUT } hci_dump_format_t; void hci_dump_open(char *filename, hci_dump_format_t format);