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