mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-28 19:20:54 +00:00
work on btstack client/server commands, allow logging to stdout using HCI_DUMP_STDOUT
This commit is contained in:
parent
c13e4b9a30
commit
8adf0dda45
@ -58,8 +58,9 @@ int main (int argc, const char * argv[]){
|
|||||||
|
|
||||||
// @TODO allow configuration per HCI CMD
|
// @TODO allow configuration per HCI CMD
|
||||||
|
|
||||||
// use logger: format HCI_DUMP_PACKETLOGGER or HCI_DUMP_BLUEZ
|
// 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("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
|
||||||
|
hci_dump_open(NULL, HCI_DUMP_STDOUT);
|
||||||
|
|
||||||
// init HCI
|
// init HCI
|
||||||
hci_init(transport, &config, control);
|
hci_init(transport, &config, control);
|
||||||
|
27
src/hci.c
27
src/hci.c
@ -107,6 +107,11 @@ hci_cmd_t hci_read_bd_addr = {
|
|||||||
// no params
|
// no params
|
||||||
};
|
};
|
||||||
|
|
||||||
|
hci_cmd_t hci_get_btstack_state = {
|
||||||
|
OPCODE(OGF_BTSTACK, HCI_BTSTACK_GET_STATE), ""
|
||||||
|
// no params ->
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// the stack is here
|
// the stack is here
|
||||||
static hci_stack_t hci_stack;
|
static hci_stack_t hci_stack;
|
||||||
@ -319,7 +324,7 @@ uint32_t hci_run(){
|
|||||||
case 4:
|
case 4:
|
||||||
// done.
|
// done.
|
||||||
hci_stack.state = HCI_STATE_WORKING;
|
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);
|
hci_stack.event_packet_handler(µ_packet, 1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -337,7 +342,25 @@ uint32_t hci_run(){
|
|||||||
|
|
||||||
|
|
||||||
int hci_send_acl_packet(uint8_t *packet, int size){
|
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){
|
int hci_send_cmd_packet(uint8_t *packet, int size){
|
||||||
|
16
src/hci.h
16
src/hci.h
@ -22,6 +22,10 @@
|
|||||||
// calculate combined ogf/ocf value
|
// calculate combined ogf/ocf value
|
||||||
#define OPCODE(ogf, ocf) (ocf | ogf << 10)
|
#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
|
// packet header lengh
|
||||||
#define HCI_CMD_DATA_PKT_HDR 0x03
|
#define HCI_CMD_DATA_PKT_HDR 0x03
|
||||||
#define HCI_ACL_DATA_PKT_HDR 0x04
|
#define HCI_ACL_DATA_PKT_HDR 0x04
|
||||||
@ -32,7 +36,8 @@
|
|||||||
#define OGF_LINK_CONTROL 0x01
|
#define OGF_LINK_CONTROL 0x01
|
||||||
#define OGF_CONTROLLER_BASEBAND 0x03
|
#define OGF_CONTROLLER_BASEBAND 0x03
|
||||||
#define OGF_INFORMATIONAL_PARAMETERS 0x04
|
#define OGF_INFORMATIONAL_PARAMETERS 0x04
|
||||||
#define OGF_VENDOR_COMMANDS 0x3f
|
#define OGF_BTSTACK 0x3d
|
||||||
|
#define OGF_VENDOR 0x3f
|
||||||
|
|
||||||
// Events from host controller to host
|
// Events from host controller to host
|
||||||
#define HCI_EVENT_INQUIRY_COMPLETE 0x01
|
#define HCI_EVENT_INQUIRY_COMPLETE 0x01
|
||||||
@ -67,7 +72,11 @@
|
|||||||
#define HCI_EVENT_VENDOR_SPECIFIC 0xFF
|
#define HCI_EVENT_VENDOR_SPECIFIC 0xFF
|
||||||
|
|
||||||
// events from BTstack for application/client lib
|
// 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)
|
#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_inquiry_mode;
|
||||||
extern hci_cmd_t hci_write_extended_inquiry_response;
|
extern hci_cmd_t hci_write_extended_inquiry_response;
|
||||||
extern hci_cmd_t hci_write_simple_pairing_mode;
|
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;
|
@ -15,6 +15,7 @@
|
|||||||
#include <strings.h> // bzero
|
#include <strings.h> // bzero
|
||||||
#include <unistd.h> // write
|
#include <unistd.h> // write
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
#include <sys/time.h> // for timestamps
|
#include <sys/time.h> // for timestamps
|
||||||
#include <sys/stat.h> // for mode flags
|
#include <sys/stat.h> // for mode flags
|
||||||
|
|
||||||
@ -40,22 +41,54 @@ static int dump_file = -1;
|
|||||||
static int dump_format;
|
static int dump_format;
|
||||||
static hcidump_hdr header_bluez;
|
static hcidump_hdr header_bluez;
|
||||||
static pktlog_hdr header_packetlogger;
|
static pktlog_hdr header_packetlogger;
|
||||||
|
static char time_string[40];
|
||||||
|
|
||||||
void hci_dump_open(char *filename, hci_dump_format_t format){
|
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_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) {
|
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
|
if (dump_file < 0) return; // not activated yet
|
||||||
|
|
||||||
// get time
|
// get time
|
||||||
struct timeval curr_time;
|
struct timeval curr_time;
|
||||||
|
struct tm* ptm;
|
||||||
gettimeofday(&curr_time, NULL);
|
gettimeofday(&curr_time, NULL);
|
||||||
|
|
||||||
switch (dump_format){
|
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:
|
case HCI_DUMP_BLUEZ:
|
||||||
bt_store_16( (uint8_t *) &header_bluez.len, 0, 1 + len);
|
bt_store_16( (uint8_t *) &header_bluez.len, 0, 1 + len);
|
||||||
header_bluez.in = in;
|
header_bluez.in = in;
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HCI_DUMP_BLUEZ = 0,
|
HCI_DUMP_BLUEZ = 0,
|
||||||
HCI_DUMP_PACKETLOGGER
|
HCI_DUMP_PACKETLOGGER,
|
||||||
|
HCI_DUMP_STDOUT
|
||||||
} hci_dump_format_t;
|
} hci_dump_format_t;
|
||||||
|
|
||||||
void hci_dump_open(char *filename, hci_dump_format_t format);
|
void hci_dump_open(char *filename, hci_dump_format_t format);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user