diff --git a/src/hci.c b/src/hci.c index 3d8cb531f..9024f86fe 100644 --- a/src/hci.c +++ b/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){ 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) ) { - uint8_t micro_packet = 100; - hci_stack.event_packet_handler(µ_packet, 1); - return; + // Get Num_HCI_Command_Packets + if (packet[0] == HCI_EVENT_COMMAND_COMPLETE || + packet[0] == HCI_EVENT_COMMAND_STATUS){ + 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 - if (packet[0] == 0x17){ + if (packet[0] == HCI_EVENT_LINK_KEY_REQUEST){ bt_flip_addr(addr, &packet[2]); hci_send_cmd(&hci_link_key_request_negative_reply, &addr); return; } // pin code request - if (packet[0] == 0x16){ + if (packet[0] == HCI_EVENT_PIN_CODE_REQUEST){ bt_flip_addr(addr, &packet[2]); 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 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 hci_stack.event_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 transport->open(config); - - // open unix socket - - // wait for connections - - // enter loop - - // handle events } int hci_power_control(HCI_POWER_MODE power_mode){ return 0; } -void hci_run(){ - - // send hci reset - hci_send_cmd(&hci_reset); - -#if 0 - while (1) { - // construct file descriptor set to wait for - // select - - // for each ready file in FD - call handle_data - sleep(1); +uint32_t hci_run(){ + uint8_t micro_packet; + switch (hci_stack.state){ + case HCI_STATE_INITIALIZING: + if (hci_stack.substate % 2) { + // odd: waiting for command completion + return 0; + } + if (hci_stack.num_cmd_packets == 0) { + // cannot send command yet + return 0; + } + 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){ 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, ...){ uint8_t * hci_cmd_buffer = hci_stack.hci_cmd_buffer; hci_cmd_buffer[0] = cmd->opcode & 0xff; @@ -252,5 +277,6 @@ int hci_send_cmd(hci_cmd_t *cmd, ...){ va_end(argptr); hci_cmd_buffer[2] = pos - 3; // send packet + hci_stack.num_cmd_packets--; return hci_stack.hci_transport->send_cmd_packet(hci_cmd_buffer, pos); } \ No newline at end of file diff --git a/src/hci.h b/src/hci.h index 549239ea1..e80618bb0 100644 --- a/src/hci.h +++ b/src/hci.h @@ -20,7 +20,6 @@ // #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 #define HCI_CMD_DATA_PKT_HDR 0x03 @@ -28,6 +27,44 @@ #define HCI_SCO_DATA_PKT_HDR 0x03 #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. */ @@ -50,6 +87,13 @@ typedef enum { HCI_POWER_ON } HCI_POWER_MODE; +typedef enum { + HCI_STATE_OFF = 0, + HCI_STATE_INITIALIZING, + HCI_STATE_WORKING, + HCI_STATE_HALTING +} HCI_STATE; + typedef struct { uint16_t opcode; const char *format; @@ -63,9 +107,9 @@ typedef struct hci_connection { typedef struct { - hci_transport_t * hci_transport; - uint8_t * hci_cmd_buffer; - hci_connection_t *connections; + hci_transport_t * hci_transport; + uint8_t * hci_cmd_buffer; + hci_connection_t * connections; /* host to controller flow control */ uint8_t num_cmd_packets; @@ -75,6 +119,11 @@ typedef struct { void (*event_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; @@ -88,8 +137,12 @@ void hci_register_acl_packet_handler (void (*handler)(uint8_t *packet, int size // power control 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); @@ -100,8 +153,6 @@ int hci_send_cmd(hci_cmd_t *cmd, ...); // send ACL packet int hci_send_acl_packet(uint8_t *packet, int size); - - // helper extern void bt_store_16(uint8_t *buffer, uint16_t pos, uint16_t value); diff --git a/src/main.c b/src/main.c index ab1f960cd..2676ff3d0 100644 --- a/src/main.c +++ b/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); // 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); } @@ -45,12 +45,12 @@ void event_handler(uint8_t *packet, int size){ 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"); } // connection established -> start L2CAP conection - if (packet[0] == 0x03){ + if (packet[0] == HCI_EVENT_CONNECTION_COMPLETE){ if (packet[2] == 0){ // get new connection handle con_handle = READ_BT_16(packet, 3); @@ -125,9 +125,6 @@ int main (int argc, const char * argv[]) { // init L2CAP l2cap_init(); - // go! - hci_run(); - // get fd for select call int transport_fd = transport->get_fd(); @@ -135,10 +132,15 @@ int main (int argc, const char * argv[]) { fd_set descriptors; FD_ZERO(&descriptors); while (1){ + // handle HCI + hci_run(); + FD_SET(transport_fd, &descriptors); // int ready = select( transport_fd+1, &descriptors, NULL, NULL, NULL); // printf("Ready: %d, isset() = %u\n", ready, FD_ISSET(transport_fd, &descriptors)); + + // handle incoming data from BT module transport->handle_data(); }