xref: /btstack/chipset/cinnamon/controller.c (revision 308e35cf33f6937b53ef6c055adea9d10e215e1a)
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 
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 
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 
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
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 
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, event, argptr);
169     va_end(argptr);
170     hci_packet_handler(HCI_EVENT_PACKET, hci_outgoing_event, length);
171 }
172 
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 
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  */
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  */
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  */
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  */
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 
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 
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 
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 
292 const hci_transport_t * controller_get_hci_transport(void){
293     return &controller_transport;
294 }
295