xref: /btstack/src/hci.c (revision 02ea9861adb72eb7d0cba8d04d752df236f0e067)
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"
131f504dbdSmatthias.ringwald 
140a974e0cSmatthias.ringwald // calculate combined ogf/ocf value
150a974e0cSmatthias.ringwald #define OPCODE(ogf, ocf) (ocf | ogf << 10)
16*02ea9861Smatthias.ringwald #define OGF_LINK_CONTROL 0x01
17*02ea9861Smatthias.ringwald #define OGF_CONTROLLER_BASEBAND 0x03
1893b8dc03Smatthias.ringwald 
1993b8dc03Smatthias.ringwald hci_cmd_t hci_inquiry = {
20*02ea9861Smatthias.ringwald     OPCODE(OGF_LINK_CONTROL, 0x01), "311" // LAP, Inquiry length, Num_responses
2193b8dc03Smatthias.ringwald };
2293b8dc03Smatthias.ringwald 
2393b8dc03Smatthias.ringwald hci_cmd_t hci_reset = {
24*02ea9861Smatthias.ringwald     OPCODE(OGF_CONTROLLER_BASEBAND, 0x03), ""
25*02ea9861Smatthias.ringwald };
26*02ea9861Smatthias.ringwald 
27*02ea9861Smatthias.ringwald hci_cmd_t hci_create_connection = {
28*02ea9861Smatthias.ringwald     OPCODE(OGF_LINK_CONTROL, 0x05), "B21121"
29*02ea9861Smatthias.ringwald     // BD_ADDR, Packet_Type, Page_Scan_Repetition_Mode, Reserved, Clock_Offset, Allow_Role_Switch
30*02ea9861Smatthias.ringwald };
31*02ea9861Smatthias.ringwald 
32*02ea9861Smatthias.ringwald hci_cmd_t hci_write_page_timeout = {
33*02ea9861Smatthias.ringwald     OPCODE(OGF_CONTROLLER_BASEBAND, 0x18), "2"
34*02ea9861Smatthias.ringwald     // Page_Timeout * 0.625 ms
35*02ea9861Smatthias.ringwald };
36*02ea9861Smatthias.ringwald 
37*02ea9861Smatthias.ringwald hci_cmd_t hci_host_buffer_size = {
38*02ea9861Smatthias.ringwald     OPCODE(OGF_CONTROLLER_BASEBAND, 0x33), "2122"
39*02ea9861Smatthias.ringwald     // Host_ACL_Data_Packet_Length:, Host_Synchronous_Data_Packet_Length:, Host_Total_Num_ACL_Data_Packets:, Host_Total_Num_Synchronous_Data_Packets:
4093b8dc03Smatthias.ringwald };
4193b8dc03Smatthias.ringwald 
4293b8dc03Smatthias.ringwald 
43475c8125Smatthias.ringwald static hci_transport_t * hci_transport;
44*02ea9861Smatthias.ringwald static uint8_t         * hci_cmd_buffer;
45475c8125Smatthias.ringwald 
4656fe0872Smatthias.ringwald void hexdump(uint8_t *data, int size){
4756fe0872Smatthias.ringwald     int i;
4856fe0872Smatthias.ringwald     for (i=0; i<size;i++){
4956fe0872Smatthias.ringwald         printf("%02X ", data[i]);
5056fe0872Smatthias.ringwald     }
5156fe0872Smatthias.ringwald     printf("\n");
5256fe0872Smatthias.ringwald }
5356fe0872Smatthias.ringwald 
5456fe0872Smatthias.ringwald #if 0
5556fe0872Smatthias.ringwald static void *hci_daemon_thread(void *arg){
5656fe0872Smatthias.ringwald     printf("HCI Daemon started\n");
5756fe0872Smatthias.ringwald     hci_run(transport, &config);
5856fe0872Smatthias.ringwald     return NULL;
5956fe0872Smatthias.ringwald }
6056fe0872Smatthias.ringwald #endif
6156fe0872Smatthias.ringwald 
62475c8125Smatthias.ringwald void hci_init(hci_transport_t *transport, void *config){
63475c8125Smatthias.ringwald 
64475c8125Smatthias.ringwald     // reference to use transport layer implementation
65475c8125Smatthias.ringwald     hci_transport = transport;
66475c8125Smatthias.ringwald 
67*02ea9861Smatthias.ringwald     // empty cmd buffer
68*02ea9861Smatthias.ringwald     hci_cmd_buffer = malloc(3+255);
69*02ea9861Smatthias.ringwald 
70475c8125Smatthias.ringwald     // open unix socket
71475c8125Smatthias.ringwald 
72475c8125Smatthias.ringwald     // wait for connections
73475c8125Smatthias.ringwald 
74475c8125Smatthias.ringwald     // enter loop
75475c8125Smatthias.ringwald 
76475c8125Smatthias.ringwald     // handle events
77475c8125Smatthias.ringwald }
78475c8125Smatthias.ringwald 
79475c8125Smatthias.ringwald int hci_power_control(HCI_POWER_MODE power_mode){
80475c8125Smatthias.ringwald     return 0;
81475c8125Smatthias.ringwald }
82475c8125Smatthias.ringwald 
83475c8125Smatthias.ringwald void hci_run(){
84475c8125Smatthias.ringwald     while (1) {
85475c8125Smatthias.ringwald         //  construct file descriptor set to wait for
86475c8125Smatthias.ringwald         //  select
87475c8125Smatthias.ringwald 
88475c8125Smatthias.ringwald         // for each ready file in FD - call handle_data
89475c8125Smatthias.ringwald         sleep(1);
90475c8125Smatthias.ringwald     }
911f504dbdSmatthias.ringwald }
9293b8dc03Smatthias.ringwald 
93*02ea9861Smatthias.ringwald int hci_send_cmd(hci_cmd_t *cmd, ...){
94*02ea9861Smatthias.ringwald     hci_cmd_buffer[0] = cmd->opcode & 0xff;
95*02ea9861Smatthias.ringwald     hci_cmd_buffer[1] = cmd->opcode >> 8;
9693b8dc03Smatthias.ringwald     int pos = 3;
9793b8dc03Smatthias.ringwald 
9893b8dc03Smatthias.ringwald     va_list argptr;
9993b8dc03Smatthias.ringwald     va_start(argptr, cmd);
10093b8dc03Smatthias.ringwald     const char *format = cmd->format;
10193b8dc03Smatthias.ringwald     uint16_t word;
10293b8dc03Smatthias.ringwald     uint32_t longword;
10393b8dc03Smatthias.ringwald     uint8_t * bt_addr;
10493b8dc03Smatthias.ringwald     while (*format) {
10593b8dc03Smatthias.ringwald         switch(*format) {
10693b8dc03Smatthias.ringwald             case '1': //  8 bit value
10793b8dc03Smatthias.ringwald             case '2': // 16 bit value
10893b8dc03Smatthias.ringwald             case 'H': // hci_handle
109554588a5Smatthias.ringwald                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
110*02ea9861Smatthias.ringwald                 hci_cmd_buffer[pos++] = word & 0xff;
11193b8dc03Smatthias.ringwald                 if (*format == '2') {
112*02ea9861Smatthias.ringwald                     hci_cmd_buffer[pos++] = word >> 8;
11393b8dc03Smatthias.ringwald                 } else if (*format == 'H') {
114554588a5Smatthias.ringwald                     // TODO
11593b8dc03Smatthias.ringwald                 }
11693b8dc03Smatthias.ringwald                 break;
11793b8dc03Smatthias.ringwald             case '3':
11893b8dc03Smatthias.ringwald             case '4':
11993b8dc03Smatthias.ringwald                 longword = va_arg(argptr, uint32_t);
12093b8dc03Smatthias.ringwald                 // longword = va_arg(argptr, int);
121*02ea9861Smatthias.ringwald                 hci_cmd_buffer[pos++] = longword;
122*02ea9861Smatthias.ringwald                 hci_cmd_buffer[pos++] = longword >> 8;
123*02ea9861Smatthias.ringwald                 hci_cmd_buffer[pos++] = longword >> 16;
12493b8dc03Smatthias.ringwald                 if (*format == '4'){
125*02ea9861Smatthias.ringwald                     hci_cmd_buffer[pos++] = longword >> 24;
12693b8dc03Smatthias.ringwald                 }
12793b8dc03Smatthias.ringwald                 break;
12893b8dc03Smatthias.ringwald             case 'B': // bt-addr
12993b8dc03Smatthias.ringwald                 bt_addr = va_arg(argptr, uint8_t *);
130*02ea9861Smatthias.ringwald                 hci_cmd_buffer[pos++] = bt_addr[5];
131*02ea9861Smatthias.ringwald                 hci_cmd_buffer[pos++] = bt_addr[4];
132*02ea9861Smatthias.ringwald                 hci_cmd_buffer[pos++] = bt_addr[3];
133*02ea9861Smatthias.ringwald                 hci_cmd_buffer[pos++] = bt_addr[2];
134*02ea9861Smatthias.ringwald                 hci_cmd_buffer[pos++] = bt_addr[1];
135*02ea9861Smatthias.ringwald                 hci_cmd_buffer[pos++] = bt_addr[0];
13693b8dc03Smatthias.ringwald                 break;
13793b8dc03Smatthias.ringwald             default:
13893b8dc03Smatthias.ringwald                 break;
13993b8dc03Smatthias.ringwald         }
14093b8dc03Smatthias.ringwald         format++;
14193b8dc03Smatthias.ringwald     };
14293b8dc03Smatthias.ringwald     va_end(argptr);
143*02ea9861Smatthias.ringwald     hci_cmd_buffer[2] = pos - 3;
144*02ea9861Smatthias.ringwald     // send packet
145*02ea9861Smatthias.ringwald     return hci_transport->send_cmd_packet(hci_cmd_buffer, pos);
14693b8dc03Smatthias.ringwald }