xref: /btstack/src/hci_transport_em9304_spi.c (revision 161a556908bc40ab3ce9e008590628b4a7c5b114)
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_process(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_RX_BUFFER_SIZE     64
62 #define SPI_EM9304_TX_BUFFER_SIZE     64
63 #define SPI_EM9304_RING_BUFFER_SIZE  128
64 
65 // state
66 static volatile enum {
67     SPI_EM9304_IDLE,
68     SPI_EM9304_RX_W4_READ_COMMAND_SENT,
69     SPI_EM9304_RX_READ_COMMAND_SENT,
70     SPI_EM9304_RX_W4_STS2_RECEIVED,
71     SPI_EM9304_RX_STS2_RECEIVED,
72     SPI_EM9304_RX_W4_DATA_RECEIVED,
73     SPI_EM9304_RX_DATA_RECEIVED,
74     SPI_EM9304_TX_W4_RDY,
75     SPI_EM9304_TX_W4_WRITE_COMMAND_SENT,
76     SPI_EM9304_TX_WRITE_COMMAND_SENT,
77     SPI_EM9304_TX_W4_STS2_RECEIVED,
78     SPI_EM9304_TX_STS2_RECEIVED,
79     SPI_EM9304_TX_W4_DATA_SENT,
80     SPI_EM9304_TX_DATA_SENT,
81 } em9304_spi_engine_state;
82 
83 static uint16_t em9304_spi_engine_rx_request_len;
84 static uint16_t em9304_spi_engine_tx_request_len;
85 
86 static btstack_ring_buffer_t em9304_spi_engine_rx_ring_buffer;
87 static uint8_t em9304_spi_engine_rx_ring_buffer_storage[SPI_EM9304_RING_BUFFER_SIZE];
88 
89 static const uint8_t  * em9304_spi_engine_tx_data;
90 static uint16_t         em9304_spi_engine_tx_size;
91 
92 static uint8_t  * em9304_spi_engine_rx_buffer;
93 static uint16_t   em9304_spi_engine_rx_len;
94 
95 // handlers
96 static void (*em9304_spi_engine_rx_done_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_RX_BUFFER_SIZE/4];
112     uint8_t  bytes[SPI_EM9304_RX_BUFFER_SIZE];
113 } em9304_spi_engine_spi_rx_buffer;
114 
115 static void em9304_spi_engine_ready_callback(void){
116     em9304_spi_engine_process();
117 }
118 
119 static void em9304_spi_engine_transfer_done(void){
120     switch (em9304_spi_engine_state){
121         case SPI_EM9304_RX_W4_READ_COMMAND_SENT:
122             em9304_spi_engine_state = SPI_EM9304_RX_READ_COMMAND_SENT;
123             break;
124         case SPI_EM9304_RX_W4_STS2_RECEIVED:
125             em9304_spi_engine_state = SPI_EM9304_RX_STS2_RECEIVED;
126             break;
127         case SPI_EM9304_RX_W4_DATA_RECEIVED:
128             em9304_spi_engine_state = SPI_EM9304_RX_DATA_RECEIVED;
129             break;
130         case SPI_EM9304_TX_W4_WRITE_COMMAND_SENT:
131             em9304_spi_engine_state = SPI_EM9304_TX_WRITE_COMMAND_SENT;
132             break;
133         case SPI_EM9304_TX_W4_STS2_RECEIVED:
134             em9304_spi_engine_state = SPI_EM9304_TX_STS2_RECEIVED;
135             break;
136         case SPI_EM9304_TX_W4_DATA_SENT:
137             em9304_spi_engine_state = SPI_EM9304_TX_DATA_SENT;
138             break;
139         default:
140             return;
141     }
142     em9304_spi_engine_process();
143 }
144 
145 static void em9304_spi_engine_transfer_rx_data(void){
146     while (1){
147         int bytes_available = btstack_ring_buffer_bytes_available(&em9304_spi_engine_rx_ring_buffer);
148         log_debug("transfer_rx_data: ring buffer has %u -> hci buffer needs %u", bytes_available, em9304_spi_engine_rx_len);
149 
150         if (!bytes_available) break;
151         if (!em9304_spi_engine_rx_len) break;
152 
153         int bytes_to_copy = btstack_min(bytes_available, em9304_spi_engine_rx_len);
154         uint32_t bytes_read;
155         btstack_ring_buffer_read(&em9304_spi_engine_rx_ring_buffer, em9304_spi_engine_rx_buffer, bytes_to_copy, &bytes_read);
156         em9304_spi_engine_rx_buffer += bytes_read;
157         em9304_spi_engine_rx_len    -= bytes_read;
158 
159         if (em9304_spi_engine_rx_len == 0){
160             (*em9304_spi_engine_rx_done_handler)();
161             break;
162         }
163     }
164 }
165 
166 static void em9304_spi_engine_start_tx_transaction(void){
167     // state = wait for RDY
168     em9304_spi_engine_state = SPI_EM9304_TX_W4_RDY;
169 
170     // chip select
171     btstack_em9304_spi->set_chip_select(1);
172 
173     // enable IRQ
174     btstack_em9304_spi->set_ready_callback(&em9304_spi_engine_ready_callback);
175 }
176 
177 static void em9304_spi_engine_process(void){
178     uint16_t max_bytes_to_send;
179 
180     switch (em9304_spi_engine_state){
181         case SPI_EM9304_IDLE:
182             if (btstack_em9304_spi->get_ready()){
183                 // RDY -> data available
184                 if (btstack_ring_buffer_bytes_free(&em9304_spi_engine_rx_ring_buffer) >= SPI_EM9304_RX_BUFFER_SIZE) {
185 
186                     // disable interrupt again
187                     btstack_em9304_spi->set_ready_callback(NULL);
188                                 // enable chip select
189                     btstack_em9304_spi->set_chip_select(1);
190 
191                     // send read command
192                     em9304_spi_engine_state = SPI_EM9304_RX_W4_READ_COMMAND_SENT;
193                     sCommand.bytes[0] = EM9304_SPI_HEADER_RX;
194                     btstack_em9304_spi->transmit(sCommand.bytes, 1);
195                 }
196             } else if (em9304_spi_engine_tx_size){
197                 em9304_spi_engine_start_tx_transaction();
198             } else if (em9304_spi_engine_rx_len){
199                 // no data ready, no data to send, but read request -> enable IRQ
200                 btstack_em9304_spi->set_ready_callback(&em9304_spi_engine_ready_callback);
201             }
202             break;
203 
204         case SPI_EM9304_RX_READ_COMMAND_SENT:
205             em9304_spi_engine_state = SPI_EM9304_RX_W4_STS2_RECEIVED;
206             btstack_em9304_spi->receive(sStas.bytes, 1);
207             break;
208 
209         case SPI_EM9304_RX_STS2_RECEIVED:
210             // check slave status
211             log_debug("RX: STS2 0x%02X", sStas.bytes[0]);
212 
213             // read data and send '0's
214             em9304_spi_engine_state = SPI_EM9304_RX_W4_DATA_RECEIVED;
215             em9304_spi_engine_rx_request_len = sStas.bytes[0];
216             btstack_em9304_spi->receive(em9304_spi_engine_spi_rx_buffer.bytes, em9304_spi_engine_rx_request_len);
217             break;
218 
219         case SPI_EM9304_RX_DATA_RECEIVED:
220 
221             // chip deselect & done
222             btstack_em9304_spi->set_chip_select(0);
223             em9304_spi_engine_state = SPI_EM9304_IDLE;
224 
225             // move data into ring buffer
226             btstack_ring_buffer_write(&em9304_spi_engine_rx_ring_buffer, em9304_spi_engine_spi_rx_buffer.bytes, em9304_spi_engine_rx_request_len);
227             em9304_spi_engine_rx_request_len = 0;
228 
229             // deliver new data
230             em9304_spi_engine_transfer_rx_data();
231             break;
232 
233         case SPI_EM9304_TX_W4_RDY:
234             // check if ready
235             if (!btstack_em9304_spi->get_ready()) break;
236 
237             // disable interrupt again
238             btstack_em9304_spi->set_ready_callback(NULL);
239 
240             // send write command
241             em9304_spi_engine_state = SPI_EM9304_TX_W4_WRITE_COMMAND_SENT;
242             sCommand.bytes[0] = EM9304_SPI_HEADER_TX;
243             btstack_em9304_spi->transmit(sCommand.bytes, 1);
244             break;
245 
246         case SPI_EM9304_TX_WRITE_COMMAND_SENT:
247             em9304_spi_engine_state = SPI_EM9304_TX_W4_STS2_RECEIVED;
248             btstack_em9304_spi->receive(sStas.bytes, 1);
249             break;
250 
251         case SPI_EM9304_TX_STS2_RECEIVED:
252             // check slave status and em9304 rx buffer space
253             log_debug("TX: STS2 0x%02X", sStas.bytes[0]);
254             max_bytes_to_send = sStas.bytes[0];
255             if (max_bytes_to_send == 0){
256                 // chip deselect & retry
257                 btstack_em9304_spi->set_chip_select(0);
258                 em9304_spi_engine_state = SPI_EM9304_IDLE;
259                 break;
260             }
261 
262             // number bytes to send
263             em9304_spi_engine_tx_request_len = btstack_min(em9304_spi_engine_tx_size, max_bytes_to_send);
264 
265             // send command
266             em9304_spi_engine_state = SPI_EM9304_TX_W4_DATA_SENT;
267             btstack_em9304_spi->transmit( (uint8_t*) em9304_spi_engine_tx_data, em9304_spi_engine_tx_request_len);
268             break;
269 
270         case SPI_EM9304_TX_DATA_SENT:
271 
272             // chip deselect & done
273             btstack_em9304_spi->set_chip_select(0);
274             em9304_spi_engine_state = SPI_EM9304_IDLE;
275 
276             // chunk processed
277             em9304_spi_engine_tx_size -= em9304_spi_engine_tx_request_len;
278             em9304_spi_engine_tx_data += em9304_spi_engine_tx_request_len;
279             em9304_spi_engine_tx_request_len = 0;
280 
281             // handle TX Complete
282             if (em9304_spi_engine_tx_size){
283                 // more data to send
284                 em9304_spi_engine_start_tx_transaction();
285             } else {
286                 // notify higher layer
287                 (*em9304_spi_engine_tx_done_handler)();
288 
289                 // re-enable irq if read pending
290                 if (em9304_spi_engine_rx_len){
291                     // no data ready, no data to send, but read request -> enable IRQ
292                     btstack_em9304_spi->set_ready_callback(&em9304_spi_engine_ready_callback);
293                 }
294             }
295             break;
296 
297         default:
298             break;
299     }
300 }
301 
302 static void em9304_spi_engine_init(void){
303     btstack_em9304_spi->open();
304     btstack_em9304_spi->set_transfer_done_callback(&em9304_spi_engine_transfer_done);
305     btstack_ring_buffer_init(&em9304_spi_engine_rx_ring_buffer, &em9304_spi_engine_rx_ring_buffer_storage[0], SPI_EM9304_RING_BUFFER_SIZE);
306 }
307 
308 static void em9304_spi_engine_close(void){
309     btstack_em9304_spi->close();
310 }
311 
312 static void em9304_spi_engine_set_block_received( void (*the_block_handler)(void)){
313     em9304_spi_engine_rx_done_handler = the_block_handler;
314 }
315 
316 static void em9304_spi_engine_set_block_sent( void (*the_block_handler)(void)){
317     em9304_spi_engine_tx_done_handler = the_block_handler;
318 }
319 
320 static void em9304_spi_engine_send_block(const uint8_t *buffer, uint16_t length){
321     em9304_spi_engine_tx_data = buffer;
322     em9304_spi_engine_tx_size = length;
323     em9304_spi_engine_process();
324 }
325 
326 static void em9304_spi_engine_receive_block(uint8_t *buffer, uint16_t length){
327     log_debug("em9304_spi_engine_receive_block: len %u, ring buffer has %u, UART_RX_LEN %u", length, btstack_ring_buffer_bytes_available(&em9304_spi_engine_rx_ring_buffer), em9304_spi_engine_rx_len);
328     em9304_spi_engine_rx_buffer = buffer;
329     em9304_spi_engine_rx_len    = length;
330     em9304_spi_engine_transfer_rx_data();
331     em9304_spi_engine_process();
332 }
333 
334 //////////////////////////////////////////////////////////////////////////////
335 
336 // assert pre-buffer for packet type is available
337 #if !defined(HCI_OUTGOING_PRE_BUFFER_SIZE) || (HCI_OUTGOING_PRE_BUFFER_SIZE == 0)
338 #error HCI_OUTGOING_PRE_BUFFER_SIZE not defined. Please update hci.h
339 #endif
340 
341 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size);
342 
343 typedef enum {
344     H4_W4_PACKET_TYPE,
345     H4_W4_EVENT_HEADER,
346     H4_W4_ACL_HEADER,
347     H4_W4_PAYLOAD,
348 } H4_STATE;
349 
350 typedef enum {
351     TX_IDLE = 1,
352     TX_W4_PACKET_SENT,
353 } TX_STATE;
354 
355 // write state
356 static TX_STATE tx_state;
357 
358 static uint8_t packet_sent_event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0};
359 
360 static  void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler;
361 
362 // packet reader state machine
363 static  H4_STATE h4_state;
364 static int bytes_to_read;
365 static int read_pos;
366 
367 // incoming packet buffer
368 static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + 1 + HCI_PACKET_BUFFER_SIZE]; // packet type + max(acl header + acl payload, event header + event data)
369 static uint8_t * hci_packet = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE];
370 
371 static void hci_transport_em9304_spi_reset_statemachine(void){
372     h4_state = H4_W4_PACKET_TYPE;
373     read_pos = 0;
374     bytes_to_read = 1;
375 }
376 
377 static void hci_transport_em9304_spi_trigger_next_read(void){
378     // log_info("hci_transport_em9304_spi_trigger_next_read: %u bytes", bytes_to_read);
379     em9304_spi_engine_receive_block(&hci_packet[read_pos], bytes_to_read);
380 }
381 
382 static void hci_transport_em9304_spi_block_read(void){
383 
384     read_pos += bytes_to_read;
385 
386     switch (h4_state) {
387         case H4_W4_PACKET_TYPE:
388             switch (hci_packet[0]){
389                 case HCI_EVENT_PACKET:
390                     bytes_to_read = HCI_EVENT_HEADER_SIZE;
391                     h4_state = H4_W4_EVENT_HEADER;
392                     break;
393                 case HCI_ACL_DATA_PACKET:
394                     bytes_to_read = HCI_ACL_HEADER_SIZE;
395                     h4_state = H4_W4_ACL_HEADER;
396                     break;
397                 default:
398                     log_error("hci_transport_h4: invalid packet type 0x%02x", hci_packet[0]);
399                     hci_transport_em9304_spi_reset_statemachine();
400                     break;
401             }
402             break;
403 
404         case H4_W4_EVENT_HEADER:
405             bytes_to_read = hci_packet[2];
406             h4_state = H4_W4_PAYLOAD;
407             break;
408 
409         case H4_W4_ACL_HEADER:
410             bytes_to_read = little_endian_read_16( hci_packet, 3);
411             // check ACL length
412             if (HCI_ACL_HEADER_SIZE + bytes_to_read >  HCI_PACKET_BUFFER_SIZE){
413                 log_error("hci_transport_h4: invalid ACL payload len %d - only space for %u", bytes_to_read, HCI_PACKET_BUFFER_SIZE - HCI_ACL_HEADER_SIZE);
414                 hci_transport_em9304_spi_reset_statemachine();
415                 break;
416             }
417             h4_state = H4_W4_PAYLOAD;
418             break;
419 
420         case H4_W4_PAYLOAD:
421             packet_handler(hci_packet[0], &hci_packet[1], read_pos-1);
422             hci_transport_em9304_spi_reset_statemachine();
423             break;
424         default:
425             break;
426     }
427 
428     hci_transport_em9304_spi_trigger_next_read();
429 }
430 
431 static void hci_transport_em9304_spi_block_sent(void){
432     switch (tx_state){
433         case TX_W4_PACKET_SENT:
434             // packet fully sent, reset state
435             tx_state = TX_IDLE;
436             // notify upper stack that it can send again
437             packet_handler(HCI_EVENT_PACKET, &packet_sent_event[0], sizeof(packet_sent_event));
438             break;
439         default:
440             break;
441     }
442 }
443 
444 static int hci_transport_em9304_spi_can_send_now(uint8_t packet_type){
445     return tx_state == TX_IDLE;
446 }
447 
448 static int hci_transport_em9304_spi_send_packet(uint8_t packet_type, uint8_t * packet, int size){
449 
450     // store packet type before actual data and increase size
451     size++;
452     packet--;
453     *packet = packet_type;
454 
455     // start sending
456     tx_state = TX_W4_PACKET_SENT;
457     em9304_spi_engine_send_block(packet, size);
458     return 0;
459 }
460 
461 static void hci_transport_em9304_spi_init(const void * transport_config){
462 }
463 
464 static int hci_transport_em9304_spi_open(void){
465 
466     // setup UART driver
467     em9304_spi_engine_init();
468     em9304_spi_engine_set_block_received(&hci_transport_em9304_spi_block_read);
469     em9304_spi_engine_set_block_sent(&hci_transport_em9304_spi_block_sent);
470     // setup H4 RX
471     hci_transport_em9304_spi_reset_statemachine();
472     hci_transport_em9304_spi_trigger_next_read();
473     // setup H4 TX
474     tx_state = TX_IDLE;
475     return 0;
476 }
477 
478 static int hci_transport_em9304_spi_close(void){
479     em9304_spi_engine_close();
480     return 0;
481 }
482 
483 static void hci_transport_em9304_spi_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
484     packet_handler = handler;
485 }
486 
487 static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
488 }
489 
490 // --- end of eHCILL implementation ---------
491 
492 static const hci_transport_t hci_transport_em9304_spi = {
493     /* const char * name; */                                        "H4",
494     /* void   (*init) (const void *transport_config); */            &hci_transport_em9304_spi_init,
495     /* int    (*open)(void); */                                     &hci_transport_em9304_spi_open,
496     /* int    (*close)(void); */                                    &hci_transport_em9304_spi_close,
497     /* void   (*register_packet_handler)(void (*handler)(...); */   &hci_transport_em9304_spi_register_packet_handler,
498     /* int    (*can_send_packet_now)(uint8_t packet_type); */       &hci_transport_em9304_spi_can_send_now,
499     /* int    (*send_packet)(...); */                               &hci_transport_em9304_spi_send_packet,
500     /* int    (*set_baudrate)(uint32_t baudrate); */                NULL,
501     /* void   (*reset_link)(void); */                               NULL,
502     /* void   (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL,
503 };
504 
505 // configure and return h4 singleton
506 const hci_transport_t * hci_transport_em9304_spi_instance(const btstack_em9304_spi_t * em9304_spi_driver) {
507     btstack_em9304_spi = em9304_spi_driver;
508     return &hci_transport_em9304_spi;
509 }
510