xref: /btstack/chipset/cinnamon/controller.c (revision eb4dccece89f38c3fa8fb13197f36188f58d954a)
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 MATTHIAS
24  * RINGWALD 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, &hci_event_command_complete,
84             /* num commands */ 1, opcode, status, len, result);
85     hci_outgoing_event_ready = true;
86 }
87 
88 static void fake_command_complete(uint16_t opcode){
89     hci_event_create_from_template_and_arguments(hci_outgoing_event, &hci_event_command_complete,
90             /* num commands */ 1, opcode, ERROR_CODE_SUCCESS, 0, NULL);
91     hci_outgoing_event_ready = true;
92 }
93 
94 static void controller_handle_hci_command(uint8_t * packet, uint16_t size){
95 
96     btstack_assert(hci_outgoing_event_ready == false);
97 
98     const uint8_t local_supported_features[] = { 0, 0, 0, 0, 0x40, 0, 0, 0};
99     const uint8_t read_buffer_size_result[] = { 0x1b, 0, HCI_NUM_TX_BUFFERS_STACK };
100     uint8_t status;
101 
102     uint16_t opcode = little_endian_read_16(packet, 0);
103     switch (opcode){
104         case HCI_OPCODE_HCI_RESET:
105             fake_command_complete(opcode);
106             break;
107         case HCI_OPCODE_HCI_READ_LOCAL_SUPPORTED_FEATURES:
108             // No. 37, byte 4, bit 6 = LE Supported (Controller)
109             send_command_complete(opcode, 0, local_supported_features, 8);
110             break;
111         case HCI_OPCODE_HCI_LE_READ_BUFFER_SIZE:
112             send_command_complete(opcode, 0, read_buffer_size_result, 8);
113             break;
114         case HCI_OPCODE_HCI_LE_SET_ADVERTISING_PARAMETERS:
115             status = ll_set_advertising_parameters(
116                     little_endian_read_16(packet,3),
117                     little_endian_read_16(packet,5),
118                     packet[7],
119                     packet[8],
120                     packet[9],
121                     &packet[10],
122                     packet[16],
123                     packet[17]);
124             send_command_complete(opcode, status, NULL, 0);
125             break;
126         case HCI_OPCODE_HCI_LE_SET_ADVERTISING_DATA:
127             status = ll_set_advertising_data(packet[3], &packet[4]);
128             send_command_complete(opcode, status, NULL, 0);
129             break;
130         case HCI_OPCODE_HCI_LE_SET_ADVERTISE_ENABLE:
131             status = ll_set_advertise_enable(packet[3]);
132             send_command_complete(opcode, status, NULL, 0);
133             break;
134         case HCI_OPCODE_HCI_LE_SET_SCAN_ENABLE:
135             ll_set_scan_enable(packet[3], packet[4]);
136             fake_command_complete(opcode);
137             break;
138         case HCI_OPCODE_HCI_LE_SET_SCAN_PARAMETERS:
139             ll_set_scan_parameters(packet[3], little_endian_read_16(packet, 4), little_endian_read_16(packet, 6), packet[8], packet[9]);
140             fake_command_complete(opcode);
141             break;
142         default:
143             log_debug("CMD opcode %02x not handled yet", opcode);
144             // try with "OK"
145             fake_command_complete(opcode);
146             break;
147     }
148 }
149 
150 // ACL handler
151 static void controller_handle_acl_data(uint8_t * packet, uint16_t size){
152     // so far, only single connection supported with fixed con handle
153     hci_con_handle_t con_handle = little_endian_read_16(packet, 0) & 0xfff;
154     btstack_assert(con_handle == HCI_CON_HANDLE);
155     btstack_assert( size > 4);
156 
157     // just queue up
158     btstack_assert(controller_ll_acl_reserved);
159     controller_ll_acl_reserved = false;
160     ll_queue_acl_packet(packet, size);
161 }
162 
163 static void transport_emit_hci_event(const hci_event_t * event, ...){
164     va_list argptr;
165     va_start(argptr, event);
166     uint16_t length = hci_event_create_from_template_and_arglist(hci_outgoing_event, event, argptr);
167     va_end(argptr);
168     hci_packet_handler(HCI_EVENT_PACKET, hci_outgoing_event, length);
169 }
170 
171 static void transport_run(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
172 
173     // deliver command complete events caused by command processor
174     if (hci_outgoing_event_ready){
175         hci_outgoing_event_ready = false;
176         hci_packet_handler(HCI_EVENT_PACKET, hci_outgoing_event, hci_outgoing_event[1]+2);
177     }
178 
179     if (send_hardware_error != 0){
180         uint8_t error_code = send_hardware_error;
181         send_hardware_error = 0;
182         transport_emit_hci_event(&hci_event_hardware_error, error_code);
183     }
184 
185     if (send_transport_sent){
186         send_transport_sent = false;
187         // notify upper stack that it might be possible to send again
188         transport_emit_hci_event(&hci_event_transport_packet_sent);
189     }
190 
191     ll_execute_once();
192 }
193 
194 static void transport_packet_handler(uint8_t packet_type, uint8_t * packet, uint16_t size){
195     // just forward to hci
196     (*hci_packet_handler)(packet_type, packet, size);
197 }
198 
199 /**
200  * init transport
201  * @param transport_config
202  */
203 static void transport_init(const void *transport_config){
204     UNUSED(transport_config);
205     ll_register_packet_handler(&transport_packet_handler);
206 }
207 
208 /**
209  * open transport connection
210  */
211 static int transport_open(void){
212     btstack_run_loop_set_data_source_handler(&hci_transport_data_source, &transport_run);
213     btstack_run_loop_enable_data_source_callbacks(&hci_transport_data_source, DATA_SOURCE_CALLBACK_POLL);
214     btstack_run_loop_add_data_source(&hci_transport_data_source);
215 
216     ll_init();
217     ll_radio_on();
218 
219     return 0;
220 }
221 
222 /**
223  * close transport connection
224  */
225 static int transport_close(void){
226     btstack_run_loop_remove_data_source(&hci_transport_data_source);
227 
228     // TODO
229 
230     return 0;
231 }
232 
233 /**
234  * register packet handler for HCI packets: ACL, SCO, and Events
235  */
236 static void transport_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
237     hci_packet_handler = handler;
238 }
239 
240 static int transport_can_send_packet_now(uint8_t packet_type){
241     if (send_transport_sent) return 0;
242     switch (packet_type){
243         case HCI_COMMAND_DATA_PACKET:
244             return hci_outgoing_event_ready ? 0 : 1;
245         case HCI_ACL_DATA_PACKET:
246             if (controller_ll_acl_reserved == false){
247                 controller_ll_acl_reserved = ll_reserve_acl_packet();
248             }
249             return controller_ll_acl_reserved ? 1 : 0;
250         default:
251             btstack_assert(false);
252             break;
253     }
254     return 0;
255 }
256 
257 static int transport_send_packet(uint8_t packet_type, uint8_t *packet, int size){
258     switch (packet_type){
259         case HCI_COMMAND_DATA_PACKET:
260             controller_handle_hci_command(packet, size);
261             send_transport_sent = true;
262             break;
263         case HCI_ACL_DATA_PACKET:
264             controller_handle_acl_data(packet, size);
265             send_transport_sent = true;
266             break;
267         default:
268             send_hardware_error = 0x01; // invalid HCI packet
269             break;
270     }
271     return 0;
272 }
273 
274 void controller_init(void){
275 }
276 
277 static const hci_transport_t controller_transport = {
278         "sx1280-vhci",
279         &transport_init,
280         &transport_open,
281         &transport_close,
282         &transport_register_packet_handler,
283         &transport_can_send_packet_now,
284         &transport_send_packet,
285         NULL, // set baud rate
286         NULL, // reset link
287         NULL, // set SCO config
288 };
289 
290 const hci_transport_t * controller_get_hci_transport(void){
291     return &controller_transport;
292 }
293