1 /*
2 * Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include "pico.h"
8 #include "cyw43.h"
9 #include "hci_transport.h"
10 #include "hci.h"
11 #include "pico/btstack_hci_transport_cyw43.h"
12 #include "pico/btstack_chipset_cyw43.h"
13
14 // assert outgoing pre-buffer for cyw43 header is available
15 #if !defined(HCI_OUTGOING_PRE_BUFFER_SIZE) || (HCI_OUTGOING_PRE_BUFFER_SIZE < 4)
16 #error HCI_OUTGOING_PRE_BUFFER_SIZE not defined or smaller than 4. Please update btstack_config.h
17 #endif
18
19 // assert outgoing packet fragments are word aligned
20 #if !defined(HCI_ACL_CHUNK_SIZE_ALIGNMENT) || ((HCI_ACL_CHUNK_SIZE_ALIGNMENT & 3) != 0)
21 #error HCI_ACL_CHUNK_SIZE_ALIGNMENT not defined or not a multiply of 4. Please update btstack_config.h
22 #endif
23
24 #define BT_DEBUG_ENABLED 0
25 #if BT_DEBUG_ENABLED
26 #define BT_DEBUG(...) CYW43_PRINTF(__VA_ARGS__)
27 #else
28 #define BT_DEBUG(...) (void)0
29 #endif
30
31 // Callback when we have data
32 static void (*hci_transport_cyw43_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = NULL;
33
34 // Incoming packet buffer - cyw43 packet header (incl packet type) + incoming pre buffer + max(acl header + acl payload, event header + event data)
35 __attribute__((aligned(4)))
36 static uint8_t hci_packet_with_pre_buffer[4 + HCI_INCOMING_PRE_BUFFER_SIZE + HCI_INCOMING_PACKET_BUFFER_SIZE ];
37
38 static btstack_data_source_t transport_data_source;
39 static bool hci_transport_ready;
40
41 // Forward declaration
42 static void hci_transport_cyw43_process(void);
43
hci_transport_data_source_process(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)44 static void hci_transport_data_source_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) {
45 assert(callback_type == DATA_SOURCE_CALLBACK_POLL);
46 assert(ds == &transport_data_source);
47 (void)callback_type;
48 (void)ds;
49 hci_transport_cyw43_process();
50 }
51
hci_transport_cyw43_init(const void * transport_config)52 static void hci_transport_cyw43_init(const void *transport_config) {
53 UNUSED(transport_config);
54 }
55
hci_transport_cyw43_open(void)56 static int hci_transport_cyw43_open(void) {
57 int err = cyw43_bluetooth_hci_init();
58 if (err != 0) {
59 CYW43_PRINTF("Failed to open cyw43 hci controller: %d\n", err);
60 return err;
61 }
62
63 // OTP should be set in which case BT gets an address of wifi mac + 1
64 // If OTP is not set for some reason BT gets set to 43:43:A2:12:1F:AC.
65 // So for safety, set the bluetooth device address here.
66 bd_addr_t addr;
67 cyw43_hal_get_mac(0, (uint8_t*)&addr);
68 addr[BD_ADDR_LEN - 1]++;
69 hci_set_chipset(btstack_chipset_cyw43_instance());
70 hci_set_bd_addr(addr);
71
72 btstack_run_loop_set_data_source_handler(&transport_data_source, &hci_transport_data_source_process);
73 btstack_run_loop_enable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_POLL);
74 btstack_run_loop_add_data_source(&transport_data_source);
75 hci_transport_ready = true;
76
77 return 0;
78 }
79
hci_transport_cyw43_close(void)80 static int hci_transport_cyw43_close(void) {
81 btstack_run_loop_disable_data_source_callbacks(&transport_data_source, DATA_SOURCE_CALLBACK_POLL);
82 btstack_run_loop_remove_data_source(&transport_data_source);
83 hci_transport_ready = false;
84
85 return 0;
86 }
87
hci_transport_cyw43_register_packet_handler(void (* handler)(uint8_t packet_type,uint8_t * packet,uint16_t size))88 static void hci_transport_cyw43_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)) {
89 hci_transport_cyw43_packet_handler = handler;
90 }
91
hci_transport_cyw43_can_send_now(uint8_t packet_type)92 static int hci_transport_cyw43_can_send_now(uint8_t packet_type) {
93 UNUSED(packet_type);
94 return true;
95 }
96
hci_transport_cyw43_send_packet(uint8_t packet_type,uint8_t * packet,int size)97 static int hci_transport_cyw43_send_packet(uint8_t packet_type, uint8_t *packet, int size) {
98 // store packet type before actual data and increase size
99 // This relies on HCI_OUTGOING_PRE_BUFFER_SIZE being set
100 uint8_t *buffer = &packet[-4];
101 uint32_t buffer_size = size + 4;
102 buffer[3] = packet_type;
103
104 CYW43_THREAD_ENTER
105 int err = cyw43_bluetooth_hci_write(buffer, buffer_size);
106
107 if (err != 0) {
108 CYW43_PRINTF("Failed to send cyw43 hci packet: %d\n", err);
109 assert(false);
110 } else {
111 BT_DEBUG("bt sent %lu\n", buffer_size);
112 static uint8_t packet_sent_event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0};
113 hci_transport_cyw43_packet_handler(HCI_EVENT_PACKET, &packet_sent_event[0], sizeof(packet_sent_event));
114 }
115 CYW43_THREAD_EXIT
116 return err;
117 }
118
119 // configure and return hci transport singleton
120 static const hci_transport_t hci_transport_cyw43 = {
121 /* const char * name; */ "CYW43",
122 /* void (*init) (const void *transport_config); */ &hci_transport_cyw43_init,
123 /* int (*open)(void); */ &hci_transport_cyw43_open,
124 /* int (*close)(void); */ &hci_transport_cyw43_close,
125 /* void (*register_packet_handler)(void (*handler)(...); */ &hci_transport_cyw43_register_packet_handler,
126 /* int (*can_send_packet_now)(uint8_t packet_type); */ &hci_transport_cyw43_can_send_now,
127 /* int (*send_packet)(...); */ &hci_transport_cyw43_send_packet,
128 /* int (*set_baudrate)(uint32_t baudrate); */ NULL,
129 /* void (*reset_link)(void); */ NULL,
130 /* void (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL,
131 };
132
hci_transport_cyw43_instance(void)133 const hci_transport_t *hci_transport_cyw43_instance(void) {
134 return &hci_transport_cyw43;
135 }
136
137 // Called to perform bt work from a data source
hci_transport_cyw43_process(void)138 static void hci_transport_cyw43_process(void) {
139 CYW43_THREAD_LOCK_CHECK
140 uint32_t len = 0;
141 bool has_work;
142 #ifdef PICO_BTSTACK_CYW43_MAX_HCI_PROCESS_LOOP_COUNT
143 uint32_t loop_count = 0;
144 #endif
145 do {
146 int err = cyw43_bluetooth_hci_read(hci_packet_with_pre_buffer, sizeof(hci_packet_with_pre_buffer), &len);
147 BT_DEBUG("bt in len=%lu err=%d\n", len, err);
148 if (err == 0 && len > 0) {
149 hci_transport_cyw43_packet_handler(hci_packet_with_pre_buffer[3], hci_packet_with_pre_buffer + 4, len - 4);
150 has_work = true;
151 } else {
152 has_work = false;
153 }
154 // PICO_CONFIG: PICO_BTSTACK_CYW43_MAX_HCI_PROCESS_LOOP_COUNT, limit the max number of iterations of the hci processing loop, type=int, advanced=true, group=pico_btstack
155 #ifdef PICO_BTSTACK_CYW43_MAX_HCI_PROCESS_LOOP_COUNT
156 if (++loop_count >= PICO_BTSTACK_CYW43_MAX_HCI_PROCESS_LOOP_COUNT) {
157 break;
158 }
159 #endif
160 } while (has_work);
161 }
162
163 // This is called from cyw43_poll_func.
cyw43_bluetooth_hci_process(void)164 void cyw43_bluetooth_hci_process(void) {
165 if (hci_transport_ready) {
166 btstack_run_loop_poll_data_sources_from_irq();
167 }
168 }
169