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