xref: /btstack/src/hci.h (revision 945627e4425bd05a805f318fc97408579184541a)
11f504dbdSmatthias.ringwald /*
21f504dbdSmatthias.ringwald  *  hci.h
31f504dbdSmatthias.ringwald  *
41f504dbdSmatthias.ringwald  *  Created by Matthias Ringwald on 4/29/09.
51f504dbdSmatthias.ringwald  *
61f504dbdSmatthias.ringwald  */
71f504dbdSmatthias.ringwald 
81f504dbdSmatthias.ringwald #pragma once
91f504dbdSmatthias.ringwald 
1023053b9eSmatthias.ringwald #include <btstack/hci_cmds.h>
1123053b9eSmatthias.ringwald #include <btstack/utils.h>
12ba681a6cSmatthias.ringwald #include "hci_transport.h"
13ba681a6cSmatthias.ringwald #include "bt_control.h"
14ba681a6cSmatthias.ringwald 
1593b8dc03Smatthias.ringwald #include <stdint.h>
1602ea9861Smatthias.ringwald #include <stdlib.h>
171cd208adSmatthias.ringwald #include <stdarg.h>
1893b8dc03Smatthias.ringwald 
1980d52d6bSmatthias.ringwald // packet header lenghts
2080d52d6bSmatthias.ringwald #define HCI_CMD_DATA_PKT_HDR	  0x03
2180d52d6bSmatthias.ringwald #define HCI_ACL_DATA_PKT_HDR	  0x04
2280d52d6bSmatthias.ringwald #define HCI_SCO_DATA_PKT_HDR	  0x03
2380d52d6bSmatthias.ringwald #define HCI_EVENT_PKT_HDR         0x02
2480d52d6bSmatthias.ringwald 
25*945627e4Smatthias.ringwald // OGFs
26*945627e4Smatthias.ringwald #define OGF_LINK_CONTROL 0x01
27*945627e4Smatthias.ringwald #define OGF_CONTROLLER_BASEBAND 0x03
28*945627e4Smatthias.ringwald #define OGF_INFORMATIONAL_PARAMETERS 0x04
29*945627e4Smatthias.ringwald #define OGF_BTSTACK 0x3d
30*945627e4Smatthias.ringwald #define OGF_VENDOR  0x3f
3180d52d6bSmatthias.ringwald 
3280d52d6bSmatthias.ringwald // cmds for BTstack
3380d52d6bSmatthias.ringwald // get state: @returns HCI_STATE
3480d52d6bSmatthias.ringwald #define BTSTACK_GET_STATE                                  0x01
3580d52d6bSmatthias.ringwald 
3680d52d6bSmatthias.ringwald // set power mode: @param HCI_POWER_MODE
3780d52d6bSmatthias.ringwald #define BTSTACK_SET_POWER_MODE                             0x02
3880d52d6bSmatthias.ringwald 
3980d52d6bSmatthias.ringwald // set capture mode: @param on
4080d52d6bSmatthias.ringwald #define BTSTACK_SET_ACL_CAPTURE_MODE                       0x03
4180d52d6bSmatthias.ringwald 
4280d52d6bSmatthias.ringwald // create l2cap channel: @param bd_addr(48), psm (16)
4380d52d6bSmatthias.ringwald #define L2CAP_CREATE_CHANNEL                               0x20
4480d52d6bSmatthias.ringwald 
4580d52d6bSmatthias.ringwald // disconnect l2cap disconnect, @param channel(16), reason(8)
4680d52d6bSmatthias.ringwald #define L2CAP_DISCONNECT                                   0x21
4780d52d6bSmatthias.ringwald 
4880d52d6bSmatthias.ringwald //
4980d52d6bSmatthias.ringwald #define IS_COMMAND(packet, command) (READ_BT_16(packet,0) == command.opcode)
5080d52d6bSmatthias.ringwald 
51*945627e4Smatthias.ringwald // data: event(8)
52*945627e4Smatthias.ringwald #define DAEMON_EVENT_CONNECTION_CLOSED                     0x70
53*945627e4Smatthias.ringwald 
54*945627e4Smatthias.ringwald // data: event(8), nr_connections(8)
55*945627e4Smatthias.ringwald #define DAEMON_NR_CONNECTIONS_CHANGED                      0x71
56*945627e4Smatthias.ringwald 
57*945627e4Smatthias.ringwald 
5806b35ec0Smatthias.ringwald /**
5906b35ec0Smatthias.ringwald  * Connection State
6006b35ec0Smatthias.ringwald  */
61c01e9cbdSmatthias.ringwald typedef enum {
62c01e9cbdSmatthias.ringwald     SEND_NEGATIVE_LINK_KEY_REQUEST = 1 << 0,
63c01e9cbdSmatthias.ringwald     SEND_PIN_CODE_RESPONSE = 1 << 1
64c01e9cbdSmatthias.ringwald } hci_connection_flags_t;
65c01e9cbdSmatthias.ringwald 
66c8e4258aSmatthias.ringwald typedef enum {
67c8e4258aSmatthias.ringwald     SENT_CREATE_CONNECTION = 1,
68c8e4258aSmatthias.ringwald     RECEIVED_CONNECTION_REQUEST,
69c8e4258aSmatthias.ringwald     ACCEPTED_CONNECTION_REQUEST,
70c8e4258aSmatthias.ringwald     REJECTED_CONNECTION_REQUEST,
71c8e4258aSmatthias.ringwald     OPEN,
72c8e4258aSmatthias.ringwald     SENT_DISCONNECT
73c8e4258aSmatthias.ringwald } CONNECTION_STATE;
74c8e4258aSmatthias.ringwald 
7543bfb1bdSmatthias.ringwald typedef enum {
7643bfb1bdSmatthias.ringwald     BLUETOOTH_OFF = 1,
7743bfb1bdSmatthias.ringwald     BLUETOOTH_ON,
7843bfb1bdSmatthias.ringwald     BLUETOOTH_ACTIVE
7943bfb1bdSmatthias.ringwald } BLUETOOTH_STATE;
8043bfb1bdSmatthias.ringwald 
81c8e4258aSmatthias.ringwald typedef struct {
8206b35ec0Smatthias.ringwald     // linked list - assert: first field
8306b35ec0Smatthias.ringwald     linked_item_t    item;
84c01e9cbdSmatthias.ringwald 
85c01e9cbdSmatthias.ringwald     // remote side
8616833f0aSmatthias.ringwald     bd_addr_t address;
8706b35ec0Smatthias.ringwald 
8806b35ec0Smatthias.ringwald     // module handle
8916833f0aSmatthias.ringwald     hci_con_handle_t con_handle;
90c01e9cbdSmatthias.ringwald 
91c8e4258aSmatthias.ringwald     // state
92c8e4258aSmatthias.ringwald     CONNECTION_STATE state;
93c8e4258aSmatthias.ringwald 
9406b35ec0Smatthias.ringwald     // errands
95c01e9cbdSmatthias.ringwald     hci_connection_flags_t flags;
96c8e4258aSmatthias.ringwald 
97ee091cf1Smatthias.ringwald     // timer
98ee091cf1Smatthias.ringwald     timer_t timeout;
99ee091cf1Smatthias.ringwald     struct timeval timestamp;
100ee091cf1Smatthias.ringwald 
10116833f0aSmatthias.ringwald } hci_connection_t;
10216833f0aSmatthias.ringwald 
10306b35ec0Smatthias.ringwald /**
10406b35ec0Smatthias.ringwald  * main data structure
10506b35ec0Smatthias.ringwald  */
10616833f0aSmatthias.ringwald typedef struct {
10706b35ec0Smatthias.ringwald     // transport component with configuration
10816833f0aSmatthias.ringwald     hci_transport_t  * hci_transport;
10911e23e5fSmatthias.ringwald     void             * config;
11011e23e5fSmatthias.ringwald 
11106b35ec0Smatthias.ringwald     // hardware power controller
11206b35ec0Smatthias.ringwald     bt_control_t     * control;
11306b35ec0Smatthias.ringwald 
11406b35ec0Smatthias.ringwald     // list of existing baseband connections
115fe1ed1b8Smatthias.ringwald     linked_list_t     connections;
11616833f0aSmatthias.ringwald 
11706b35ec0Smatthias.ringwald     // single buffer for HCI Command assembly
11806b35ec0Smatthias.ringwald     uint8_t          * hci_cmd_buffer;
11906b35ec0Smatthias.ringwald 
12016833f0aSmatthias.ringwald     /* host to controller flow control */
12116833f0aSmatthias.ringwald     uint8_t  num_cmd_packets;
12216833f0aSmatthias.ringwald     uint8_t  num_acl_packets;
12316833f0aSmatthias.ringwald 
12416833f0aSmatthias.ringwald     /* callback to L2CAP layer */
1251cd208adSmatthias.ringwald     void (*event_packet_handler)(uint8_t *packet, uint16_t size);
1261cd208adSmatthias.ringwald     void (*acl_packet_handler)  (uint8_t *packet, uint16_t size);
12716833f0aSmatthias.ringwald 
1283429f56bSmatthias.ringwald     /* hci state machine */
1293429f56bSmatthias.ringwald     HCI_STATE state;
1303429f56bSmatthias.ringwald     uint8_t   substate;
1313429f56bSmatthias.ringwald     uint8_t   cmds_ready;
1323429f56bSmatthias.ringwald 
13316833f0aSmatthias.ringwald } hci_stack_t;
13416833f0aSmatthias.ringwald 
135*945627e4Smatthias.ringwald // create and send hci command packets based on a template and a list of parameters
136*945627e4Smatthias.ringwald uint16_t hci_create_cmd(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, ...);
137*945627e4Smatthias.ringwald uint16_t hci_create_cmd_internal(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, va_list argptr);
138*945627e4Smatthias.ringwald 
139475c8125Smatthias.ringwald // set up HCI
14011e23e5fSmatthias.ringwald void hci_init(hci_transport_t *transport, void *config, bt_control_t *control);
141475c8125Smatthias.ringwald 
1421cd208adSmatthias.ringwald void hci_register_event_packet_handler(void (*handler)(uint8_t *packet, uint16_t size));
14316833f0aSmatthias.ringwald 
1441cd208adSmatthias.ringwald void hci_register_acl_packet_handler  (void (*handler)(uint8_t *packet, uint16_t size));
14516833f0aSmatthias.ringwald 
146475c8125Smatthias.ringwald // power control
147475c8125Smatthias.ringwald int hci_power_control(HCI_POWER_MODE mode);
148475c8125Smatthias.ringwald 
1493429f56bSmatthias.ringwald /**
150c8e4258aSmatthias.ringwald  * run the hci control loop once
1513429f56bSmatthias.ringwald  */
15206b35ec0Smatthias.ringwald void hci_run();
1531f504dbdSmatthias.ringwald 
1541cd208adSmatthias.ringwald // create and send hci command packets based on a template and a list of parameters
15502ea9861Smatthias.ringwald int hci_send_cmd(hci_cmd_t *cmd, ...);
156d8905019Smatthias.ringwald 
157d8905019Smatthias.ringwald // send complete CMD packet
15849857181Smatthias.ringwald int hci_send_cmd_packet(uint8_t *packet, int size);
159554588a5Smatthias.ringwald 
16043625864Smatthias.ringwald // send ACL packet
16143625864Smatthias.ringwald int hci_send_acl_packet(uint8_t *packet, int size);
16206b35ec0Smatthias.ringwald 
16306b35ec0Smatthias.ringwald //
1641e6aba47Smatthias.ringwald void hci_emit_state();
165c8e4258aSmatthias.ringwald void hci_emit_connection_complete(hci_connection_t *conn);
166ee091cf1Smatthias.ringwald void hci_emit_l2cap_check_timeout(hci_connection_t *conn);
16743bfb1bdSmatthias.ringwald void hci_emit_nr_connections_changed();
168038bc64cSmatthias.ringwald void hci_emit_hci_open_failed();
169