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