xref: /btstack/port/zephyr/src/main.c (revision 277e512c6ebe4d2708137a04f187d5a036a7654b)
1*277e512cSDirk Helbig /*
2*277e512cSDirk Helbig  * Copyright (c) 2016 Nordic Semiconductor ASA
3*277e512cSDirk Helbig  * Copyright (c) 2015-2016 Intel Corporation
4*277e512cSDirk Helbig  *
5*277e512cSDirk Helbig  * SPDX-License-Identifier: Apache-2.0
6*277e512cSDirk Helbig  */
7*277e512cSDirk Helbig 
8*277e512cSDirk Helbig #include <errno.h>
9*277e512cSDirk Helbig #include <stddef.h>
10*277e512cSDirk Helbig #include <stdio.h>
11*277e512cSDirk Helbig #include <string.h>
12*277e512cSDirk Helbig 
13*277e512cSDirk Helbig #include <zephyr/kernel.h>
14*277e512cSDirk Helbig #include <zephyr/bluetooth/bluetooth.h>
15*277e512cSDirk Helbig #include <zephyr/bluetooth/l2cap.h>
16*277e512cSDirk Helbig #include <zephyr/bluetooth/hci.h>
17*277e512cSDirk Helbig #include <zephyr/bluetooth/buf.h>
18*277e512cSDirk Helbig #include <zephyr/bluetooth/hci_raw.h>
19*277e512cSDirk Helbig 
20*277e512cSDirk Helbig // Nordic NDK
21*277e512cSDirk Helbig #include "nrf.h"
22*277e512cSDirk Helbig 
23*277e512cSDirk Helbig // BTstack
24*277e512cSDirk Helbig #include "btstack_debug.h"
25*277e512cSDirk Helbig #include "btstack_event.h"
26*277e512cSDirk Helbig #include "btstack_memory.h"
27*277e512cSDirk Helbig #include "btstack_run_loop_zephyr.h"
28*277e512cSDirk Helbig #include "hci.h"
29*277e512cSDirk Helbig #include "hci_dump.h"
30*277e512cSDirk Helbig #include "hci_dump_embedded_stdout.h"
31*277e512cSDirk Helbig #include "hci_transport.h"
32*277e512cSDirk Helbig 
33*277e512cSDirk Helbig #include "btstack_tlv.h"
34*277e512cSDirk Helbig #include "btstack_tlv_none.h"
35*277e512cSDirk Helbig #include "ble/le_device_db_tlv.h"
36*277e512cSDirk Helbig 
37*277e512cSDirk Helbig static K_FIFO_DEFINE(tx_queue);
38*277e512cSDirk Helbig static K_FIFO_DEFINE(rx_queue);
39*277e512cSDirk Helbig 
40*277e512cSDirk Helbig //
41*277e512cSDirk Helbig // hci_transport_zephyr.c
42*277e512cSDirk Helbig //
43*277e512cSDirk Helbig 
44*277e512cSDirk Helbig static void (*transport_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size);
45*277e512cSDirk Helbig 
46*277e512cSDirk Helbig /**
47*277e512cSDirk Helbig  * init transport
48*277e512cSDirk Helbig  * @param transport_config
49*277e512cSDirk Helbig  */
50*277e512cSDirk Helbig static void transport_init(const void *transport_config){
51*277e512cSDirk Helbig 	/* startup Controller */
52*277e512cSDirk Helbig 	bt_enable_raw(&rx_queue);
53*277e512cSDirk Helbig }
54*277e512cSDirk Helbig 
55*277e512cSDirk Helbig /**
56*277e512cSDirk Helbig  * open transport connection
57*277e512cSDirk Helbig  */
58*277e512cSDirk Helbig static int transport_open(void){
59*277e512cSDirk Helbig     return 0;
60*277e512cSDirk Helbig }
61*277e512cSDirk Helbig 
62*277e512cSDirk Helbig /**
63*277e512cSDirk Helbig  * close transport connection
64*277e512cSDirk Helbig  */
65*277e512cSDirk Helbig static int transport_close(void){
66*277e512cSDirk Helbig     return 0;
67*277e512cSDirk Helbig }
68*277e512cSDirk Helbig 
69*277e512cSDirk Helbig /**
70*277e512cSDirk Helbig  * register packet handler for HCI packets: ACL, SCO, and Events
71*277e512cSDirk Helbig  */
72*277e512cSDirk Helbig static void transport_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
73*277e512cSDirk Helbig     transport_packet_handler = handler;
74*277e512cSDirk Helbig }
75*277e512cSDirk Helbig 
76*277e512cSDirk Helbig static void send_hardware_error(uint8_t error_code){
77*277e512cSDirk Helbig     // hci_outgoing_event[0] = HCI_EVENT_HARDWARE_ERROR;
78*277e512cSDirk Helbig     // hci_outgoing_event[1] = 1;
79*277e512cSDirk Helbig     // hci_outgoing_event[2] = error_code;
80*277e512cSDirk Helbig     // hci_outgoing_event_ready = 1;
81*277e512cSDirk Helbig }
82*277e512cSDirk Helbig 
83*277e512cSDirk Helbig static int transport_send_packet(uint8_t packet_type, uint8_t *packet, int size){
84*277e512cSDirk Helbig 	struct net_buf *buf;
85*277e512cSDirk Helbig     switch (packet_type){
86*277e512cSDirk Helbig         case HCI_COMMAND_DATA_PACKET:
87*277e512cSDirk Helbig 		    buf = bt_buf_get_tx(BT_BUF_CMD, K_NO_WAIT, packet, size);
88*277e512cSDirk Helbig 			if (!buf) {
89*277e512cSDirk Helbig 				log_error("No available command buffers!\n");
90*277e512cSDirk Helbig                 break;
91*277e512cSDirk Helbig 			}
92*277e512cSDirk Helbig 
93*277e512cSDirk Helbig 			memcpy(net_buf_add(buf, size), packet, size);
94*277e512cSDirk Helbig 			bt_send(buf);
95*277e512cSDirk Helbig             break;
96*277e512cSDirk Helbig         case HCI_ACL_DATA_PACKET:
97*277e512cSDirk Helbig 		    buf = bt_buf_get_tx(BT_BUF_ACL_OUT, K_NO_WAIT, packet, size);
98*277e512cSDirk Helbig 			if (!buf) {
99*277e512cSDirk Helbig 				log_error("No available ACL buffers!\n");
100*277e512cSDirk Helbig                 break;
101*277e512cSDirk Helbig 			}
102*277e512cSDirk Helbig 
103*277e512cSDirk Helbig 			memcpy(net_buf_add(buf, size), packet, size);
104*277e512cSDirk Helbig 			bt_send(buf);
105*277e512cSDirk Helbig             break;
106*277e512cSDirk Helbig         default:
107*277e512cSDirk Helbig             send_hardware_error(0x01);  // invalid HCI packet
108*277e512cSDirk Helbig             break;
109*277e512cSDirk Helbig     }
110*277e512cSDirk Helbig 
111*277e512cSDirk Helbig     return 0;
112*277e512cSDirk Helbig }
113*277e512cSDirk Helbig 
114*277e512cSDirk Helbig static const hci_transport_t transport = {
115*277e512cSDirk Helbig     /* const char * name; */                                        "nRF5-Zephyr",
116*277e512cSDirk Helbig     /* void   (*init) (const void *transport_config); */            &transport_init,
117*277e512cSDirk Helbig     /* int    (*open)(void); */                                     &transport_open,
118*277e512cSDirk Helbig     /* int    (*close)(void); */                                    &transport_close,
119*277e512cSDirk Helbig     /* void   (*register_packet_handler)(void (*handler)(...); */   &transport_register_packet_handler,
120*277e512cSDirk Helbig     /* int    (*can_send_packet_now)(uint8_t packet_type); */       NULL,
121*277e512cSDirk Helbig     /* int    (*send_packet)(...); */                               &transport_send_packet,
122*277e512cSDirk Helbig     /* int    (*set_baudrate)(uint32_t baudrate); */                NULL,
123*277e512cSDirk Helbig     /* void   (*reset_link)(void); */                               NULL,
124*277e512cSDirk Helbig };
125*277e512cSDirk Helbig 
126*277e512cSDirk Helbig static const hci_transport_t * transport_get_instance(void){
127*277e512cSDirk Helbig 	return &transport;
128*277e512cSDirk Helbig }
129*277e512cSDirk Helbig 
130*277e512cSDirk Helbig static void transport_deliver_controller_packet(struct net_buf * buf){
131*277e512cSDirk Helbig 		uint16_t    size = buf->len;
132*277e512cSDirk Helbig 		uint8_t * packet = buf->data;
133*277e512cSDirk Helbig 		switch (bt_buf_get_type(buf)) {
134*277e512cSDirk Helbig 			case BT_BUF_ACL_IN:
135*277e512cSDirk Helbig 				transport_packet_handler(HCI_ACL_DATA_PACKET, packet, size);
136*277e512cSDirk Helbig 				break;
137*277e512cSDirk Helbig 			case BT_BUF_EVT:
138*277e512cSDirk Helbig 				transport_packet_handler(HCI_EVENT_PACKET, packet, size);
139*277e512cSDirk Helbig 				break;
140*277e512cSDirk Helbig 			default:
141*277e512cSDirk Helbig 				log_error("Unknown type %u\n", bt_buf_get_type(buf));
142*277e512cSDirk Helbig 				break;
143*277e512cSDirk Helbig 		}
144*277e512cSDirk Helbig 		net_buf_unref(buf);
145*277e512cSDirk Helbig }
146*277e512cSDirk Helbig 
147*277e512cSDirk Helbig // btstack_run_loop_zephry.c
148*277e512cSDirk Helbig 
149*277e512cSDirk Helbig // the run loop
150*277e512cSDirk Helbig //static btstack_linked_list_t timers;
151*277e512cSDirk Helbig 
152*277e512cSDirk Helbig // TODO: handle 32 bit ms time overrun
153*277e512cSDirk Helbig static uint32_t btstack_run_loop_zephyr_get_time_ms(void){
154*277e512cSDirk Helbig 	return  k_uptime_get_32();
155*277e512cSDirk Helbig }
156*277e512cSDirk Helbig 
157*277e512cSDirk Helbig static void btstack_run_loop_zephyr_set_timer(btstack_timer_source_t *ts, uint32_t timeout_in_ms){
158*277e512cSDirk Helbig     ts->timeout = k_uptime_get_32() + 1 + timeout_in_ms;
159*277e512cSDirk Helbig }
160*277e512cSDirk Helbig 
161*277e512cSDirk Helbig /**
162*277e512cSDirk Helbig  * Execute run_loop
163*277e512cSDirk Helbig  */
164*277e512cSDirk Helbig static void btstack_run_loop_zephyr_execute(void) {
165*277e512cSDirk Helbig     while (1) {
166*277e512cSDirk Helbig         // process timers
167*277e512cSDirk Helbig         uint32_t now = k_uptime_get_32();
168*277e512cSDirk Helbig         btstack_run_loop_base_process_timers(now);
169*277e512cSDirk Helbig 
170*277e512cSDirk Helbig         // get time until next timer expires
171*277e512cSDirk Helbig         k_timeout_t timeout;
172*277e512cSDirk Helbig         timeout.ticks = btstack_run_loop_base_get_time_until_timeout(now);
173*277e512cSDirk Helbig         if (timeout.ticks < 0){
174*277e512cSDirk Helbig             timeout.ticks = K_TICKS_FOREVER;
175*277e512cSDirk Helbig         }
176*277e512cSDirk Helbig 
177*277e512cSDirk Helbig         // process RX fifo only
178*277e512cSDirk Helbig         struct net_buf *buf = net_buf_get(&rx_queue, timeout);
179*277e512cSDirk Helbig 		if (buf){
180*277e512cSDirk Helbig 			transport_deliver_controller_packet(buf);
181*277e512cSDirk Helbig 		}
182*277e512cSDirk Helbig 	}
183*277e512cSDirk Helbig }
184*277e512cSDirk Helbig 
185*277e512cSDirk Helbig static void btstack_run_loop_zephyr_btstack_run_loop_init(void){
186*277e512cSDirk Helbig     btstack_run_loop_base_init();
187*277e512cSDirk Helbig }
188*277e512cSDirk Helbig 
189*277e512cSDirk Helbig static const btstack_run_loop_t btstack_run_loop_zephyr = {
190*277e512cSDirk Helbig     &btstack_run_loop_zephyr_btstack_run_loop_init,
191*277e512cSDirk Helbig     NULL,
192*277e512cSDirk Helbig     NULL,
193*277e512cSDirk Helbig     NULL,
194*277e512cSDirk Helbig     NULL,
195*277e512cSDirk Helbig     &btstack_run_loop_zephyr_set_timer,
196*277e512cSDirk Helbig     &btstack_run_loop_base_add_timer,
197*277e512cSDirk Helbig     &btstack_run_loop_base_remove_timer,
198*277e512cSDirk Helbig     &btstack_run_loop_zephyr_execute,
199*277e512cSDirk Helbig     &btstack_run_loop_base_dump_timer,
200*277e512cSDirk Helbig     &btstack_run_loop_zephyr_get_time_ms,
201*277e512cSDirk Helbig };
202*277e512cSDirk Helbig /**
203*277e512cSDirk Helbig  * @brief Provide btstack_run_loop_posix instance for use with btstack_run_loop_init
204*277e512cSDirk Helbig  */
205*277e512cSDirk Helbig const btstack_run_loop_t * btstack_run_loop_zephyr_get_instance(void){
206*277e512cSDirk Helbig     return &btstack_run_loop_zephyr;
207*277e512cSDirk Helbig }
208*277e512cSDirk Helbig 
209*277e512cSDirk Helbig static btstack_packet_callback_registration_t hci_event_callback_registration;
210*277e512cSDirk Helbig 
211*277e512cSDirk Helbig static bd_addr_t static_address;
212*277e512cSDirk Helbig 
213*277e512cSDirk Helbig static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
214*277e512cSDirk Helbig     if (packet_type != HCI_EVENT_PACKET) return;
215*277e512cSDirk Helbig     if (hci_event_packet_get_type(packet) != BTSTACK_EVENT_STATE) return;
216*277e512cSDirk Helbig     if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
217*277e512cSDirk Helbig     printf("BTstack up and running as %s.\n", bd_addr_to_str(static_address));
218*277e512cSDirk Helbig }
219*277e512cSDirk Helbig 
220*277e512cSDirk Helbig int btstack_main(void);
221*277e512cSDirk Helbig 
222*277e512cSDirk Helbig #if defined(CONFIG_BT_CTLR_ASSERT_HANDLER)
223*277e512cSDirk Helbig void bt_ctlr_assert_handle(char *file, uint32_t line)
224*277e512cSDirk Helbig {
225*277e512cSDirk Helbig 	printf("CONFIG_BT_CTLR_ASSERT_HANDLER: file %s, line %u\n", file, line);
226*277e512cSDirk Helbig 	while (1) {
227*277e512cSDirk Helbig 	}
228*277e512cSDirk Helbig }
229*277e512cSDirk Helbig #endif /* CONFIG_BT_CTLR_ASSERT_HANDLER */
230*277e512cSDirk Helbig 
231*277e512cSDirk Helbig void main(void)
232*277e512cSDirk Helbig {
233*277e512cSDirk Helbig 	// configure console UART by replacing CONFIG_UART_NRF5_BAUD_RATE with 115200 in uart_console.c
234*277e512cSDirk Helbig 
235*277e512cSDirk Helbig 	printf("BTstack booting up..\n");
236*277e512cSDirk Helbig 
237*277e512cSDirk Helbig 	// start with BTstack init - especially configure HCI Transport
238*277e512cSDirk Helbig     btstack_memory_init();
239*277e512cSDirk Helbig     btstack_run_loop_init(btstack_run_loop_zephyr_get_instance());
240*277e512cSDirk Helbig 
241*277e512cSDirk Helbig     // enable full log output while porting
242*277e512cSDirk Helbig     hci_dump_init(hci_dump_embedded_stdout_get_instance());
243*277e512cSDirk Helbig 
244*277e512cSDirk Helbig     const btstack_tlv_t * btstack_tlv_impl = btstack_tlv_none_init_instance();
245*277e512cSDirk Helbig     // setup global tlv
246*277e512cSDirk Helbig     btstack_tlv_set_instance(btstack_tlv_impl, NULL);
247*277e512cSDirk Helbig 
248*277e512cSDirk Helbig     // setup LE Device DB using TLV
249*277e512cSDirk Helbig     le_device_db_tlv_configure(btstack_tlv_impl, NULL);
250*277e512cSDirk Helbig 
251*277e512cSDirk Helbig     // init HCI
252*277e512cSDirk Helbig     hci_init(transport_get_instance(), NULL);
253*277e512cSDirk Helbig 
254*277e512cSDirk Helbig     // nRF5 chipsets don't have an official public address
255*277e512cSDirk Helbig     // Instead, a Static Random Address is assigned during manufacturing
256*277e512cSDirk Helbig     // let's use it as well
257*277e512cSDirk Helbig     big_endian_store_16(static_address, 0, NRF_FICR->DEVICEADDR[1] | 0xc000);
258*277e512cSDirk Helbig     big_endian_store_32(static_address, 2, NRF_FICR->DEVICEADDR[0]);
259*277e512cSDirk Helbig     gap_random_address_set(static_address);
260*277e512cSDirk Helbig 
261*277e512cSDirk Helbig     // inform about BTstack state
262*277e512cSDirk Helbig     hci_event_callback_registration.callback = &packet_handler;
263*277e512cSDirk Helbig     hci_add_event_handler(&hci_event_callback_registration);
264*277e512cSDirk Helbig 
265*277e512cSDirk Helbig     // hand over to btstack embedded code
266*277e512cSDirk Helbig     btstack_main();
267*277e512cSDirk Helbig 
268*277e512cSDirk Helbig     // go
269*277e512cSDirk Helbig     btstack_run_loop_execute();
270*277e512cSDirk Helbig 
271*277e512cSDirk Helbig     while (1){};
272*277e512cSDirk Helbig }
273