xref: /btstack/src/hci.c (revision 3091b266fe4659428bc06046eb8edbf8c4f5b0c6)
1 /*
2  *  hci.c
3  *
4  *  Created by Matthias Ringwald on 4/29/09.
5  *
6  */
7 
8 #include <unistd.h>
9 #include <stdarg.h>
10 #include <string.h>
11 #include <stdio.h>
12 #include "hci.h"
13 
14 // calculate combined ogf/ocf value
15 #define OPCODE(ogf, ocf) (ocf | ogf << 10)
16 #define OGF_LINK_CONTROL 0x01
17 #define OGF_CONTROLLER_BASEBAND 0x03
18 
19 hci_cmd_t hci_inquiry = {
20     OPCODE(OGF_LINK_CONTROL, 0x01), "311"
21     // LAP, Inquiry length, Num_responses
22 };
23 
24 hci_cmd_t hci_link_key_request_negative_reply = {
25     OPCODE(OGF_LINK_CONTROL, 0x0c), "B"
26 };
27 
28 hci_cmd_t hci_pin_code_request_reply = {
29     OPCODE(OGF_LINK_CONTROL, 0x0d), "B1P"
30     // BD_ADDR, pin length, PIN: c-string
31 };
32 
33 hci_cmd_t hci_reset = {
34     OPCODE(OGF_CONTROLLER_BASEBAND, 0x03), ""
35 };
36 
37 hci_cmd_t hci_create_connection = {
38     OPCODE(OGF_LINK_CONTROL, 0x05), "B21121"
39     // BD_ADDR, Packet_Type, Page_Scan_Repetition_Mode, Reserved, Clock_Offset, Allow_Role_Switch
40 };
41 
42 hci_cmd_t hci_write_page_timeout = {
43     OPCODE(OGF_CONTROLLER_BASEBAND, 0x18), "2"
44     // Page_Timeout * 0.625 ms
45 };
46 
47 hci_cmd_t hci_write_authentication_enable = {
48     OPCODE(OGF_CONTROLLER_BASEBAND, 0x20), "1"
49     // Authentication_Enable
50 };
51 
52 hci_cmd_t hci_host_buffer_size = {
53     OPCODE(OGF_CONTROLLER_BASEBAND, 0x33), "2122"
54     // Host_ACL_Data_Packet_Length:, Host_Synchronous_Data_Packet_Length:, Host_Total_Num_ACL_Data_Packets:, Host_Total_Num_Synchronous_Data_Packets:
55 };
56 
57 
58 static hci_transport_t * hci_transport;
59 static uint8_t         * hci_cmd_buffer;
60 
61 void hexdump(uint8_t *data, int size){
62     int i;
63     for (i=0; i<size;i++){
64         printf("%02X ", data[i]);
65     }
66     printf("\n");
67 }
68 
69 #if 0
70 static void *hci_daemon_thread(void *arg){
71     printf("HCI Daemon started\n");
72     hci_run(transport, &config);
73     return NULL;
74 }
75 #endif
76 
77 void hci_init(hci_transport_t *transport, void *config){
78 
79     // reference to use transport layer implementation
80     hci_transport = transport;
81 
82     // empty cmd buffer
83     hci_cmd_buffer = malloc(3+255);
84 
85     // open unix socket
86 
87     // wait for connections
88 
89     // enter loop
90 
91     // handle events
92 }
93 
94 int hci_power_control(HCI_POWER_MODE power_mode){
95     return 0;
96 }
97 
98 void hci_run(){
99     while (1) {
100         //  construct file descriptor set to wait for
101         //  select
102 
103         // for each ready file in FD - call handle_data
104         sleep(1);
105     }
106 }
107 
108 int hci_send_cmd(hci_cmd_t *cmd, ...){
109     hci_cmd_buffer[0] = cmd->opcode & 0xff;
110     hci_cmd_buffer[1] = cmd->opcode >> 8;
111     int pos = 3;
112 
113     va_list argptr;
114     va_start(argptr, cmd);
115     const char *format = cmd->format;
116     uint16_t word;
117     uint32_t longword;
118     uint8_t * ptr;
119     while (*format) {
120         switch(*format) {
121             case '1': //  8 bit value
122             case '2': // 16 bit value
123             case 'H': // hci_handle
124                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
125                 hci_cmd_buffer[pos++] = word & 0xff;
126                 if (*format == '2') {
127                     hci_cmd_buffer[pos++] = word >> 8;
128                 } else if (*format == 'H') {
129                     // TODO
130                 }
131                 break;
132             case '3':
133             case '4':
134                 longword = va_arg(argptr, uint32_t);
135                 // longword = va_arg(argptr, int);
136                 hci_cmd_buffer[pos++] = longword;
137                 hci_cmd_buffer[pos++] = longword >> 8;
138                 hci_cmd_buffer[pos++] = longword >> 16;
139                 if (*format == '4'){
140                     hci_cmd_buffer[pos++] = longword >> 24;
141                 }
142                 break;
143             case 'B': // bt-addr
144                 ptr = va_arg(argptr, uint8_t *);
145                 hci_cmd_buffer[pos++] = ptr[5];
146                 hci_cmd_buffer[pos++] = ptr[4];
147                 hci_cmd_buffer[pos++] = ptr[3];
148                 hci_cmd_buffer[pos++] = ptr[2];
149                 hci_cmd_buffer[pos++] = ptr[1];
150                 hci_cmd_buffer[pos++] = ptr[0];
151                 break;
152             case 'P': // c string passed as pascal string with leading 1-byte len
153                 ptr = va_arg(argptr, uint8_t *);
154                 memcpy(&hci_cmd_buffer[pos], ptr, 16);
155                 pos += 16;
156                 break;
157             default:
158                 break;
159         }
160         format++;
161     };
162     va_end(argptr);
163     hci_cmd_buffer[2] = pos - 3;
164     // send packet
165     return hci_transport->send_cmd_packet(hci_cmd_buffer, pos);
166 }