xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/transport/uart/src/ble_hci_uart.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <assert.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <errno.h>
24 #include <stdint.h>
25 #include "sysinit/sysinit.h"
26 #include "syscfg/syscfg.h"
27 #include "os/os_cputime.h"
28 #include "bsp/bsp.h"
29 #include "os/os.h"
30 #include "mem/mem.h"
31 #include "hal/hal_gpio.h"
32 #include "hal/hal_uart.h"
33 
34 /* BLE */
35 #include "nimble/ble.h"
36 #include "nimble/nimble_opt.h"
37 #include "nimble/hci_common.h"
38 #include "nimble/ble_hci_trans.h"
39 
40 #include "transport/uart/ble_hci_uart.h"
41 
42 #define BLE_HCI_UART_EVT_COUNT  \
43     (MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT) + MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT))
44 
45 /***
46  * NOTES:
47  * The UART HCI transport doesn't use event buffer priorities.  All incoming
48  * and outgoing events use buffers from the same pool.
49  *
50  * The "skip" definitions are here so that when buffers cannot be allocated,
51  * the command or acl packets are simply skipped so that the HCI interface
52  * does not lose synchronization and resets dont (necessarily) occur.
53  */
54 
55 /* XXX: for now, define this here */
56 #if MYNEWT_VAL(BLE_DEVICE)
57 extern void ble_ll_data_buffer_overflow(void);
58 extern void ble_ll_hw_error(uint8_t err);
59 
60 static const uint8_t ble_hci_uart_reset_cmd[4] = { 0x01, 0x03, 0x0C, 0x00 };
61 #endif
62 
63 /***
64  * NOTES:
65  * The "skip" definitions are here so that when buffers cannot be allocated,
66  * the command or acl packets are simply skipped so that the HCI interface
67  * does not lose synchronization and resets dont (necessarily) occur.
68  */
69 #define BLE_HCI_UART_H4_NONE        0x00
70 #define BLE_HCI_UART_H4_CMD         0x01
71 #define BLE_HCI_UART_H4_ACL         0x02
72 #define BLE_HCI_UART_H4_SCO         0x03
73 #define BLE_HCI_UART_H4_EVT         0x04
74 #define BLE_HCI_UART_H4_SYNC_LOSS   0x80
75 #define BLE_HCI_UART_H4_SKIP_CMD    0x81
76 #define BLE_HCI_UART_H4_SKIP_ACL    0x82
77 #define BLE_HCI_UART_H4_LE_EVT      0x83
78 #define BLE_HCI_UART_H4_SKIP_EVT    0x84
79 
80 static ble_hci_trans_rx_cmd_fn *ble_hci_uart_rx_cmd_cb;
81 static void *ble_hci_uart_rx_cmd_arg;
82 
83 static ble_hci_trans_rx_acl_fn *ble_hci_uart_rx_acl_cb;
84 static void *ble_hci_uart_rx_acl_arg;
85 
86 static struct os_mempool ble_hci_uart_evt_hi_pool;
87 static os_membuf_t ble_hci_uart_evt_hi_buf[
88         OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
89                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
90 ];
91 
92 static struct os_mempool ble_hci_uart_evt_lo_pool;
93 static os_membuf_t ble_hci_uart_evt_lo_buf[
94         OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
95                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
96 ];
97 
98 static struct os_mempool ble_hci_uart_cmd_pool;
99 static os_membuf_t ble_hci_uart_cmd_buf[
100 	OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ)
101 ];
102 
103 static struct os_mbuf_pool ble_hci_uart_acl_mbuf_pool;
104 static struct os_mempool_ext ble_hci_uart_acl_pool;
105 
106 /*
107  * The MBUF payload size must accommodate the HCI data header size plus the
108  * maximum ACL data packet length. The ACL block size is the size of the
109  * mbufs we will allocate.
110  */
111 #define ACL_BLOCK_SIZE  OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) \
112                                  + BLE_MBUF_MEMBLOCK_OVERHEAD \
113                                  + BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
114 
115 static os_membuf_t ble_hci_uart_acl_buf[
116 	OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_ACL_BUF_COUNT),
117                         ACL_BLOCK_SIZE)
118 ];
119 
120 /**
121  * A packet to be sent over the UART.  This can be a command, an event, or ACL
122  * data.
123  */
124 struct ble_hci_uart_pkt {
125     STAILQ_ENTRY(ble_hci_uart_pkt) next;
126     void *data;
127     uint8_t type;
128 };
129 
130 static struct os_mempool ble_hci_uart_pkt_pool;
131 static os_membuf_t ble_hci_uart_pkt_buf[
132         OS_MEMPOOL_SIZE(BLE_HCI_UART_EVT_COUNT + 1 +
133                         MYNEWT_VAL(BLE_HCI_ACL_OUT_COUNT),
134                         sizeof (struct ble_hci_uart_pkt))
135 ];
136 
137 /**
138  * An incoming or outgoing command or event.
139  */
140 struct ble_hci_uart_cmd {
141     uint8_t *data;      /* Pointer to ble_hci_uart_cmd data */
142     uint16_t cur;       /* Number of bytes read/written */
143     uint16_t len;       /* Total number of bytes to read/write */
144 };
145 
146 /**
147  * An incoming ACL data packet.
148  */
149 struct ble_hci_uart_acl {
150     struct os_mbuf *buf; /* Buffer containing the data */
151     uint8_t *dptr;       /* Pointer to where bytes should be placed */
152     uint16_t len;        /* Target size when buf is considered complete */
153     uint16_t rxd_bytes;  /* current count of bytes received for packet */
154 };
155 
156 /**
157  * Structure for transmitting ACL packets over UART
158  *
159  */
160 struct ble_hci_uart_h4_acl_tx
161 {
162     uint8_t *dptr;
163     struct os_mbuf *tx_acl;
164 };
165 
166 static struct {
167     /*** State of data received over UART. */
168     uint8_t rx_type;    /* Pending packet type. 0 means nothing pending */
169     union {
170         struct ble_hci_uart_cmd rx_cmd;
171         struct ble_hci_uart_acl rx_acl;
172     };
173 
174     /*** State of data transmitted over UART. */
175     uint8_t tx_type;    /* Pending packet type. 0 means nothing pending */
176     uint16_t rem_tx_len; /* Used for acl tx only currently */
177     union {
178         struct ble_hci_uart_cmd tx_cmd;
179         struct ble_hci_uart_h4_acl_tx tx_pkt;
180     };
181     STAILQ_HEAD(, ble_hci_uart_pkt) tx_pkts; /* Packet queue to send to UART */
182 } ble_hci_uart_state;
183 
184 /**
185  * Allocates a buffer (mbuf) for ACL operation.
186  *
187  * @return                      The allocated buffer on success;
188  *                              NULL on buffer exhaustion.
189  */
190 static struct os_mbuf *
ble_hci_trans_acl_buf_alloc(void)191 ble_hci_trans_acl_buf_alloc(void)
192 {
193     struct os_mbuf *m;
194     uint8_t usrhdr_len;
195 
196 #if MYNEWT_VAL(BLE_DEVICE)
197     usrhdr_len = sizeof(struct ble_mbuf_hdr);
198 #elif MYNEWT_VAL(BLE_HS_FLOW_CTRL)
199     usrhdr_len = BLE_MBUF_HS_HDR_LEN;
200 #else
201     usrhdr_len = 0;
202 #endif
203 
204     m = os_mbuf_get_pkthdr(&ble_hci_uart_acl_mbuf_pool, usrhdr_len);
205     return m;
206 }
207 
208 static int
ble_hci_uart_acl_tx(struct os_mbuf * om)209 ble_hci_uart_acl_tx(struct os_mbuf *om)
210 {
211     struct ble_hci_uart_pkt *pkt;
212     os_sr_t sr;
213 
214     /* If this packet is zero length, just free it */
215     if (OS_MBUF_PKTLEN(om) == 0) {
216         os_mbuf_free_chain(om);
217         return 0;
218     }
219 
220     pkt = os_memblock_get(&ble_hci_uart_pkt_pool);
221     if (pkt == NULL) {
222         os_mbuf_free_chain(om);
223         return BLE_ERR_MEM_CAPACITY;
224     }
225 
226     pkt->type = BLE_HCI_UART_H4_ACL;
227     pkt->data = om;
228 
229     OS_ENTER_CRITICAL(sr);
230     STAILQ_INSERT_TAIL(&ble_hci_uart_state.tx_pkts, pkt, next);
231     OS_EXIT_CRITICAL(sr);
232 
233     hal_uart_start_tx(MYNEWT_VAL(BLE_HCI_UART_PORT));
234 
235     return 0;
236 }
237 
238 static int
ble_hci_uart_cmdevt_tx(uint8_t * hci_ev,uint8_t h4_type)239 ble_hci_uart_cmdevt_tx(uint8_t *hci_ev, uint8_t h4_type)
240 {
241     struct ble_hci_uart_pkt *pkt;
242     os_sr_t sr;
243 
244     pkt = os_memblock_get(&ble_hci_uart_pkt_pool);
245     if (pkt == NULL) {
246         ble_hci_trans_buf_free(hci_ev);
247         return BLE_ERR_MEM_CAPACITY;
248     }
249 
250     pkt->type = h4_type;
251     pkt->data = hci_ev;
252 
253     OS_ENTER_CRITICAL(sr);
254     STAILQ_INSERT_TAIL(&ble_hci_uart_state.tx_pkts, pkt, next);
255     OS_EXIT_CRITICAL(sr);
256 
257     hal_uart_start_tx(MYNEWT_VAL(BLE_HCI_UART_PORT));
258 
259     return 0;
260 }
261 
262 /**
263  * @return                      The packet type to transmit on success;
264  *                              -1 if there is nothing to send.
265  */
266 static int
ble_hci_uart_tx_pkt_type(void)267 ble_hci_uart_tx_pkt_type(void)
268 {
269     struct ble_hci_uart_pkt *pkt;
270     struct os_mbuf *om;
271     os_sr_t sr;
272     int rc;
273 
274     OS_ENTER_CRITICAL(sr);
275 
276     pkt = STAILQ_FIRST(&ble_hci_uart_state.tx_pkts);
277     if (!pkt) {
278         OS_EXIT_CRITICAL(sr);
279         return -1;
280     }
281 
282     STAILQ_REMOVE(&ble_hci_uart_state.tx_pkts, pkt, ble_hci_uart_pkt, next);
283 
284     OS_EXIT_CRITICAL(sr);
285 
286     rc = pkt->type;
287     switch (pkt->type) {
288     case BLE_HCI_UART_H4_CMD:
289         ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_CMD;
290         ble_hci_uart_state.tx_cmd.data = pkt->data;
291         ble_hci_uart_state.tx_cmd.cur = 0;
292         ble_hci_uart_state.tx_cmd.len = ble_hci_uart_state.tx_cmd.data[2] +
293                                         BLE_HCI_CMD_HDR_LEN;
294         break;
295 
296     case BLE_HCI_UART_H4_EVT:
297         ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_EVT;
298         ble_hci_uart_state.tx_cmd.data = pkt->data;
299         ble_hci_uart_state.tx_cmd.cur = 0;
300         ble_hci_uart_state.tx_cmd.len = ble_hci_uart_state.tx_cmd.data[1] +
301                                         BLE_HCI_EVENT_HDR_LEN;
302         break;
303 
304     case BLE_HCI_UART_H4_ACL:
305         ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_ACL;
306         om = (struct os_mbuf *)pkt->data;
307         /* NOTE: first mbuf must have non-zero length */
308         os_mbuf_trim_front(om);
309         ble_hci_uart_state.tx_pkt.tx_acl = om;
310         ble_hci_uart_state.tx_pkt.dptr = om->om_data;
311         ble_hci_uart_state.rem_tx_len = OS_MBUF_PKTLEN(om);
312         break;
313 
314     default:
315         rc = -1;
316         break;
317     }
318 
319     os_memblock_put(&ble_hci_uart_pkt_pool, pkt);
320 
321     return rc;
322 }
323 
324 /**
325  * @return                      The byte to transmit on success;
326  *                              -1 if there is nothing to send.
327  */
328 static int
ble_hci_uart_tx_char(void * arg)329 ble_hci_uart_tx_char(void *arg)
330 {
331     uint8_t u8;
332     int rc;
333     struct os_mbuf *om;
334 
335     switch (ble_hci_uart_state.tx_type) {
336     case BLE_HCI_UART_H4_NONE: /* No pending packet, pick one from the queue */
337         rc = ble_hci_uart_tx_pkt_type();
338         break;
339 
340     case BLE_HCI_UART_H4_CMD:
341     case BLE_HCI_UART_H4_EVT:
342         rc = ble_hci_uart_state.tx_cmd.data[ble_hci_uart_state.tx_cmd.cur++];
343 
344         if (ble_hci_uart_state.tx_cmd.cur == ble_hci_uart_state.tx_cmd.len) {
345             ble_hci_trans_buf_free(ble_hci_uart_state.tx_cmd.data);
346             ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_NONE;
347         }
348         break;
349 
350     case BLE_HCI_UART_H4_ACL:
351         /* Copy the first unsent byte from the tx buffer and remove it from the
352          * source.
353          */
354         u8 = ble_hci_uart_state.tx_pkt.dptr[0];
355         --ble_hci_uart_state.rem_tx_len;
356         if (ble_hci_uart_state.rem_tx_len == 0) {
357             os_mbuf_free_chain(ble_hci_uart_state.tx_pkt.tx_acl);
358             ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_NONE;
359         } else {
360             om = ble_hci_uart_state.tx_pkt.tx_acl;
361             --om->om_len;
362             if (om->om_len == 0) {
363                 /* Remove and free any zero mbufs */
364                 while ((om != NULL) && (om->om_len == 0)) {
365                     ble_hci_uart_state.tx_pkt.tx_acl = SLIST_NEXT(om, om_next);
366                     os_mbuf_free(om);
367                     om = ble_hci_uart_state.tx_pkt.tx_acl;
368                 }
369                 /* NOTE: om should never be NULL! What to do? */
370                 if (om == NULL) {
371                     assert(0);
372                     ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_NONE;
373                 } else {
374                     ble_hci_uart_state.tx_pkt.dptr = om->om_data;
375                 }
376             } else {
377                 ble_hci_uart_state.tx_pkt.dptr++;
378             }
379         }
380         rc = u8;
381         break;
382     default:
383         rc = -1;
384         break;
385     }
386 
387     return rc;
388 }
389 
390 #if MYNEWT_VAL(BLE_DEVICE)
391 /**
392  * HCI uart sync lost.
393  *
394  * This occurs when the controller receives an invalid packet type or a length
395  * field that is out of range. The controller needs to send a HW error to the
396  * host and wait to find a LL reset command.
397  */
398 static void
ble_hci_uart_sync_lost(void)399 ble_hci_uart_sync_lost(void)
400 {
401     ble_hci_uart_state.rx_cmd.len = 0;
402     ble_hci_uart_state.rx_cmd.cur = 0;
403     ble_hci_uart_state.rx_cmd.data =
404         ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
405     ble_ll_hw_error(BLE_HW_ERR_HCI_SYNC_LOSS);
406     ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_SYNC_LOSS;
407 }
408 #endif
409 
410 /**
411  * @return                      The type of packet to follow success;
412  *                              -1 if there is no valid packet to receive.
413  */
414 static int
ble_hci_uart_rx_pkt_type(uint8_t data)415 ble_hci_uart_rx_pkt_type(uint8_t data)
416 {
417     struct os_mbuf *m;
418 
419     ble_hci_uart_state.rx_type = data;
420 
421     switch (ble_hci_uart_state.rx_type) {
422     /* Host should never receive a command! */
423 #if MYNEWT_VAL(BLE_DEVICE)
424     case BLE_HCI_UART_H4_CMD:
425         ble_hci_uart_state.rx_cmd.len = 0;
426         ble_hci_uart_state.rx_cmd.cur = 0;
427         ble_hci_uart_state.rx_cmd.data =
428             ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
429         if (ble_hci_uart_state.rx_cmd.data == NULL) {
430             ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_SKIP_CMD;
431         }
432         break;
433 #endif
434 
435         /* Controller should never receive an event */
436 #if MYNEWT_VAL(BLE_HOST)
437     case BLE_HCI_UART_H4_EVT:
438         /*
439          * The event code is unknown at the moment. Depending on event priority,
440          * buffer *shall* be allocated from ble_hci_uart_evt_hi_pool
441          * or "may* be allocated from ble_hci_uart_evt_lo_pool.
442          * Thus do not allocate the buffer yet.
443          */
444         ble_hci_uart_state.rx_cmd.data = NULL;
445         ble_hci_uart_state.rx_cmd.len = 0;
446         ble_hci_uart_state.rx_cmd.cur = 0;
447         break;
448 #endif
449 
450     case BLE_HCI_UART_H4_ACL:
451         ble_hci_uart_state.rx_acl.len = 0;
452         ble_hci_uart_state.rx_acl.rxd_bytes = 0;
453         m = ble_hci_trans_acl_buf_alloc();
454         if (m) {
455             ble_hci_uart_state.rx_acl.dptr = m->om_data;
456         } else {
457             ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_SKIP_ACL;
458         }
459         ble_hci_uart_state.rx_acl.buf = m;
460         break;
461 
462     default:
463 #if MYNEWT_VAL(BLE_DEVICE)
464         /*
465          * If we receive an unknown HCI packet type this is considered a loss
466          * of sync.
467          */
468         ble_hci_uart_sync_lost();
469 #else
470         /*
471          * XXX: not sure what to do about host in this case. Just go back to
472          * none for now.
473          */
474         ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
475 #endif
476         break;
477     }
478 
479     return 0;
480 }
481 
482 #if MYNEWT_VAL(BLE_DEVICE)
483 /**
484  * HCI uart sync loss.
485  *
486  * Find a LL reset command in the byte stream. The LL reset command is a
487  * sequence of 4 bytes:
488  *  0x01    HCI Packet Type = HCI CMD
489  *  0x03    OCF for reset command
490  *  0x0C    OGF for reset command (0x03 shifted left by two bits as the OGF
491  *          occupies the uopper 6 bits of this byte.
492  *  0x00    Parameter length of reset command (no parameters).
493  *
494  * @param data Byte received over serial port
495  */
496 void
ble_hci_uart_rx_sync_loss(uint8_t data)497 ble_hci_uart_rx_sync_loss(uint8_t data)
498 {
499     int rc;
500     int index;
501 
502     /*
503      * If we couldnt allocate a command buffer (should not occur but
504      * possible) try to allocate one on each received character. If we get
505      * a reset and buffer is not available we have to ignore reset.
506      */
507     if (ble_hci_uart_state.rx_cmd.data == NULL) {
508         ble_hci_uart_state.rx_cmd.data =
509             ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
510     }
511 
512     index = ble_hci_uart_state.rx_cmd.cur;
513     if (data == ble_hci_uart_reset_cmd[index]) {
514         if (index == 3) {
515             if (ble_hci_uart_state.rx_cmd.data == NULL) {
516                 index = 0;
517             } else {
518                 assert(ble_hci_uart_rx_cmd_cb != NULL);
519                 ble_hci_uart_state.rx_cmd.data[0] = 0x03;
520                 ble_hci_uart_state.rx_cmd.data[1] = 0x0C;
521                 ble_hci_uart_state.rx_cmd.data[2] = 0x00;
522                 rc = ble_hci_uart_rx_cmd_cb(ble_hci_uart_state.rx_cmd.data,
523                                             ble_hci_uart_rx_cmd_arg);
524                 if (rc != 0) {
525                     ble_hci_trans_buf_free(ble_hci_uart_state.rx_cmd.data);
526                 }
527                 ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
528             }
529         } else {
530             ++index;
531         }
532     } else {
533         index = 0;
534     }
535 
536     ble_hci_uart_state.rx_cmd.cur = index;
537 }
538 
539 static void
ble_hci_uart_rx_cmd(uint8_t data)540 ble_hci_uart_rx_cmd(uint8_t data)
541 {
542     int rc;
543 
544     ble_hci_uart_state.rx_cmd.data[ble_hci_uart_state.rx_cmd.cur++] = data;
545 
546     if (ble_hci_uart_state.rx_cmd.cur < BLE_HCI_CMD_HDR_LEN) {
547         return;
548     }
549 
550     if (ble_hci_uart_state.rx_cmd.cur == BLE_HCI_CMD_HDR_LEN) {
551         ble_hci_uart_state.rx_cmd.len = ble_hci_uart_state.rx_cmd.data[2] +
552                                          BLE_HCI_CMD_HDR_LEN;
553     }
554 
555     if (ble_hci_uart_state.rx_cmd.cur == ble_hci_uart_state.rx_cmd.len) {
556         assert(ble_hci_uart_rx_cmd_cb != NULL);
557         rc = ble_hci_uart_rx_cmd_cb(ble_hci_uart_state.rx_cmd.data,
558                                     ble_hci_uart_rx_cmd_arg);
559         if (rc != 0) {
560             ble_hci_trans_buf_free(ble_hci_uart_state.rx_cmd.data);
561         }
562         ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
563     }
564 }
565 
566 static void
ble_hci_uart_rx_skip_cmd(uint8_t data)567 ble_hci_uart_rx_skip_cmd(uint8_t data)
568 {
569     ble_hci_uart_state.rx_cmd.cur++;
570 
571     if (ble_hci_uart_state.rx_cmd.cur < BLE_HCI_CMD_HDR_LEN) {
572         return;
573     }
574 
575     if (ble_hci_uart_state.rx_cmd.cur == BLE_HCI_CMD_HDR_LEN) {
576         ble_hci_uart_state.rx_cmd.len = data + BLE_HCI_CMD_HDR_LEN;
577     }
578 
579     if (ble_hci_uart_state.rx_cmd.cur == ble_hci_uart_state.rx_cmd.len) {
580         /*
581          * XXX: for now we simply skip the command and do nothing. This
582          * should not happen but at least we retain HCI synch. The host
583          * can decide what to do in this case. It may be appropriate for
584          * the controller to attempt to send back a command complete or
585          * command status in this case.
586          */
587         ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
588     }
589 }
590 #endif
591 
592 #if MYNEWT_VAL(BLE_HOST)
593 static inline void
ble_hci_uart_rx_evt_cb()594 ble_hci_uart_rx_evt_cb()
595 {
596     int rc;
597 
598     if (ble_hci_uart_state.rx_cmd.cur == ble_hci_uart_state.rx_cmd.len) {
599         assert(ble_hci_uart_rx_cmd_cb != NULL);
600         rc = ble_hci_uart_rx_cmd_cb(ble_hci_uart_state.rx_cmd.data,
601                                     ble_hci_uart_rx_cmd_arg);
602         if (rc != 0) {
603             ble_hci_trans_buf_free(ble_hci_uart_state.rx_cmd.data);
604         }
605         ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
606     }
607 }
608 
609 static void
ble_hci_uart_rx_evt(uint8_t data)610 ble_hci_uart_rx_evt(uint8_t data)
611 {
612     /* Determine event priority to allocate buffer */
613     if (!ble_hci_uart_state.rx_cmd.data) {
614         /* In case of LE Meta Event priority might be still unknown */
615         if (data == BLE_HCI_EVCODE_LE_META) {
616             ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_LE_EVT;
617             ble_hci_uart_state.rx_cmd.cur++;
618             return;
619         }
620 
621         ble_hci_uart_state.rx_cmd.data =
622             ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
623         assert(ble_hci_uart_state.rx_cmd.data != NULL);
624     }
625 
626     ble_hci_uart_state.rx_cmd.data[ble_hci_uart_state.rx_cmd.cur++] = data;
627 
628     if (ble_hci_uart_state.rx_cmd.cur < BLE_HCI_EVENT_HDR_LEN) {
629         return;
630     }
631 
632     if (ble_hci_uart_state.rx_cmd.cur == BLE_HCI_EVENT_HDR_LEN) {
633         ble_hci_uart_state.rx_cmd.len = ble_hci_uart_state.rx_cmd.data[1] +
634                                         BLE_HCI_EVENT_HDR_LEN;
635     }
636 
637     ble_hci_uart_rx_evt_cb();
638 }
639 
640 static void
ble_hci_uart_rx_le_evt(uint8_t data)641 ble_hci_uart_rx_le_evt(uint8_t data)
642 {
643     ble_hci_uart_state.rx_cmd.cur++;
644 
645     if (ble_hci_uart_state.rx_cmd.cur == BLE_HCI_EVENT_HDR_LEN) {
646         /* LE Meta Event parameter length is never 0 */
647         assert(data != 0);
648         ble_hci_uart_state.rx_cmd.len = data + BLE_HCI_EVENT_HDR_LEN;
649         return;
650     }
651 
652     /* Determine event priority to allocate buffer */
653     if (!ble_hci_uart_state.rx_cmd.data) {
654         /* Determine event priority to allocate buffer */
655         if (data == BLE_HCI_LE_SUBEV_ADV_RPT ||
656                 data == BLE_HCI_LE_SUBEV_EXT_ADV_RPT) {
657             ble_hci_uart_state.rx_cmd.data =
658                 ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
659             if (ble_hci_uart_state.rx_cmd.data == NULL) {
660                 ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_SKIP_EVT;
661                 return;
662             }
663         } else {
664             ble_hci_uart_state.rx_cmd.data =
665                 ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
666             assert(ble_hci_uart_state.rx_cmd.data != NULL);
667         }
668 
669         ble_hci_uart_state.rx_cmd.data[0] = BLE_HCI_EVCODE_LE_META;
670         ble_hci_uart_state.rx_cmd.data[1] =
671                 ble_hci_uart_state.rx_cmd.len - BLE_HCI_EVENT_HDR_LEN;
672     }
673 
674     ble_hci_uart_state.rx_cmd.data[ble_hci_uart_state.rx_cmd.cur - 1] = data;
675     ble_hci_uart_rx_evt_cb();
676 }
677 
678 static void
ble_hci_uart_rx_skip_evt(uint8_t data)679 ble_hci_uart_rx_skip_evt(uint8_t data)
680 {
681     if (++ble_hci_uart_state.rx_cmd.cur == ble_hci_uart_state.rx_cmd.len) {
682         ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
683     }
684 }
685 #endif
686 
687 static void
ble_hci_uart_rx_acl(uint8_t data)688 ble_hci_uart_rx_acl(uint8_t data)
689 {
690     uint16_t rxd_bytes;
691     uint16_t pktlen;
692 
693     rxd_bytes = ble_hci_uart_state.rx_acl.rxd_bytes;
694     ble_hci_uart_state.rx_acl.dptr[rxd_bytes] = data;
695     ++rxd_bytes;
696     ble_hci_uart_state.rx_acl.rxd_bytes = rxd_bytes;
697 
698     if (rxd_bytes < BLE_HCI_DATA_HDR_SZ) {
699         return;
700     }
701 
702     if (rxd_bytes == BLE_HCI_DATA_HDR_SZ) {
703         pktlen = ble_hci_uart_state.rx_acl.dptr[3];
704         pktlen = (pktlen << 8) + ble_hci_uart_state.rx_acl.dptr[2];
705         ble_hci_uart_state.rx_acl.len = pktlen + BLE_HCI_DATA_HDR_SZ;
706 
707         /*
708          * Data portion cannot exceed data length of acl buffer. If it does
709          * this is considered to be a loss of sync.
710          */
711         if (pktlen > MYNEWT_VAL(BLE_ACL_BUF_SIZE)) {
712             os_mbuf_free_chain(ble_hci_uart_state.rx_acl.buf);
713 #if MYNEWT_VAL(BLE_DEVICE)
714             ble_hci_uart_sync_lost();
715 #else
716         /*
717          * XXX: not sure what to do about host in this case. Just go back to
718          * none for now.
719          */
720         ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
721 #endif
722         }
723     }
724 
725     if (rxd_bytes == ble_hci_uart_state.rx_acl.len) {
726         assert(ble_hci_uart_rx_acl_cb != NULL);
727         /* XXX: can this callback fail? What if it does? */
728         OS_MBUF_PKTLEN(ble_hci_uart_state.rx_acl.buf) = rxd_bytes;
729         ble_hci_uart_state.rx_acl.buf->om_len = rxd_bytes;
730         ble_hci_uart_rx_acl_cb(ble_hci_uart_state.rx_acl.buf,
731                                ble_hci_uart_rx_acl_arg);
732         ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
733     }
734 }
735 
736 static void
ble_hci_uart_rx_skip_acl(uint8_t data)737 ble_hci_uart_rx_skip_acl(uint8_t data)
738 {
739     uint16_t rxd_bytes;
740     uint16_t pktlen;
741 
742     rxd_bytes = ble_hci_uart_state.rx_acl.rxd_bytes;
743     ++rxd_bytes;
744     ble_hci_uart_state.rx_acl.rxd_bytes = rxd_bytes;
745 
746     if (rxd_bytes == (BLE_HCI_DATA_HDR_SZ - 1)) {
747         ble_hci_uart_state.rx_acl.len = data;
748         return;
749     }
750 
751     if (rxd_bytes == BLE_HCI_DATA_HDR_SZ) {
752         pktlen = data;
753         pktlen = (pktlen << 8) + ble_hci_uart_state.rx_acl.len;
754         ble_hci_uart_state.rx_acl.len = pktlen + BLE_HCI_DATA_HDR_SZ;
755     }
756 
757     if (rxd_bytes == ble_hci_uart_state.rx_acl.len) {
758 /* XXX: I dont like this but for now this denotes controller only */
759 #if MYNEWT_VAL(BLE_DEVICE)
760         ble_ll_data_buffer_overflow();
761 #endif
762         ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
763     }
764 }
765 
766 static int
ble_hci_uart_rx_char(void * arg,uint8_t data)767 ble_hci_uart_rx_char(void *arg, uint8_t data)
768 {
769     switch (ble_hci_uart_state.rx_type) {
770     case BLE_HCI_UART_H4_NONE:
771         return ble_hci_uart_rx_pkt_type(data);
772 #if MYNEWT_VAL(BLE_DEVICE)
773     case BLE_HCI_UART_H4_CMD:
774         ble_hci_uart_rx_cmd(data);
775         return 0;
776     case BLE_HCI_UART_H4_SKIP_CMD:
777         ble_hci_uart_rx_skip_cmd(data);
778         return 0;
779     case BLE_HCI_UART_H4_SYNC_LOSS:
780         ble_hci_uart_rx_sync_loss(data);
781         return 0;
782 #endif
783 #if MYNEWT_VAL(BLE_HOST)
784     case BLE_HCI_UART_H4_EVT:
785         ble_hci_uart_rx_evt(data);
786         return 0;
787     case BLE_HCI_UART_H4_LE_EVT:
788         ble_hci_uart_rx_le_evt(data);
789         return 0;
790     case BLE_HCI_UART_H4_SKIP_EVT:
791         ble_hci_uart_rx_skip_evt(data);
792         return 0;
793 #endif
794     case BLE_HCI_UART_H4_ACL:
795         ble_hci_uart_rx_acl(data);
796         return 0;
797     case BLE_HCI_UART_H4_SKIP_ACL:
798         ble_hci_uart_rx_skip_acl(data);
799         return 0;
800     default:
801         /* This should never happen! */
802         assert(0);
803         return 0;
804     }
805 }
806 
807 static void
ble_hci_uart_set_rx_cbs(ble_hci_trans_rx_cmd_fn * cmd_cb,void * cmd_arg,ble_hci_trans_rx_acl_fn * acl_cb,void * acl_arg)808 ble_hci_uart_set_rx_cbs(ble_hci_trans_rx_cmd_fn *cmd_cb,
809                         void *cmd_arg,
810                         ble_hci_trans_rx_acl_fn *acl_cb,
811                         void *acl_arg)
812 {
813     ble_hci_uart_rx_cmd_cb = cmd_cb;
814     ble_hci_uart_rx_cmd_arg = cmd_arg;
815     ble_hci_uart_rx_acl_cb = acl_cb;
816     ble_hci_uart_rx_acl_arg = acl_arg;
817 }
818 
819 static void
ble_hci_uart_free_pkt(uint8_t type,uint8_t * cmdevt,struct os_mbuf * acl)820 ble_hci_uart_free_pkt(uint8_t type, uint8_t *cmdevt, struct os_mbuf *acl)
821 {
822     switch (type) {
823     case BLE_HCI_UART_H4_NONE:
824         break;
825 
826     case BLE_HCI_UART_H4_CMD:
827     case BLE_HCI_UART_H4_EVT:
828         ble_hci_trans_buf_free(cmdevt);
829         break;
830 
831     case BLE_HCI_UART_H4_ACL:
832         os_mbuf_free_chain(acl);
833         break;
834 
835     default:
836         assert(0);
837         break;
838     }
839 }
840 
841 static int
ble_hci_uart_config(void)842 ble_hci_uart_config(void)
843 {
844     int rc;
845 
846     rc = hal_uart_init_cbs(MYNEWT_VAL(BLE_HCI_UART_PORT),
847                            ble_hci_uart_tx_char, NULL,
848                            ble_hci_uart_rx_char, NULL);
849     if (rc != 0) {
850         return BLE_ERR_UNSPECIFIED;
851     }
852 
853     rc = hal_uart_config(MYNEWT_VAL(BLE_HCI_UART_PORT),
854                          MYNEWT_VAL(BLE_HCI_UART_BAUD),
855                          MYNEWT_VAL(BLE_HCI_UART_DATA_BITS),
856                          MYNEWT_VAL(BLE_HCI_UART_STOP_BITS),
857                          MYNEWT_VAL(BLE_HCI_UART_PARITY),
858                          MYNEWT_VAL(BLE_HCI_UART_FLOW_CTRL));
859     if (rc != 0) {
860         return BLE_ERR_HW_FAIL;
861     }
862 
863     return 0;
864 }
865 
866 /**
867  * Sends an HCI event from the controller to the host.
868  *
869  * @param cmd                   The HCI event to send.  This buffer must be
870  *                                  allocated via ble_hci_trans_buf_alloc().
871  *
872  * @return                      0 on success;
873  *                              A BLE_ERR_[...] error code on failure.
874  */
875 int
ble_hci_trans_ll_evt_tx(uint8_t * cmd)876 ble_hci_trans_ll_evt_tx(uint8_t *cmd)
877 {
878     int rc;
879 
880     rc = ble_hci_uart_cmdevt_tx(cmd, BLE_HCI_UART_H4_EVT);
881     return rc;
882 }
883 
884 /**
885  * Sends ACL data from controller to host.
886  *
887  * @param om                    The ACL data packet to send.
888  *
889  * @return                      0 on success;
890  *                              A BLE_ERR_[...] error code on failure.
891  */
892 int
ble_hci_trans_ll_acl_tx(struct os_mbuf * om)893 ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
894 {
895     int rc;
896 
897     rc = ble_hci_uart_acl_tx(om);
898     return rc;
899 }
900 
901 /**
902  * Sends an HCI command from the host to the controller.
903  *
904  * @param cmd                   The HCI command to send.  This buffer must be
905  *                                  allocated via ble_hci_trans_buf_alloc().
906  *
907  * @return                      0 on success;
908  *                              A BLE_ERR_[...] error code on failure.
909  */
910 int
ble_hci_trans_hs_cmd_tx(uint8_t * cmd)911 ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
912 {
913     int rc;
914 
915     rc = ble_hci_uart_cmdevt_tx(cmd, BLE_HCI_UART_H4_CMD);
916     return rc;
917 }
918 
919 /**
920  * Sends ACL data from host to controller.
921  *
922  * @param om                    The ACL data packet to send.
923  *
924  * @return                      0 on success;
925  *                              A BLE_ERR_[...] error code on failure.
926  */
927 int
ble_hci_trans_hs_acl_tx(struct os_mbuf * om)928 ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
929 {
930     int rc;
931 
932     rc = ble_hci_uart_acl_tx(om);
933     return rc;
934 }
935 
936 /**
937  * Configures the HCI transport to call the specified callback upon receiving
938  * HCI packets from the controller.  This function should only be called by by
939  * host.
940  *
941  * @param cmd_cb                The callback to execute upon receiving an HCI
942  *                                  event.
943  * @param cmd_arg               Optional argument to pass to the command
944  *                                  callback.
945  * @param acl_cb                The callback to execute upon receiving ACL
946  *                                  data.
947  * @param acl_arg               Optional argument to pass to the ACL
948  *                                  callback.
949  */
950 void
ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn * cmd_cb,void * cmd_arg,ble_hci_trans_rx_acl_fn * acl_cb,void * acl_arg)951 ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb,
952                      void *cmd_arg,
953                      ble_hci_trans_rx_acl_fn *acl_cb,
954                      void *acl_arg)
955 {
956     ble_hci_uart_set_rx_cbs(cmd_cb, cmd_arg, acl_cb, acl_arg);
957 }
958 
959 /**
960  * Configures the HCI transport to operate with a host.  The transport will
961  * execute specified callbacks upon receiving HCI packets from the controller.
962  *
963  * @param cmd_cb                The callback to execute upon receiving an HCI
964  *                                  event.
965  * @param cmd_arg               Optional argument to pass to the command
966  *                                  callback.
967  * @param acl_cb                The callback to execute upon receiving ACL
968  *                                  data.
969  * @param acl_arg               Optional argument to pass to the ACL
970  *                                  callback.
971  */
972 void
ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn * cmd_cb,void * cmd_arg,ble_hci_trans_rx_acl_fn * acl_cb,void * acl_arg)973 ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb,
974                      void *cmd_arg,
975                      ble_hci_trans_rx_acl_fn *acl_cb,
976                      void *acl_arg)
977 {
978     ble_hci_uart_set_rx_cbs(cmd_cb, cmd_arg, acl_cb, acl_arg);
979 }
980 
981 /**
982  * Allocates a flat buffer of the specified type.
983  *
984  * @param type                  The type of buffer to allocate; one of the
985  *                                  BLE_HCI_TRANS_BUF_[...] constants.
986  *
987  * @return                      The allocated buffer on success;
988  *                              NULL on buffer exhaustion.
989  */
990 uint8_t *
ble_hci_trans_buf_alloc(int type)991 ble_hci_trans_buf_alloc(int type)
992 {
993     uint8_t *buf;
994 
995     switch (type) {
996     case BLE_HCI_TRANS_BUF_CMD:
997         buf = os_memblock_get(&ble_hci_uart_cmd_pool);
998         break;
999     case BLE_HCI_TRANS_BUF_EVT_HI:
1000         buf = os_memblock_get(&ble_hci_uart_evt_hi_pool);
1001         if (buf == NULL) {
1002             /* If no high-priority event buffers remain, try to grab a
1003              * low-priority one.
1004              */
1005             buf = os_memblock_get(&ble_hci_uart_evt_lo_pool);
1006         }
1007         break;
1008 
1009     case BLE_HCI_TRANS_BUF_EVT_LO:
1010         buf = os_memblock_get(&ble_hci_uart_evt_lo_pool);
1011         break;
1012 
1013     default:
1014         assert(0);
1015         buf = NULL;
1016     }
1017 
1018     return buf;
1019 }
1020 
1021 /**
1022  * Frees the specified flat buffer.  The buffer must have been allocated via
1023  * ble_hci_trans_buf_alloc().
1024  *
1025  * @param buf                   The buffer to free.
1026  */
1027 void
ble_hci_trans_buf_free(uint8_t * buf)1028 ble_hci_trans_buf_free(uint8_t *buf)
1029 {
1030     int rc;
1031 
1032     /*
1033      * XXX: this may look a bit odd, but the controller uses the command
1034      * buffer to send back the command complete/status as an immediate
1035      * response to the command. This was done to insure that the controller
1036      * could always send back one of these events when a command was received.
1037      * Thus, we check to see which pool the buffer came from so we can free
1038      * it to the appropriate pool
1039      */
1040     if (os_memblock_from(&ble_hci_uart_evt_hi_pool, buf)) {
1041         rc = os_memblock_put(&ble_hci_uart_evt_hi_pool, buf);
1042         assert(rc == 0);
1043     } else if (os_memblock_from(&ble_hci_uart_evt_lo_pool, buf)) {
1044         rc = os_memblock_put(&ble_hci_uart_evt_lo_pool, buf);
1045         assert(rc == 0);
1046     } else {
1047         assert(os_memblock_from(&ble_hci_uart_cmd_pool, buf));
1048         rc = os_memblock_put(&ble_hci_uart_cmd_pool, buf);
1049         assert(rc == 0);
1050     }
1051 }
1052 
1053 /**
1054  * Configures a callback to get executed whenever an ACL data packet is freed.
1055  * The function is called in lieu of actually freeing the packet.
1056  *
1057  * @param cb                    The callback to configure.
1058  *
1059  * @return                      0 on success.
1060  */
1061 int
ble_hci_trans_set_acl_free_cb(os_mempool_put_fn * cb,void * arg)1062 ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg)
1063 {
1064     ble_hci_uart_acl_pool.mpe_put_cb = cb;
1065     ble_hci_uart_acl_pool.mpe_put_arg = arg;
1066     return 0;
1067 }
1068 
1069 /**
1070  * Resets the HCI UART transport to a clean state.  Frees all buffers and
1071  * reconfigures the UART.
1072  *
1073  * @return                      0 on success;
1074  *                              A BLE_ERR_[...] error code on failure.
1075  */
1076 int
ble_hci_trans_reset(void)1077 ble_hci_trans_reset(void)
1078 {
1079     struct ble_hci_uart_pkt *pkt;
1080     int rc;
1081 
1082     /* Close the UART to prevent race conditions as the buffers are freed. */
1083     rc = hal_uart_close(MYNEWT_VAL(BLE_HCI_UART_PORT));
1084     if (rc != 0) {
1085         return BLE_ERR_HW_FAIL;
1086     }
1087 
1088     ble_hci_uart_free_pkt(ble_hci_uart_state.rx_type,
1089                           ble_hci_uart_state.rx_cmd.data,
1090                           ble_hci_uart_state.rx_acl.buf);
1091     ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
1092 
1093     ble_hci_uart_free_pkt(ble_hci_uart_state.tx_type,
1094                           ble_hci_uart_state.tx_cmd.data,
1095                           ble_hci_uart_state.tx_pkt.tx_acl);
1096     ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_NONE;
1097 
1098     while ((pkt = STAILQ_FIRST(&ble_hci_uart_state.tx_pkts)) != NULL) {
1099         STAILQ_REMOVE(&ble_hci_uart_state.tx_pkts, pkt, ble_hci_uart_pkt,
1100                       next);
1101         ble_hci_uart_free_pkt(pkt->type, pkt->data, pkt->data);
1102         os_memblock_put(&ble_hci_uart_pkt_pool, pkt);
1103     }
1104 
1105     /* Reopen the UART. */
1106     rc = ble_hci_uart_config();
1107     if (rc != 0) {
1108         return rc;
1109     }
1110 
1111     return 0;
1112 }
1113 
1114 /**
1115  * Initializes the UART HCI transport module.
1116  *
1117  * @return                      0 on success;
1118  *                              A BLE_ERR_[...] error code on failure.
1119  */
1120 void
ble_hci_uart_init(void)1121 ble_hci_uart_init(void)
1122 {
1123     int rc;
1124 
1125     /* Ensure this function only gets called by sysinit. */
1126     SYSINIT_ASSERT_ACTIVE();
1127 
1128     rc = os_mempool_ext_init(&ble_hci_uart_acl_pool,
1129                              MYNEWT_VAL(BLE_ACL_BUF_COUNT),
1130                              ACL_BLOCK_SIZE,
1131                              ble_hci_uart_acl_buf,
1132                              "ble_hci_uart_acl_pool");
1133     SYSINIT_PANIC_ASSERT(rc == 0);
1134 
1135     rc = os_mbuf_pool_init(&ble_hci_uart_acl_mbuf_pool,
1136                            &ble_hci_uart_acl_pool.mpe_mp,
1137                            ACL_BLOCK_SIZE,
1138                            MYNEWT_VAL(BLE_ACL_BUF_COUNT));
1139     SYSINIT_PANIC_ASSERT(rc == 0);
1140 
1141     /*
1142      * Create memory pool of HCI command buffers. NOTE: we currently dont
1143      * allow this to be configured. The controller will only allow one
1144      * outstanding command. We decided to keep this a pool in case we allow
1145      * allow the controller to handle more than one outstanding command.
1146      */
1147     rc = os_mempool_init(&ble_hci_uart_cmd_pool,
1148                          1,
1149                          BLE_HCI_TRANS_CMD_SZ,
1150                          ble_hci_uart_cmd_buf,
1151                          "ble_hci_uart_cmd_pool");
1152     SYSINIT_PANIC_ASSERT(rc == 0);
1153 
1154     rc = os_mempool_init(&ble_hci_uart_evt_hi_pool,
1155                          MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
1156                          MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
1157                          ble_hci_uart_evt_hi_buf,
1158                          "ble_hci_uart_evt_hi_pool");
1159     SYSINIT_PANIC_ASSERT(rc == 0);
1160 
1161     rc = os_mempool_init(&ble_hci_uart_evt_lo_pool,
1162                          MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
1163                          MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
1164                          ble_hci_uart_evt_lo_buf,
1165                          "ble_hci_uart_evt_lo_pool");
1166     SYSINIT_PANIC_ASSERT(rc == 0);
1167 
1168     /*
1169      * Create memory pool of packet list nodes. NOTE: the number of these
1170      * buffers should be, at least, the total number of event buffers (hi
1171      * and lo), the number of command buffers (currently 1) and the total
1172      * number of buffers that the controller could possibly hand to the host.
1173      */
1174     rc = os_mempool_init(&ble_hci_uart_pkt_pool,
1175                          BLE_HCI_UART_EVT_COUNT + 1 +
1176                          MYNEWT_VAL(BLE_HCI_ACL_OUT_COUNT),
1177                          sizeof (struct ble_hci_uart_pkt),
1178                          ble_hci_uart_pkt_buf,
1179                          "ble_hci_uart_pkt_pool");
1180     SYSINIT_PANIC_ASSERT(rc == 0);
1181 
1182     rc = ble_hci_uart_config();
1183     SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failure configuring UART HCI");
1184 
1185     memset(&ble_hci_uart_state, 0, sizeof ble_hci_uart_state);
1186     STAILQ_INIT(&ble_hci_uart_state.tx_pkts);
1187 }
1188