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