1 /*
2 * Copyright (C) 2020 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holders nor the names of
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * 4. Any redistribution, use, or modification is done solely for
17 * personal benefit and not for any commercial purpose or for
18 * monetary gain.
19 *
20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * Please inquire about commercial licensing options at
34 * [email protected]
35 *
36 */
37
38 #define BTSTACK_FILE__ "controller.c"
39
40 #define DEBUG
41
42 #include <string.h>
43
44 #include "controller.h"
45
46 #include "ll.h"
47
48 #include "btstack_config.h"
49 #include "btstack_debug.h"
50 #include "btstack_util.h"
51 #include "btstack_run_loop.h"
52 #include "btstack_run_loop_embedded.h"
53 #include "bluetooth_company_id.h"
54 #include "hci_event.h"
55 #include "hci_transport.h"
56 #include "btstack_tlv.h"
57 #include "btstack_tlv_none.h"
58 #include "ble/le_device_db_tlv.h"
59 #include "hci_cmd.h"
60
61 // HCI Connection Handle used for all HCI events/connections
62 #define HCI_CON_HANDLE 0x0001
63
64 //
65 // Controller
66 //
67 static uint8_t send_hardware_error;
68 static bool send_transport_sent;
69
70 static btstack_data_source_t hci_transport_data_source;
71
72 static uint8_t hci_outgoing_event[258];
73 static bool hci_outgoing_event_ready;
74
75 static void (*hci_packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size);
76
77 /** BTstack Controller Implementation */
78
79 // Controller State
80 static bool controller_ll_acl_reserved;
81
send_command_complete(uint16_t opcode,uint8_t status,const uint8_t * result,uint16_t len)82 static void send_command_complete(uint16_t opcode, uint8_t status, const uint8_t * result, uint16_t len){
83 hci_event_create_from_template_and_arguments(hci_outgoing_event, sizeof(hci_outgoing_event),
84 &hci_event_command_complete, /* num commands */ 1, opcode, status, len, result);
85 hci_outgoing_event_ready = true;
86 btstack_run_loop_poll_data_sources_from_irq();
87 }
88
fake_command_complete(uint16_t opcode)89 static void fake_command_complete(uint16_t opcode){
90 hci_event_create_from_template_and_arguments(hci_outgoing_event, sizeof(hci_outgoing_event),
91 &hci_event_command_complete, /* num commands */ 1, opcode, ERROR_CODE_SUCCESS, 0, NULL);
92 hci_outgoing_event_ready = true;
93 btstack_run_loop_poll_data_sources_from_irq();
94 }
95
controller_handle_hci_command(uint8_t * packet,uint16_t size)96 static void controller_handle_hci_command(uint8_t * packet, uint16_t size){
97
98 btstack_assert(hci_outgoing_event_ready == false);
99
100 const uint8_t local_supported_features[] = { 0, 0, 0, 0, 0x40, 0, 0, 0};
101 const uint8_t read_buffer_size_result[] = { 0x1b, 0, HCI_NUM_TX_BUFFERS_STACK };
102 uint8_t status;
103
104 uint16_t opcode = little_endian_read_16(packet, 0);
105 switch (opcode){
106 case HCI_OPCODE_HCI_RESET:
107 fake_command_complete(opcode);
108 break;
109 case HCI_OPCODE_HCI_READ_LOCAL_SUPPORTED_FEATURES:
110 // No. 37, byte 4, bit 6 = LE Supported (Controller)
111 send_command_complete(opcode, 0, local_supported_features, 8);
112 break;
113 case HCI_OPCODE_HCI_LE_READ_BUFFER_SIZE:
114 send_command_complete(opcode, 0, read_buffer_size_result, 8);
115 break;
116 case HCI_OPCODE_HCI_LE_SET_ADVERTISING_PARAMETERS:
117 status = ll_set_advertising_parameters(
118 little_endian_read_16(packet,3),
119 little_endian_read_16(packet,5),
120 packet[7],
121 packet[8],
122 packet[9],
123 &packet[10],
124 packet[16],
125 packet[17]);
126 send_command_complete(opcode, status, NULL, 0);
127 break;
128 case HCI_OPCODE_HCI_LE_SET_ADVERTISING_DATA:
129 status = ll_set_advertising_data(packet[3], &packet[4]);
130 send_command_complete(opcode, status, NULL, 0);
131 break;
132 case HCI_OPCODE_HCI_LE_SET_ADVERTISE_ENABLE:
133 status = ll_set_advertise_enable(packet[3]);
134 send_command_complete(opcode, status, NULL, 0);
135 break;
136 case HCI_OPCODE_HCI_LE_SET_SCAN_ENABLE:
137 ll_set_scan_enable(packet[3], packet[4]);
138 fake_command_complete(opcode);
139 break;
140 case HCI_OPCODE_HCI_LE_SET_SCAN_PARAMETERS:
141 ll_set_scan_parameters(packet[3], little_endian_read_16(packet, 4), little_endian_read_16(packet, 6), packet[8], packet[9]);
142 fake_command_complete(opcode);
143 break;
144 default:
145 log_debug("CMD opcode %02x not handled yet", opcode);
146 // try with "OK"
147 fake_command_complete(opcode);
148 break;
149 }
150 }
151
152 // ACL handler
controller_handle_acl_data(uint8_t * packet,uint16_t size)153 static void controller_handle_acl_data(uint8_t * packet, uint16_t size){
154 // so far, only single connection supported with fixed con handle
155 hci_con_handle_t con_handle = little_endian_read_16(packet, 0) & 0xfff;
156 btstack_assert(con_handle == HCI_CON_HANDLE);
157 btstack_assert( size > 4);
158
159 // just queue up
160 btstack_assert(controller_ll_acl_reserved);
161 controller_ll_acl_reserved = false;
162 ll_queue_acl_packet(packet, size);
163 }
164
transport_emit_hci_event(const hci_event_t * event,...)165 static void transport_emit_hci_event(const hci_event_t * event, ...){
166 va_list argptr;
167 va_start(argptr, event);
168 uint16_t length = hci_event_create_from_template_and_arglist(hci_outgoing_event, sizeof(hci_outgoing_event), event, argptr);
169 va_end(argptr);
170 hci_packet_handler(HCI_EVENT_PACKET, hci_outgoing_event, length);
171 }
172
transport_run(btstack_data_source_t * ds,btstack_data_source_callback_type_t callback_type)173 static void transport_run(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
174
175 // deliver command complete events caused by command processor
176 if (hci_outgoing_event_ready){
177 hci_outgoing_event_ready = false;
178 hci_packet_handler(HCI_EVENT_PACKET, hci_outgoing_event, hci_outgoing_event[1]+2);
179 }
180
181 if (send_hardware_error != 0){
182 uint8_t error_code = send_hardware_error;
183 send_hardware_error = 0;
184 transport_emit_hci_event(&hci_event_hardware_error, error_code);
185 }
186
187 if (send_transport_sent){
188 send_transport_sent = false;
189 // notify upper stack that it might be possible to send again
190 transport_emit_hci_event(&hci_event_transport_packet_sent);
191 }
192
193 ll_execute_once();
194 }
195
transport_packet_handler(uint8_t packet_type,uint8_t * packet,uint16_t size)196 static void transport_packet_handler(uint8_t packet_type, uint8_t * packet, uint16_t size){
197 // just forward to hci
198 (*hci_packet_handler)(packet_type, packet, size);
199 }
200
201 /**
202 * init transport
203 * @param transport_config
204 */
transport_init(const void * transport_config)205 static void transport_init(const void *transport_config){
206 UNUSED(transport_config);
207 ll_register_packet_handler(&transport_packet_handler);
208 }
209
210 /**
211 * open transport connection
212 */
transport_open(void)213 static int transport_open(void){
214 btstack_run_loop_set_data_source_handler(&hci_transport_data_source, &transport_run);
215 btstack_run_loop_enable_data_source_callbacks(&hci_transport_data_source, DATA_SOURCE_CALLBACK_POLL);
216 btstack_run_loop_add_data_source(&hci_transport_data_source);
217
218 ll_init();
219 ll_radio_on();
220
221 return 0;
222 }
223
224 /**
225 * close transport connection
226 */
transport_close(void)227 static int transport_close(void){
228 btstack_run_loop_remove_data_source(&hci_transport_data_source);
229
230 // TODO
231
232 return 0;
233 }
234
235 /**
236 * register packet handler for HCI packets: ACL, SCO, and Events
237 */
transport_register_packet_handler(void (* handler)(uint8_t packet_type,uint8_t * packet,uint16_t size))238 static void transport_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
239 hci_packet_handler = handler;
240 }
241
transport_can_send_packet_now(uint8_t packet_type)242 static int transport_can_send_packet_now(uint8_t packet_type){
243 if (send_transport_sent) return 0;
244 switch (packet_type){
245 case HCI_COMMAND_DATA_PACKET:
246 return hci_outgoing_event_ready ? 0 : 1;
247 case HCI_ACL_DATA_PACKET:
248 if (controller_ll_acl_reserved == false){
249 controller_ll_acl_reserved = ll_reserve_acl_packet();
250 }
251 return controller_ll_acl_reserved ? 1 : 0;
252 default:
253 btstack_assert(false);
254 break;
255 }
256 return 0;
257 }
258
transport_send_packet(uint8_t packet_type,uint8_t * packet,int size)259 static int transport_send_packet(uint8_t packet_type, uint8_t *packet, int size){
260 switch (packet_type){
261 case HCI_COMMAND_DATA_PACKET:
262 controller_handle_hci_command(packet, size);
263 send_transport_sent = true;
264 break;
265 case HCI_ACL_DATA_PACKET:
266 controller_handle_acl_data(packet, size);
267 send_transport_sent = true;
268 break;
269 default:
270 send_hardware_error = 0x01; // invalid HCI packet
271 break;
272 }
273 return 0;
274 }
275
controller_init(void)276 void controller_init(void){
277 }
278
279 static const hci_transport_t controller_transport = {
280 "sx1280-vhci",
281 &transport_init,
282 &transport_open,
283 &transport_close,
284 &transport_register_packet_handler,
285 &transport_can_send_packet_now,
286 &transport_send_packet,
287 NULL, // set baud rate
288 NULL, // reset link
289 NULL, // set SCO config
290 };
291
controller_get_hci_transport(void)292 const hci_transport_t * controller_get_hci_transport(void){
293 return &controller_transport;
294 }
295