xref: /btstack/src/hci.c (revision d8905019be9ad7442f3ac596d5059ee2e2a49025)
11f504dbdSmatthias.ringwald /*
21f504dbdSmatthias.ringwald  *  hci.c
31f504dbdSmatthias.ringwald  *
41f504dbdSmatthias.ringwald  *  Created by Matthias Ringwald on 4/29/09.
51f504dbdSmatthias.ringwald  *
61f504dbdSmatthias.ringwald  */
71f504dbdSmatthias.ringwald 
8475c8125Smatthias.ringwald #include <unistd.h>
993b8dc03Smatthias.ringwald #include <stdarg.h>
1093b8dc03Smatthias.ringwald #include <string.h>
1156fe0872Smatthias.ringwald #include <stdio.h>
121f504dbdSmatthias.ringwald #include "hci.h"
13*d8905019Smatthias.ringwald #include "hci_dump.h"
1493b8dc03Smatthias.ringwald 
1516833f0aSmatthias.ringwald // the stack is here
1616833f0aSmatthias.ringwald static hci_stack_t       hci_stack;
1716833f0aSmatthias.ringwald 
18475c8125Smatthias.ringwald 
1943625864Smatthias.ringwald void bt_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){
208b658ebcSmatthias.ringwald     buffer[pos++] = value;
218b658ebcSmatthias.ringwald     buffer[pos++] = value >> 8;
228b658ebcSmatthias.ringwald }
238b658ebcSmatthias.ringwald 
248b658ebcSmatthias.ringwald void bt_store_32(uint8_t *buffer, uint16_t pos, uint32_t value){
258b658ebcSmatthias.ringwald     buffer[pos++] = value;
268b658ebcSmatthias.ringwald     buffer[pos++] = value >> 8;
278b658ebcSmatthias.ringwald     buffer[pos++] = value >> 16;
288b658ebcSmatthias.ringwald     buffer[pos++] = value >> 24;
2943625864Smatthias.ringwald }
3043625864Smatthias.ringwald 
311281a47eSmatthias.ringwald void bt_flip_addr(bd_addr_t dest, bd_addr_t src){
321281a47eSmatthias.ringwald     dest[0] = src[5];
331281a47eSmatthias.ringwald     dest[1] = src[4];
341281a47eSmatthias.ringwald     dest[2] = src[3];
351281a47eSmatthias.ringwald     dest[3] = src[2];
361281a47eSmatthias.ringwald     dest[4] = src[1];
371281a47eSmatthias.ringwald     dest[5] = src[0];
381281a47eSmatthias.ringwald }
391281a47eSmatthias.ringwald 
4002582713Smatthias.ringwald void hexdump(void *data, int size){
4156fe0872Smatthias.ringwald     int i;
4256fe0872Smatthias.ringwald     for (i=0; i<size;i++){
4302582713Smatthias.ringwald         printf("%02X ", ((uint8_t *)data)[i]);
4456fe0872Smatthias.ringwald     }
4556fe0872Smatthias.ringwald     printf("\n");
4656fe0872Smatthias.ringwald }
4756fe0872Smatthias.ringwald 
4816833f0aSmatthias.ringwald /**
4997addcc5Smatthias.ringwald  * Linked link list
5097addcc5Smatthias.ringwald  */
5197addcc5Smatthias.ringwald 
5297addcc5Smatthias.ringwald /**
5397addcc5Smatthias.ringwald  * get link for given address
5497addcc5Smatthias.ringwald  *
5597addcc5Smatthias.ringwald  * @return connection OR NULL, if not found
5697addcc5Smatthias.ringwald  */
57145be03fSmatthias.ringwald #if 0
5897addcc5Smatthias.ringwald static hci_connection_t *link_for_addr(bd_addr_t addr){
5997addcc5Smatthias.ringwald     return NULL;
6097addcc5Smatthias.ringwald }
61145be03fSmatthias.ringwald #endif
6297addcc5Smatthias.ringwald 
6397addcc5Smatthias.ringwald /**
6416833f0aSmatthias.ringwald  * Handler called by HCI transport
6516833f0aSmatthias.ringwald  */
661cd208adSmatthias.ringwald static void dummy_handler(uint8_t *packet, uint16_t size){
6716833f0aSmatthias.ringwald }
6816833f0aSmatthias.ringwald 
6916833f0aSmatthias.ringwald static void acl_handler(uint8_t *packet, int size){
7016833f0aSmatthias.ringwald     hci_stack.acl_packet_handler(packet, size);
7194ab26f8Smatthias.ringwald 
7294ab26f8Smatthias.ringwald     // execute main loop
7394ab26f8Smatthias.ringwald     hci_run();
7416833f0aSmatthias.ringwald }
7522909952Smatthias.ringwald 
7616833f0aSmatthias.ringwald static void event_handler(uint8_t *packet, int size){
771281a47eSmatthias.ringwald     bd_addr_t addr;
7822909952Smatthias.ringwald 
793429f56bSmatthias.ringwald     // Get Num_HCI_Command_Packets
803429f56bSmatthias.ringwald     if (packet[0] == HCI_EVENT_COMMAND_COMPLETE ||
813429f56bSmatthias.ringwald         packet[0] == HCI_EVENT_COMMAND_STATUS){
823429f56bSmatthias.ringwald         hci_stack.num_cmd_packets = packet[2];
8322909952Smatthias.ringwald     }
8422909952Smatthias.ringwald 
853429f56bSmatthias.ringwald     // handle BT initialization
863429f56bSmatthias.ringwald     if (hci_stack.state == HCI_STATE_INITIALIZING){
877301ad89Smatthias.ringwald         // handle H4 synchronization loss on restart
887301ad89Smatthias.ringwald         // if (hci_stack.substate == 1 && packet[0] == HCI_EVENT_HARDWARE_ERROR){
897301ad89Smatthias.ringwald         //    hci_stack.substate = 0;
907301ad89Smatthias.ringwald         // }
917301ad89Smatthias.ringwald         // handle normal init sequence
923429f56bSmatthias.ringwald         if (hci_stack.substate % 2){
933429f56bSmatthias.ringwald             // odd: waiting for event
943429f56bSmatthias.ringwald             if (packet[0] == HCI_EVENT_COMMAND_COMPLETE){
953429f56bSmatthias.ringwald                 hci_stack.substate++;
963429f56bSmatthias.ringwald             }
973429f56bSmatthias.ringwald         }
9822909952Smatthias.ringwald     }
9922909952Smatthias.ringwald 
1001281a47eSmatthias.ringwald     // link key request
1013429f56bSmatthias.ringwald     if (packet[0] == HCI_EVENT_LINK_KEY_REQUEST){
1021281a47eSmatthias.ringwald         bt_flip_addr(addr, &packet[2]);
1031281a47eSmatthias.ringwald         hci_send_cmd(&hci_link_key_request_negative_reply, &addr);
1041281a47eSmatthias.ringwald         return;
1051281a47eSmatthias.ringwald     }
1061281a47eSmatthias.ringwald 
1071281a47eSmatthias.ringwald     // pin code request
1083429f56bSmatthias.ringwald     if (packet[0] == HCI_EVENT_PIN_CODE_REQUEST){
1091281a47eSmatthias.ringwald         bt_flip_addr(addr, &packet[2]);
1101281a47eSmatthias.ringwald         hci_send_cmd(&hci_pin_code_request_reply, &addr, 4, "1234");
1111281a47eSmatthias.ringwald     }
1121281a47eSmatthias.ringwald 
11316833f0aSmatthias.ringwald     hci_stack.event_packet_handler(packet, size);
11494ab26f8Smatthias.ringwald 
11594ab26f8Smatthias.ringwald 	// execute main loop
11694ab26f8Smatthias.ringwald 	hci_run();
11716833f0aSmatthias.ringwald }
11816833f0aSmatthias.ringwald 
11916833f0aSmatthias.ringwald /** Register L2CAP handlers */
1201cd208adSmatthias.ringwald void hci_register_event_packet_handler(void (*handler)(uint8_t *packet, uint16_t size)){
12116833f0aSmatthias.ringwald     hci_stack.event_packet_handler = handler;
12216833f0aSmatthias.ringwald }
1231cd208adSmatthias.ringwald void hci_register_acl_packet_handler  (void (*handler)(uint8_t *packet, uint16_t size)){
12416833f0aSmatthias.ringwald     hci_stack.acl_packet_handler = handler;
12516833f0aSmatthias.ringwald }
12616833f0aSmatthias.ringwald 
1277301ad89Smatthias.ringwald static int null_control_function(void *config){
1287301ad89Smatthias.ringwald     return 0;
1297301ad89Smatthias.ringwald }
1307301ad89Smatthias.ringwald static const char * null_control_name(void *config){
1317301ad89Smatthias.ringwald     return "Hardware unknown";
1327301ad89Smatthias.ringwald }
1337301ad89Smatthias.ringwald 
1347301ad89Smatthias.ringwald static bt_control_t null_control = {
1357301ad89Smatthias.ringwald     null_control_function,
1367301ad89Smatthias.ringwald     null_control_function,
1377301ad89Smatthias.ringwald     null_control_function,
1387301ad89Smatthias.ringwald     null_control_name
1397301ad89Smatthias.ringwald };
1407301ad89Smatthias.ringwald 
14111e23e5fSmatthias.ringwald void hci_init(hci_transport_t *transport, void *config, bt_control_t *control){
142475c8125Smatthias.ringwald 
143475c8125Smatthias.ringwald     // reference to use transport layer implementation
14416833f0aSmatthias.ringwald     hci_stack.hci_transport = transport;
145475c8125Smatthias.ringwald 
14611e23e5fSmatthias.ringwald     // references to used control implementation
1477301ad89Smatthias.ringwald     if (control) {
14811e23e5fSmatthias.ringwald         hci_stack.control = control;
1497301ad89Smatthias.ringwald     } else {
1507301ad89Smatthias.ringwald         hci_stack.control = &null_control;
1517301ad89Smatthias.ringwald     }
15211e23e5fSmatthias.ringwald 
15311e23e5fSmatthias.ringwald     // reference to used config
15411e23e5fSmatthias.ringwald     hci_stack.config = config;
15511e23e5fSmatthias.ringwald 
15602ea9861Smatthias.ringwald     // empty cmd buffer
15716833f0aSmatthias.ringwald     hci_stack.hci_cmd_buffer = malloc(3+255);
15816833f0aSmatthias.ringwald 
15916833f0aSmatthias.ringwald     // higher level handler
16016833f0aSmatthias.ringwald     hci_stack.event_packet_handler = dummy_handler;
16116833f0aSmatthias.ringwald     hci_stack.acl_packet_handler = dummy_handler;
16216833f0aSmatthias.ringwald 
16316833f0aSmatthias.ringwald     // register packet handlers with transport
16416833f0aSmatthias.ringwald     transport->register_event_packet_handler( event_handler);
16516833f0aSmatthias.ringwald     transport->register_acl_packet_handler( acl_handler);
166475c8125Smatthias.ringwald }
167475c8125Smatthias.ringwald 
168475c8125Smatthias.ringwald int hci_power_control(HCI_POWER_MODE power_mode){
16911e23e5fSmatthias.ringwald     if (power_mode == HCI_POWER_ON) {
1707301ad89Smatthias.ringwald 
1717301ad89Smatthias.ringwald         // set up state machine
1727301ad89Smatthias.ringwald         hci_stack.num_cmd_packets = 1; // assume that one cmd can be sent
1737301ad89Smatthias.ringwald         hci_stack.state = HCI_STATE_INITIALIZING;
1747301ad89Smatthias.ringwald         hci_stack.substate = 0;
1757301ad89Smatthias.ringwald 
1767301ad89Smatthias.ringwald         // power on
17711e23e5fSmatthias.ringwald         hci_stack.control->on(hci_stack.config);
1787301ad89Smatthias.ringwald 
1797301ad89Smatthias.ringwald         // open low-level device
1807301ad89Smatthias.ringwald         hci_stack.hci_transport->open(hci_stack.config);
1817301ad89Smatthias.ringwald 
18211e23e5fSmatthias.ringwald     } else if (power_mode == HCI_POWER_OFF){
1837301ad89Smatthias.ringwald 
1847301ad89Smatthias.ringwald         // close low-level device
1857301ad89Smatthias.ringwald         hci_stack.hci_transport->close(hci_stack.config);
1867301ad89Smatthias.ringwald 
1877301ad89Smatthias.ringwald         // power off
18811e23e5fSmatthias.ringwald         hci_stack.control->off(hci_stack.config);
18911e23e5fSmatthias.ringwald     }
19068d92d03Smatthias.ringwald 
19168d92d03Smatthias.ringwald 	// trigger next/first action
19268d92d03Smatthias.ringwald 	hci_run();
19368d92d03Smatthias.ringwald 
194475c8125Smatthias.ringwald     return 0;
195475c8125Smatthias.ringwald }
196475c8125Smatthias.ringwald 
1973429f56bSmatthias.ringwald uint32_t hci_run(){
1983429f56bSmatthias.ringwald     uint8_t micro_packet;
1993429f56bSmatthias.ringwald     switch (hci_stack.state){
2003429f56bSmatthias.ringwald         case HCI_STATE_INITIALIZING:
2013429f56bSmatthias.ringwald             if (hci_stack.substate % 2) {
2023429f56bSmatthias.ringwald                 // odd: waiting for command completion
2033429f56bSmatthias.ringwald                 return 0;
2043429f56bSmatthias.ringwald             }
2053429f56bSmatthias.ringwald             if (hci_stack.num_cmd_packets == 0) {
2063429f56bSmatthias.ringwald                 // cannot send command yet
2073429f56bSmatthias.ringwald                 return 0;
2083429f56bSmatthias.ringwald             }
2093429f56bSmatthias.ringwald             switch (hci_stack.substate/2){
2103429f56bSmatthias.ringwald                 case 0:
21122909952Smatthias.ringwald                     hci_send_cmd(&hci_reset);
2123429f56bSmatthias.ringwald                     break;
2133429f56bSmatthias.ringwald 				case 1:
214f432a6ddSmatthias.ringwald 					hci_send_cmd(&hci_read_bd_addr);
215f432a6ddSmatthias.ringwald 					break;
216f432a6ddSmatthias.ringwald                 case 2:
2173429f56bSmatthias.ringwald                     // ca. 15 sec
2183429f56bSmatthias.ringwald                     hci_send_cmd(&hci_write_page_timeout, 0x6000);
2193429f56bSmatthias.ringwald                     break;
220f432a6ddSmatthias.ringwald 				case 3:
221bd67ef2fSmatthias.ringwald 					hci_send_cmd(&hci_write_scan_enable, 3); // 3 inq scan + page scan
222f432a6ddSmatthias.ringwald 					break;
223f432a6ddSmatthias.ringwald                 case 4:
2243429f56bSmatthias.ringwald                     // done.
2253429f56bSmatthias.ringwald                     hci_stack.state = HCI_STATE_WORKING;
2268adf0ddaSmatthias.ringwald                     micro_packet = HCI_EVENT_BTSTACK_WORKING;
2273429f56bSmatthias.ringwald                     hci_stack.event_packet_handler(&micro_packet, 1);
2283429f56bSmatthias.ringwald                     break;
2293429f56bSmatthias.ringwald                 default:
2303429f56bSmatthias.ringwald                     break;
231475c8125Smatthias.ringwald             }
2323429f56bSmatthias.ringwald             hci_stack.substate++;
2333429f56bSmatthias.ringwald             break;
2343429f56bSmatthias.ringwald         default:
2353429f56bSmatthias.ringwald             break;
2361f504dbdSmatthias.ringwald     }
23793b8dc03Smatthias.ringwald 
2383429f56bSmatthias.ringwald     // don't check for timetous yet
2393429f56bSmatthias.ringwald     return 0;
2403429f56bSmatthias.ringwald }
24116833f0aSmatthias.ringwald 
24216833f0aSmatthias.ringwald 
24343625864Smatthias.ringwald int hci_send_acl_packet(uint8_t *packet, int size){
24416833f0aSmatthias.ringwald     return hci_stack.hci_transport->send_acl_packet(packet, size);
24543625864Smatthias.ringwald }
24643625864Smatthias.ringwald 
24731452debSmatthias.ringwald int hci_send_cmd_packet(uint8_t *packet, int size){
24831452debSmatthias.ringwald     if (READ_CMD_OGF(packet) != OGF_BTSTACK) {
24931452debSmatthias.ringwald         hci_stack.num_cmd_packets--;
25031452debSmatthias.ringwald         return hci_stack.hci_transport->send_cmd_packet(packet, size);
25131452debSmatthias.ringwald     }
25231452debSmatthias.ringwald 
25331452debSmatthias.ringwald     hci_dump_packet( HCI_COMMAND_DATA_PACKET, 1, packet, size);
25431452debSmatthias.ringwald 
2558adf0ddaSmatthias.ringwald     // BTstack internal commands
2568adf0ddaSmatthias.ringwald     uint8_t event[3];
2578adf0ddaSmatthias.ringwald     switch (READ_CMD_OCF(packet)){
2588adf0ddaSmatthias.ringwald         case HCI_BTSTACK_GET_STATE:
2598adf0ddaSmatthias.ringwald             event[0] = HCI_EVENT_BTSTACK_STATE;
2608adf0ddaSmatthias.ringwald             event[1] = 1;
2618adf0ddaSmatthias.ringwald             event[2] = hci_stack.state;
26231452debSmatthias.ringwald             hci_dump_packet( HCI_EVENT_PACKET, 0, event, 3);
2638adf0ddaSmatthias.ringwald             hci_stack.event_packet_handler(event, 3);
2648adf0ddaSmatthias.ringwald             break;
2658adf0ddaSmatthias.ringwald         default:
2668adf0ddaSmatthias.ringwald             // TODO log into hci dump as vendor specific"event"
2678adf0ddaSmatthias.ringwald             printf("Error: command %u not implemented\n:", READ_CMD_OCF(packet));
2688adf0ddaSmatthias.ringwald             break;
2698adf0ddaSmatthias.ringwald     }
2708adf0ddaSmatthias.ringwald     return 0;
2718adf0ddaSmatthias.ringwald }
2728adf0ddaSmatthias.ringwald 
2731cd208adSmatthias.ringwald 
2741cd208adSmatthias.ringwald /**
2751cd208adSmatthias.ringwald  * pre: numcmds >= 0 - it's allowed to send a command to the controller
2761cd208adSmatthias.ringwald  */
2771cd208adSmatthias.ringwald int hci_send_cmd(hci_cmd_t *cmd, ...){
2781cd208adSmatthias.ringwald     va_list argptr;
2791cd208adSmatthias.ringwald     va_start(argptr, cmd);
2801cd208adSmatthias.ringwald     uint8_t * hci_cmd_buffer = hci_stack.hci_cmd_buffer;
2811cd208adSmatthias.ringwald     uint16_t size = hci_create_cmd_internal(hci_stack.hci_cmd_buffer, cmd, argptr);
2821cd208adSmatthias.ringwald     va_end(argptr);
2831cd208adSmatthias.ringwald     return hci_send_cmd_packet(hci_cmd_buffer, size);
28493b8dc03Smatthias.ringwald }