xref: /btstack/src/hci_transport_em9304_spi.c (revision cd5f23a3250874824c01a2b3326a9522fea3f99f)
1 /*
2  * Copyright (C) 2014 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__ "hci_transport_em9304_spi.c"
39 
40 #include "btstack_config.h"
41 #include "btstack_em9304_spi.h"
42 
43 // EM9304 SPI Driver
44 static const btstack_em9304_spi_t * btstack_em9304_spi;
45 
46 /////////////////////////
47 // em9304 engine
48 #include "btstack_ring_buffer.h"
49 #include "btstack_debug.h"
50 #include "btstack_util.h"
51 #include "hci.h"
52 #include "hci_transport.h"
53 
54 static void em9304_spi_engine_run(void);
55 
56 #define STS_SLAVE_READY 0xc0
57 
58 #define EM9304_SPI_HEADER_TX        0x42
59 #define EM9304_SPI_HEADER_RX        0x81
60 
61 #define SPI_EM9304_BUFFER_SIZE        64
62 #define SPI_EM9304_RING_BUFFER_SIZE  128
63 
64 // state
65 static volatile enum {
66     SPI_EM9304_OFF,
67     SPI_EM9304_READY_FOR_TX,
68     SPI_EM9304_READY_FOR_TX_AND_RX,
69     SPI_EM9304_RX_W4_READ_COMMAND_SENT,
70     SPI_EM9304_RX_READ_COMMAND_SENT,
71     SPI_EM9304_RX_W4_STS2_RECEIVED,
72     SPI_EM9304_RX_STS2_RECEIVED,
73     SPI_EM9304_RX_W4_DATA_RECEIVED,
74     SPI_EM9304_RX_DATA_RECEIVED,
75     SPI_EM9304_TX_W4_RDY,
76     SPI_EM9304_TX_W4_WRITE_COMMAND_SENT,
77     SPI_EM9304_TX_WRITE_COMMAND_SENT,
78     SPI_EM9304_TX_W4_STS2_RECEIVED,
79     SPI_EM9304_TX_STS2_RECEIVED,
80     SPI_EM9304_TX_W4_DATA_SENT,
81     SPI_EM9304_TX_DATA_SENT,
82     SPI_EM9304_DONE,
83 } em9304_spi_engine_state;
84 
85 static uint16_t em9304_spi_engine_rx_request_len;
86 static uint16_t em9304_spi_engine_tx_request_len;
87 
88 static btstack_ring_buffer_t em9304_spi_engine_rx_ring_buffer;
89 
90 static uint8_t em9304_spi_engine_rx_ring_buffer_storage[SPI_EM9304_RING_BUFFER_SIZE];
91 
92 static const uint8_t  * em9304_spi_engine_tx_data;
93 static uint16_t         em9304_spi_engine_tx_size;
94 
95 // handlers
96 static void (*em9304_spi_engine_rx_available_handler)(void);
97 static void (*em9304_spi_engine_tx_done_handler)(void);
98 
99 // TODO: get rid of alignment requirement
100 union {
101     uint32_t words[1];
102     uint8_t  bytes[1];
103 } sCommand;
104 
105 union {
106     uint32_t words[1];
107     uint8_t  bytes[1];
108 } sStas;
109 
110 union {
111     uint32_t words[SPI_EM9304_BUFFER_SIZE/4];
112     uint8_t  bytes[SPI_EM9304_BUFFER_SIZE];
113 } em9304_spi_engine_spi_buffer;
114 
115 static void em9304_spi_engine_ready_callback(void){
116     // TODO: collect states
117     em9304_spi_engine_run();
118 }
119 
120 static void em9304_spi_engine_transfer_done(void){
121     switch (em9304_spi_engine_state){
122         case SPI_EM9304_RX_W4_READ_COMMAND_SENT:
123             em9304_spi_engine_state = SPI_EM9304_RX_READ_COMMAND_SENT;
124             break;
125         case SPI_EM9304_RX_W4_STS2_RECEIVED:
126             em9304_spi_engine_state = SPI_EM9304_RX_STS2_RECEIVED;
127             break;
128         case SPI_EM9304_RX_W4_DATA_RECEIVED:
129             em9304_spi_engine_state = SPI_EM9304_RX_DATA_RECEIVED;
130             break;
131         case SPI_EM9304_TX_W4_WRITE_COMMAND_SENT:
132             em9304_spi_engine_state = SPI_EM9304_TX_WRITE_COMMAND_SENT;
133             break;
134         case SPI_EM9304_TX_W4_STS2_RECEIVED:
135             em9304_spi_engine_state = SPI_EM9304_TX_STS2_RECEIVED;
136             break;
137         case SPI_EM9304_TX_W4_DATA_SENT:
138             em9304_spi_engine_state = SPI_EM9304_TX_DATA_SENT;
139             break;
140         default:
141             return;
142     }
143     em9304_spi_engine_run();
144 }
145 
146 static void em9304_spi_engine_start_tx_transaction(void){
147     // state = wait for RDY
148     em9304_spi_engine_state = SPI_EM9304_TX_W4_RDY;
149 
150     // chip select
151     btstack_em9304_spi->set_chip_select(1);
152 
153     // enable IRQ
154     btstack_em9304_spi->set_ready_callback(&em9304_spi_engine_ready_callback);
155 }
156 
157 static void em9304_spi_engine_start_rx_transaction(void){
158     // disable interrupt again
159     btstack_em9304_spi->set_ready_callback(NULL);
160 
161     // enable chip select
162     btstack_em9304_spi->set_chip_select(1);
163 
164     // send read command
165     em9304_spi_engine_state = SPI_EM9304_RX_W4_READ_COMMAND_SENT;
166     sCommand.bytes[0] = EM9304_SPI_HEADER_RX;
167     btstack_em9304_spi->transmit(sCommand.bytes, 1);
168 }
169 
170 static inline int em9304_engine_space_in_rx_buffer(void){
171     return btstack_ring_buffer_bytes_free(&em9304_spi_engine_rx_ring_buffer) >= SPI_EM9304_BUFFER_SIZE;
172 }
173 
174 static void em9304_engine_receive_buffer_ready(void){
175     // no data ready for receive or transmit, but space in rx ringbuffer  -> enable READY IRQ
176     em9304_spi_engine_state = SPI_EM9304_READY_FOR_TX_AND_RX;
177     btstack_em9304_spi->set_ready_callback(&em9304_spi_engine_ready_callback);
178     // avoid dead lock, check READY again
179     if (btstack_em9304_spi->get_ready()){
180         em9304_spi_engine_start_rx_transaction();
181     }
182 }
183 
184 static void em9304_engine_start_next_transaction(void){
185 
186     switch (em9304_spi_engine_state){
187         case SPI_EM9304_READY_FOR_TX:
188         case SPI_EM9304_READY_FOR_TX_AND_RX:
189         case SPI_EM9304_DONE:
190             break;
191         default:
192             return;
193     }
194 
195     if (btstack_em9304_spi->get_ready() && em9304_engine_space_in_rx_buffer()) {
196         em9304_spi_engine_start_rx_transaction();
197     } else if (em9304_spi_engine_tx_size){
198         em9304_spi_engine_start_tx_transaction();
199     } else if (em9304_engine_space_in_rx_buffer()){
200         em9304_engine_receive_buffer_ready();
201     }
202 }
203 
204 static void em9304_engine_action_done(void){
205     // chip deselect & done
206     btstack_em9304_spi->set_chip_select(0);
207     em9304_spi_engine_state = SPI_EM9304_DONE;
208 }
209 
210 static void em9304_spi_engine_run(void){
211     uint16_t max_bytes_to_send;
212     switch (em9304_spi_engine_state){
213 
214         case SPI_EM9304_READY_FOR_TX_AND_RX:
215             // check if ready
216             if (!btstack_em9304_spi->get_ready()) break;
217             em9304_spi_engine_start_rx_transaction();
218             break;
219 
220         case SPI_EM9304_RX_READ_COMMAND_SENT:
221             em9304_spi_engine_state = SPI_EM9304_RX_W4_STS2_RECEIVED;
222             btstack_em9304_spi->receive(sStas.bytes, 1);
223             break;
224 
225         case SPI_EM9304_RX_STS2_RECEIVED:
226             // check slave status
227             log_debug("RX: STS2 0x%02X", sStas.bytes[0]);
228 
229             // read data
230             em9304_spi_engine_state = SPI_EM9304_RX_W4_DATA_RECEIVED;
231             em9304_spi_engine_rx_request_len = sStas.bytes[0];
232             btstack_em9304_spi->receive(em9304_spi_engine_spi_buffer.bytes, em9304_spi_engine_rx_request_len);
233             break;
234 
235         case SPI_EM9304_RX_DATA_RECEIVED:
236             // done
237             em9304_engine_action_done();
238 
239             // move data into ring buffer
240             btstack_ring_buffer_write(&em9304_spi_engine_rx_ring_buffer, em9304_spi_engine_spi_buffer.bytes, em9304_spi_engine_rx_request_len);
241             em9304_spi_engine_rx_request_len = 0;
242 
243             // notify about new data available -- assume empty
244             (*em9304_spi_engine_rx_available_handler)();
245 
246             // next
247             em9304_engine_start_next_transaction();
248             break;
249 
250         case SPI_EM9304_TX_W4_RDY:
251             // check if ready
252             if (!btstack_em9304_spi->get_ready()) break;
253 
254             // disable interrupt again
255             btstack_em9304_spi->set_ready_callback(NULL);
256 
257             // send write command
258             em9304_spi_engine_state = SPI_EM9304_TX_W4_WRITE_COMMAND_SENT;
259             sCommand.bytes[0] = EM9304_SPI_HEADER_TX;
260             btstack_em9304_spi->transmit(sCommand.bytes, 1);
261             break;
262 
263         case SPI_EM9304_TX_WRITE_COMMAND_SENT:
264             em9304_spi_engine_state = SPI_EM9304_TX_W4_STS2_RECEIVED;
265             btstack_em9304_spi->receive(sStas.bytes, 1);
266             break;
267 
268         case SPI_EM9304_TX_STS2_RECEIVED:
269             // check slave status and em9304 rx buffer space
270             log_debug("TX: STS2 0x%02X", sStas.bytes[0]);
271             max_bytes_to_send = sStas.bytes[0];
272             if (max_bytes_to_send == 0u){
273                 // done
274                 em9304_engine_action_done();
275                 // next
276                 em9304_engine_start_next_transaction();
277                 break;
278             }
279 
280             // number bytes to send
281             em9304_spi_engine_tx_request_len = btstack_min(em9304_spi_engine_tx_size, max_bytes_to_send);
282 
283             // send command
284             em9304_spi_engine_state = SPI_EM9304_TX_W4_DATA_SENT;
285             if ( (((uintptr_t) em9304_spi_engine_tx_data) & 0x03u) == 0u){
286                 // 4-byte aligned
287                 btstack_em9304_spi->transmit( (uint8_t*) em9304_spi_engine_tx_data, em9304_spi_engine_tx_request_len);
288             } else {
289                 // TODO: get rid of alignment requirement
290                 // enforce alignment by copying to spi buffer first
291                 (void)memcpy(em9304_spi_engine_spi_buffer.bytes,
292                              em9304_spi_engine_tx_data,
293                              em9304_spi_engine_tx_request_len);
294                 btstack_em9304_spi->transmit( (uint8_t*) em9304_spi_engine_spi_buffer.bytes, em9304_spi_engine_tx_request_len);
295             }
296             break;
297 
298         case SPI_EM9304_TX_DATA_SENT:
299             // done
300             em9304_engine_action_done();
301 
302             // chunk sent
303             em9304_spi_engine_tx_size -= em9304_spi_engine_tx_request_len;
304             em9304_spi_engine_tx_data += em9304_spi_engine_tx_request_len;
305             em9304_spi_engine_tx_request_len = 0;
306 
307             // notify higher layer when complete
308             if (em9304_spi_engine_tx_size == 0u){
309                 (*em9304_spi_engine_tx_done_handler)();
310             }
311 
312             // next
313             em9304_engine_start_next_transaction();
314             break;
315 
316         default:
317             break;
318     }
319 }
320 
321 static void em9304_spi_engine_init(void){
322     btstack_em9304_spi->open();
323     btstack_em9304_spi->set_transfer_done_callback(&em9304_spi_engine_transfer_done);
324     btstack_ring_buffer_init(&em9304_spi_engine_rx_ring_buffer, &em9304_spi_engine_rx_ring_buffer_storage[0], SPI_EM9304_RING_BUFFER_SIZE);
325     em9304_spi_engine_state = SPI_EM9304_DONE;
326     em9304_engine_start_next_transaction();
327 }
328 
329 static void em9304_spi_engine_close(void){
330     em9304_spi_engine_state = SPI_EM9304_OFF;
331     btstack_em9304_spi->close();
332 }
333 
334 static void em9304_spi_engine_set_data_available( void (*the_block_handler)(void)){
335     em9304_spi_engine_rx_available_handler = the_block_handler;
336 }
337 
338 static void em9304_spi_engine_set_block_sent( void (*the_block_handler)(void)){
339     em9304_spi_engine_tx_done_handler = the_block_handler;
340 }
341 
342 static void em9304_spi_engine_send_block(const uint8_t *buffer, uint16_t length){
343     em9304_spi_engine_tx_data = buffer;
344     em9304_spi_engine_tx_size = length;
345     em9304_engine_start_next_transaction();
346 }
347 
348 static uint16_t em9304_engine_num_bytes_available(void){
349     return btstack_ring_buffer_bytes_available(&em9304_spi_engine_rx_ring_buffer);
350 }
351 
352 static void em9304_engine_get_bytes(uint8_t * buffer, uint16_t num_bytes){
353     uint32_t bytes_read;
354     btstack_ring_buffer_read(&em9304_spi_engine_rx_ring_buffer, buffer, num_bytes, &bytes_read);
355 }
356 
357 //////////////////////////////////////////////////////////////////////////////
358 
359 // assert pre-buffer for packet type is available
360 #if !defined(HCI_OUTGOING_PRE_BUFFER_SIZE) || (HCI_OUTGOING_PRE_BUFFER_SIZE == 0)
361 #error HCI_OUTGOING_PRE_BUFFER_SIZE not defined. Please update hci.h
362 #endif
363 
364 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size);
365 
366 typedef enum {
367     H4_W4_PACKET_TYPE,
368     H4_W4_EVENT_HEADER,
369     H4_W4_ACL_HEADER,
370     H4_W4_PAYLOAD,
371 } H4_STATE;
372 
373 typedef enum {
374     TX_IDLE = 1,
375     TX_W4_PACKET_SENT,
376 } TX_STATE;
377 
378 // write state
379 static TX_STATE tx_state;
380 
381 static  void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler;
382 
383 // packet reader state machine
384 static H4_STATE hci_transport_em9304_h4_state;
385 static uint16_t hci_transport_em9304_spi_bytes_to_read;
386 static uint16_t hci_transport_em9304_spi_read_pos;
387 
388 // incoming packet buffer
389 static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + HCI_INCOMING_PACKET_BUFFER_SIZE + 1]; // packet type + max(acl header + acl payload, event header + event data)
390 static uint8_t * hci_packet = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE];
391 
392 static void hci_transport_em9304_spi_block_read(void);
393 
394 static void hci_transport_em9304_spi_reset_statemachine(void){
395     hci_transport_em9304_h4_state = H4_W4_PACKET_TYPE;
396     hci_transport_em9304_spi_read_pos = 0;
397     hci_transport_em9304_spi_bytes_to_read = 1;
398 }
399 
400 static void hci_transport_em9304_spi_process_data(void){
401     while (true){
402 
403         uint16_t bytes_available = em9304_engine_num_bytes_available();
404         log_debug("transfer_rx_data: ring buffer has %u -> hci wants %u", bytes_available, hci_transport_em9304_spi_bytes_to_read);
405 
406         if (!bytes_available) break;
407         if (!hci_transport_em9304_spi_bytes_to_read) break;
408 
409         uint16_t bytes_to_copy = btstack_min(bytes_available, hci_transport_em9304_spi_bytes_to_read);
410         em9304_engine_get_bytes(&hci_packet[hci_transport_em9304_spi_read_pos], bytes_to_copy);
411 
412         hci_transport_em9304_spi_read_pos      += bytes_to_copy;
413         hci_transport_em9304_spi_bytes_to_read -= bytes_to_copy;
414 
415         if (hci_transport_em9304_spi_bytes_to_read == 0u){
416             hci_transport_em9304_spi_block_read();
417         }
418     }
419 }
420 
421 static void hci_transport_em9304_spi_packet_complete(void){
422     packet_handler(hci_packet[0u], &hci_packet[1u], hci_transport_em9304_spi_read_pos-1u);
423     hci_transport_em9304_spi_reset_statemachine();
424 }
425 
426 static void hci_transport_em9304_spi_block_read(void){
427     switch (hci_transport_em9304_h4_state) {
428         case H4_W4_PACKET_TYPE:
429             switch (hci_packet[0]){
430                 case HCI_EVENT_PACKET:
431                     hci_transport_em9304_spi_bytes_to_read = HCI_EVENT_HEADER_SIZE;
432                     hci_transport_em9304_h4_state = H4_W4_EVENT_HEADER;
433                     break;
434                 case HCI_ACL_DATA_PACKET:
435                     hci_transport_em9304_spi_bytes_to_read = HCI_ACL_HEADER_SIZE;
436                     hci_transport_em9304_h4_state = H4_W4_ACL_HEADER;
437                     break;
438                 default:
439                     log_error("invalid packet type 0x%02x", hci_packet[0]);
440                     hci_transport_em9304_spi_reset_statemachine();
441                     break;
442             }
443             break;
444 
445         case H4_W4_EVENT_HEADER:
446             hci_transport_em9304_spi_bytes_to_read = hci_packet[2];
447             // check Event length
448             if (hci_transport_em9304_spi_bytes_to_read > (HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_EVENT_HEADER_SIZE)){
449                 log_error("invalid Event len %d - only space for %u", hci_transport_em9304_spi_bytes_to_read, HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_EVENT_HEADER_SIZE);
450                 hci_transport_em9304_spi_reset_statemachine();
451                 break;
452             }
453             if (hci_transport_em9304_spi_bytes_to_read == 0u){
454                 hci_transport_em9304_spi_packet_complete();
455                 break;
456             }
457             hci_transport_em9304_h4_state = H4_W4_PAYLOAD;
458             break;
459 
460         case H4_W4_ACL_HEADER:
461             hci_transport_em9304_spi_bytes_to_read = little_endian_read_16( hci_packet, 3);
462             // check ACL length
463             if (hci_transport_em9304_spi_bytes_to_read > (HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_ACL_HEADER_SIZE)){
464                 log_error("invalid ACL payload len %d - only space for %u", hci_transport_em9304_spi_bytes_to_read, HCI_INCOMING_PACKET_BUFFER_SIZE - HCI_ACL_HEADER_SIZE);
465                 hci_transport_em9304_spi_reset_statemachine();
466                 break;
467             }
468             if (hci_transport_em9304_spi_bytes_to_read == 0u){
469                 hci_transport_em9304_spi_packet_complete();
470                 break;
471             }
472             hci_transport_em9304_h4_state = H4_W4_PAYLOAD;
473             break;
474 
475         case H4_W4_PAYLOAD:
476             hci_transport_em9304_spi_packet_complete();
477             break;
478         default:
479             break;
480     }
481 }
482 
483 static void hci_transport_em9304_spi_block_sent(void){
484 
485     static const uint8_t packet_sent_event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0};
486 
487     switch (tx_state){
488         case TX_W4_PACKET_SENT:
489             // packet fully sent, reset state
490             tx_state = TX_IDLE;
491             // notify upper stack that it can send again
492             packet_handler(HCI_EVENT_PACKET, (uint8_t *) &packet_sent_event[0], sizeof(packet_sent_event));
493             break;
494         default:
495             break;
496     }
497 }
498 
499 static int hci_transport_em9304_spi_can_send_now(uint8_t packet_type){
500     UNUSED(packet_type);
501     return tx_state == TX_IDLE;
502 }
503 
504 static int hci_transport_em9304_spi_send_packet(uint8_t packet_type, uint8_t * packet, int size){
505 
506     // store packet type before actual data and increase size
507     size++;
508     packet--;
509     *packet = packet_type;
510 
511     // start sending
512     tx_state = TX_W4_PACKET_SENT;
513     em9304_spi_engine_send_block(packet, size);
514     return 0;
515 }
516 
517 static void hci_transport_em9304_spi_init(const void * transport_config){
518     UNUSED(transport_config);
519 }
520 
521 static int hci_transport_em9304_spi_open(void){
522 
523     // setup UART driver
524     em9304_spi_engine_init();
525     em9304_spi_engine_set_data_available(&hci_transport_em9304_spi_process_data);
526     em9304_spi_engine_set_block_sent(&hci_transport_em9304_spi_block_sent);
527     // setup H4 RX
528     hci_transport_em9304_spi_reset_statemachine();
529     // setup H4 TX
530     tx_state = TX_IDLE;
531     return 0;
532 }
533 
534 static int hci_transport_em9304_spi_close(void){
535     em9304_spi_engine_close();
536     return 0;
537 }
538 
539 static void hci_transport_em9304_spi_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
540     packet_handler = handler;
541 }
542 
543 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
544     UNUSED(packet_type);
545     UNUSED(packet);
546     UNUSED(size);
547 }
548 
549 // --- end of eHCILL implementation ---------
550 
551 // configure and return h4 singleton
552 const hci_transport_t * hci_transport_em9304_spi_instance(const btstack_em9304_spi_t * em9304_spi_driver) {
553 
554     static const hci_transport_t hci_transport_em9304_spi = {
555             /* const char * name; */                                        "H4",
556             /* void   (*init) (const void *transport_config); */            &hci_transport_em9304_spi_init,
557             /* int    (*open)(void); */                                     &hci_transport_em9304_spi_open,
558             /* int    (*close)(void); */                                    &hci_transport_em9304_spi_close,
559             /* void   (*register_packet_handler)(void (*handler)(...); */   &hci_transport_em9304_spi_register_packet_handler,
560             /* int    (*can_send_packet_now)(uint8_t packet_type); */       &hci_transport_em9304_spi_can_send_now,
561             /* int    (*send_packet)(...); */                               &hci_transport_em9304_spi_send_packet,
562             /* int    (*set_baudrate)(uint32_t baudrate); */                NULL,
563             /* void   (*reset_link)(void); */                               NULL,
564             /* void   (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL,
565     };
566 
567     btstack_em9304_spi = em9304_spi_driver;
568     return &hci_transport_em9304_spi;
569 }
570