mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-16 08:42:28 +00:00
track num_cmd_packets. use state machine for BT initialization.
This commit is contained in:
parent
1281a47e99
commit
3429f56b3a
98
src/hci.c
98
src/hci.c
@ -101,28 +101,32 @@ static void acl_handler(uint8_t *packet, int size){
|
|||||||
|
|
||||||
static void event_handler(uint8_t *packet, int size){
|
static void event_handler(uint8_t *packet, int size){
|
||||||
bd_addr_t addr;
|
bd_addr_t addr;
|
||||||
|
|
||||||
if ( COMMAND_COMPLETE_EVENT(packet, hci_reset) ) {
|
|
||||||
// reset done, write page timeout
|
|
||||||
hci_send_cmd(&hci_write_page_timeout, 0x6000); // ca. 15 sec
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_page_timeout) ) {
|
// Get Num_HCI_Command_Packets
|
||||||
uint8_t micro_packet = 100;
|
if (packet[0] == HCI_EVENT_COMMAND_COMPLETE ||
|
||||||
hci_stack.event_packet_handler(µ_packet, 1);
|
packet[0] == HCI_EVENT_COMMAND_STATUS){
|
||||||
return;
|
hci_stack.num_cmd_packets = packet[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle BT initialization
|
||||||
|
if (hci_stack.state == HCI_STATE_INITIALIZING){
|
||||||
|
if (hci_stack.substate % 2){
|
||||||
|
// odd: waiting for event
|
||||||
|
if (packet[0] == HCI_EVENT_COMMAND_COMPLETE){
|
||||||
|
hci_stack.substate++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// link key request
|
// link key request
|
||||||
if (packet[0] == 0x17){
|
if (packet[0] == HCI_EVENT_LINK_KEY_REQUEST){
|
||||||
bt_flip_addr(addr, &packet[2]);
|
bt_flip_addr(addr, &packet[2]);
|
||||||
hci_send_cmd(&hci_link_key_request_negative_reply, &addr);
|
hci_send_cmd(&hci_link_key_request_negative_reply, &addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pin code request
|
// pin code request
|
||||||
if (packet[0] == 0x16){
|
if (packet[0] == HCI_EVENT_PIN_CODE_REQUEST){
|
||||||
bt_flip_addr(addr, &packet[2]);
|
bt_flip_addr(addr, &packet[2]);
|
||||||
hci_send_cmd(&hci_pin_code_request_reply, &addr, 4, "1234");
|
hci_send_cmd(&hci_pin_code_request_reply, &addr, 4, "1234");
|
||||||
}
|
}
|
||||||
@ -146,6 +150,11 @@ void hci_init(hci_transport_t *transport, void *config){
|
|||||||
// empty cmd buffer
|
// empty cmd buffer
|
||||||
hci_stack.hci_cmd_buffer = malloc(3+255);
|
hci_stack.hci_cmd_buffer = malloc(3+255);
|
||||||
|
|
||||||
|
// set up state
|
||||||
|
hci_stack.num_cmd_packets = 1; // assume that one cmd can be sent
|
||||||
|
hci_stack.state = HCI_STATE_INITIALIZING;
|
||||||
|
hci_stack.substate = 0;
|
||||||
|
|
||||||
// higher level handler
|
// higher level handler
|
||||||
hci_stack.event_packet_handler = dummy_handler;
|
hci_stack.event_packet_handler = dummy_handler;
|
||||||
hci_stack.acl_packet_handler = dummy_handler;
|
hci_stack.acl_packet_handler = dummy_handler;
|
||||||
@ -156,44 +165,60 @@ void hci_init(hci_transport_t *transport, void *config){
|
|||||||
|
|
||||||
// open low-level device
|
// open low-level device
|
||||||
transport->open(config);
|
transport->open(config);
|
||||||
|
|
||||||
// open unix socket
|
|
||||||
|
|
||||||
// wait for connections
|
|
||||||
|
|
||||||
// enter loop
|
|
||||||
|
|
||||||
// handle events
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int hci_power_control(HCI_POWER_MODE power_mode){
|
int hci_power_control(HCI_POWER_MODE power_mode){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hci_run(){
|
uint32_t hci_run(){
|
||||||
|
uint8_t micro_packet;
|
||||||
// send hci reset
|
switch (hci_stack.state){
|
||||||
hci_send_cmd(&hci_reset);
|
case HCI_STATE_INITIALIZING:
|
||||||
|
if (hci_stack.substate % 2) {
|
||||||
#if 0
|
// odd: waiting for command completion
|
||||||
while (1) {
|
return 0;
|
||||||
// construct file descriptor set to wait for
|
}
|
||||||
// select
|
if (hci_stack.num_cmd_packets == 0) {
|
||||||
|
// cannot send command yet
|
||||||
// for each ready file in FD - call handle_data
|
return 0;
|
||||||
sleep(1);
|
}
|
||||||
|
switch (hci_stack.substate/2){
|
||||||
|
case 0:
|
||||||
|
hci_send_cmd(&hci_reset);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// ca. 15 sec
|
||||||
|
hci_send_cmd(&hci_write_page_timeout, 0x6000);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// done.
|
||||||
|
hci_stack.state = HCI_STATE_WORKING;
|
||||||
|
micro_packet = BTSTACK_EVENT_HCI_WORKING;
|
||||||
|
hci_stack.event_packet_handler(µ_packet, 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hci_stack.substate++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
// don't check for timetous yet
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
return hci_stack.hci_transport->send_acl_packet(packet, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pre: numcmds >= 0 - it's allowed to send a command to the controller
|
||||||
|
*/
|
||||||
int hci_send_cmd(hci_cmd_t *cmd, ...){
|
int hci_send_cmd(hci_cmd_t *cmd, ...){
|
||||||
uint8_t * hci_cmd_buffer = hci_stack.hci_cmd_buffer;
|
uint8_t * hci_cmd_buffer = hci_stack.hci_cmd_buffer;
|
||||||
hci_cmd_buffer[0] = cmd->opcode & 0xff;
|
hci_cmd_buffer[0] = cmd->opcode & 0xff;
|
||||||
@ -252,5 +277,6 @@ int hci_send_cmd(hci_cmd_t *cmd, ...){
|
|||||||
va_end(argptr);
|
va_end(argptr);
|
||||||
hci_cmd_buffer[2] = pos - 3;
|
hci_cmd_buffer[2] = pos - 3;
|
||||||
// send packet
|
// send packet
|
||||||
|
hci_stack.num_cmd_packets--;
|
||||||
return hci_stack.hci_transport->send_cmd_packet(hci_cmd_buffer, pos);
|
return hci_stack.hci_transport->send_cmd_packet(hci_cmd_buffer, pos);
|
||||||
}
|
}
|
67
src/hci.h
67
src/hci.h
@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
// #define STORE_BT_16( buffer, pos, value ) { buffer[pos] = (value) & 0xff; buffer[pos+1] = (value) >> 8; }
|
// #define STORE_BT_16( buffer, pos, value ) { buffer[pos] = (value) & 0xff; buffer[pos+1] = (value) >> 8; }
|
||||||
|
|
||||||
#define COMMAND_COMPLETE_EVENT(event,cmd) ( event[0] == 0x0e && READ_BT_16(event,3) == cmd.opcode)
|
|
||||||
|
|
||||||
// packet headers
|
// packet headers
|
||||||
#define HCI_CMD_DATA_PKT_HDR 0x03
|
#define HCI_CMD_DATA_PKT_HDR 0x03
|
||||||
@ -28,6 +27,44 @@
|
|||||||
#define HCI_SCO_DATA_PKT_HDR 0x03
|
#define HCI_SCO_DATA_PKT_HDR 0x03
|
||||||
#define HCI_EVENT_PKT_HDR 0x02
|
#define HCI_EVENT_PKT_HDR 0x02
|
||||||
|
|
||||||
|
|
||||||
|
// Events from host controller to host
|
||||||
|
#define HCI_EVENT_INQUIRY_COMPLETE 0x01
|
||||||
|
#define HCI_EVENT_INQUIRY_RESULT 0x02
|
||||||
|
#define HCI_EVENT_CONNECTION_COMPLETE 0x03
|
||||||
|
#define HCI_EVENT_CONNECTION_REQUEST 0x04
|
||||||
|
#define HCI_EVENT_DISCONNECTION_COMPLETE 0x05
|
||||||
|
#define HCI_EVENT_AUTHENTICATION_COMPLETE_EVENT 0x06
|
||||||
|
#define HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE 0x07
|
||||||
|
#define HCI_EVENT_ENCRIPTION_CHANGE 0x08
|
||||||
|
#define HCI_EVENT_CHANGE_CONNECTION_LINK_KEY_COMPLETE 0x09
|
||||||
|
#define HCI_EVENT_MASTER_LINK_KEY_COMPLETE 0x0A
|
||||||
|
#define HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE 0x0B
|
||||||
|
#define HCI_EVENT_READ_REMOTE_VERSION_INFORMATION_COMPLETE 0x0C
|
||||||
|
#define HCI_EVENT_QOS_SETUP_COMPLETE 0x0D
|
||||||
|
#define HCI_EVENT_COMMAND_COMPLETE 0x0E
|
||||||
|
#define HCI_EVENT_COMMAND_STATUS 0x0F
|
||||||
|
#define HCI_EVENT_HARDWARE_ERROR 0x10
|
||||||
|
#define HCI_EVENT_FLUSH_OCCURED 0x11
|
||||||
|
#define HCI_EVENT_ROLE_CHANGE 0x12
|
||||||
|
#define HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS 0x13
|
||||||
|
#define HCI_EVENT_MODE_CHANGE_EVENT 0x14
|
||||||
|
#define HCI_EVENT_RETURN_LINK_KEYS 0x15
|
||||||
|
#define HCI_EVENT_PIN_CODE_REQUEST 0x16
|
||||||
|
#define HCI_EVENT_LINK_KEY_REQUEST 0x17
|
||||||
|
#define HCI_EVENT_LINK_KEY_NOTIFICATION 0x18
|
||||||
|
#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_INQUIRY_RESULT_WITH_RSSI 0x22
|
||||||
|
#define HCI_EVENT_VENDOR_SPECIFIC 0xFF
|
||||||
|
|
||||||
|
// events from BTstack for application/client lib
|
||||||
|
#define BTSTACK_EVENT_HCI_WORKING 0x80
|
||||||
|
|
||||||
|
#define COMMAND_COMPLETE_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_COMPLETE && READ_BT_16(event,3) == cmd.opcode)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Length of a bluetooth device address.
|
* @brief Length of a bluetooth device address.
|
||||||
*/
|
*/
|
||||||
@ -50,6 +87,13 @@ typedef enum {
|
|||||||
HCI_POWER_ON
|
HCI_POWER_ON
|
||||||
} HCI_POWER_MODE;
|
} HCI_POWER_MODE;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HCI_STATE_OFF = 0,
|
||||||
|
HCI_STATE_INITIALIZING,
|
||||||
|
HCI_STATE_WORKING,
|
||||||
|
HCI_STATE_HALTING
|
||||||
|
} HCI_STATE;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t opcode;
|
uint16_t opcode;
|
||||||
const char *format;
|
const char *format;
|
||||||
@ -63,9 +107,9 @@ typedef struct hci_connection {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
hci_transport_t * hci_transport;
|
hci_transport_t * hci_transport;
|
||||||
uint8_t * hci_cmd_buffer;
|
uint8_t * hci_cmd_buffer;
|
||||||
hci_connection_t *connections;
|
hci_connection_t * connections;
|
||||||
|
|
||||||
/* host to controller flow control */
|
/* host to controller flow control */
|
||||||
uint8_t num_cmd_packets;
|
uint8_t num_cmd_packets;
|
||||||
@ -75,6 +119,11 @@ typedef struct {
|
|||||||
void (*event_packet_handler)(uint8_t *packet, int size);
|
void (*event_packet_handler)(uint8_t *packet, int size);
|
||||||
void (*acl_packet_handler) (uint8_t *packet, int size);
|
void (*acl_packet_handler) (uint8_t *packet, int size);
|
||||||
|
|
||||||
|
/* hci state machine */
|
||||||
|
HCI_STATE state;
|
||||||
|
uint8_t substate;
|
||||||
|
uint8_t cmds_ready;
|
||||||
|
|
||||||
} hci_stack_t;
|
} hci_stack_t;
|
||||||
|
|
||||||
|
|
||||||
@ -88,8 +137,12 @@ void hci_register_acl_packet_handler (void (*handler)(uint8_t *packet, int size
|
|||||||
// power control
|
// power control
|
||||||
int hci_power_control(HCI_POWER_MODE mode);
|
int hci_power_control(HCI_POWER_MODE mode);
|
||||||
|
|
||||||
// run the hci daemon loop
|
/**
|
||||||
void hci_run();
|
* run the hci daemon loop once
|
||||||
|
*
|
||||||
|
* @return 0 or next timeout
|
||||||
|
*/
|
||||||
|
uint32_t hci_run();
|
||||||
|
|
||||||
//
|
//
|
||||||
void hexdump(uint8_t *data, int size);
|
void hexdump(uint8_t *data, int size);
|
||||||
@ -100,8 +153,6 @@ int hci_send_cmd(hci_cmd_t *cmd, ...);
|
|||||||
// send ACL packet
|
// send ACL packet
|
||||||
int hci_send_acl_packet(uint8_t *packet, int size);
|
int hci_send_acl_packet(uint8_t *packet, int size);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// helper
|
// helper
|
||||||
extern void bt_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);
|
extern void bt_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);
|
||||||
|
|
||||||
|
14
src/main.c
14
src/main.c
@ -36,7 +36,7 @@ void event_handler(uint8_t *packet, int size){
|
|||||||
// printf("Event type: %x, opcode: %x, other %x\n", packet[0], packet[3] | packet[4] << 8);
|
// printf("Event type: %x, opcode: %x, other %x\n", packet[0], packet[3] | packet[4] << 8);
|
||||||
|
|
||||||
// bt stack activated, set authentication enabled
|
// bt stack activated, set authentication enabled
|
||||||
if (packet[0] == 100) {
|
if (packet[0] == BTSTACK_EVENT_HCI_WORKING) {
|
||||||
hci_send_cmd(&hci_write_authentication_enable, 1);
|
hci_send_cmd(&hci_write_authentication_enable, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,12 +45,12 @@ void event_handler(uint8_t *packet, int size){
|
|||||||
hci_send_cmd(&hci_create_connection, &addr, 0x18, 0, 0, 0, 0);
|
hci_send_cmd(&hci_create_connection, &addr, 0x18, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet[0] == 0x16){
|
if (packet[0] == HCI_EVENT_PIN_CODE_REQUEST){
|
||||||
printf("Please enter PIN 1234 on remote device\n");
|
printf("Please enter PIN 1234 on remote device\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// connection established -> start L2CAP conection
|
// connection established -> start L2CAP conection
|
||||||
if (packet[0] == 0x03){
|
if (packet[0] == HCI_EVENT_CONNECTION_COMPLETE){
|
||||||
if (packet[2] == 0){
|
if (packet[2] == 0){
|
||||||
// get new connection handle
|
// get new connection handle
|
||||||
con_handle = READ_BT_16(packet, 3);
|
con_handle = READ_BT_16(packet, 3);
|
||||||
@ -125,9 +125,6 @@ int main (int argc, const char * argv[]) {
|
|||||||
// init L2CAP
|
// init L2CAP
|
||||||
l2cap_init();
|
l2cap_init();
|
||||||
|
|
||||||
// go!
|
|
||||||
hci_run();
|
|
||||||
|
|
||||||
// get fd for select call
|
// get fd for select call
|
||||||
int transport_fd = transport->get_fd();
|
int transport_fd = transport->get_fd();
|
||||||
|
|
||||||
@ -135,10 +132,15 @@ int main (int argc, const char * argv[]) {
|
|||||||
fd_set descriptors;
|
fd_set descriptors;
|
||||||
FD_ZERO(&descriptors);
|
FD_ZERO(&descriptors);
|
||||||
while (1){
|
while (1){
|
||||||
|
// handle HCI
|
||||||
|
hci_run();
|
||||||
|
|
||||||
FD_SET(transport_fd, &descriptors);
|
FD_SET(transport_fd, &descriptors);
|
||||||
// int ready =
|
// int ready =
|
||||||
select( transport_fd+1, &descriptors, NULL, NULL, NULL);
|
select( transport_fd+1, &descriptors, NULL, NULL, NULL);
|
||||||
// printf("Ready: %d, isset() = %u\n", ready, FD_ISSET(transport_fd, &descriptors));
|
// printf("Ready: %d, isset() = %u\n", ready, FD_ISSET(transport_fd, &descriptors));
|
||||||
|
|
||||||
|
// handle incoming data from BT module
|
||||||
transport->handle_data();
|
transport->handle_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user