• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "securec.h"
22 #include "sysinit/sysinit.h"
23 #include "nimble/hci_common.h"
24 #include "host/ble_hs.h"
25 #include "nimble/nimble_port.h"
26 #include "nimble/ble_hci_trans.h"
27 #include "wm_bt.h"
28 #include "wm_mem.h"
29 
30 #define BLE_HCI_UART_H4_NONE        0x00
31 #define BLE_HCI_UART_H4_CMD         0x01
32 #define BLE_HCI_UART_H4_ACL         0x02
33 #define BLE_HCI_UART_H4_SCO         0x03
34 #define BLE_HCI_UART_H4_EVT         0x04
35 #define BLE_HCI_UART_H4_SYNC_LOSS   0x80
36 #define BLE_HCI_UART_H4_SKIP_CMD    0x81
37 #define BLE_HCI_UART_H4_SKIP_ACL    0x82
38 #define BLE_HCI_UART_H4_LE_EVT      0x83
39 #define BLE_HCI_UART_H4_SKIP_EVT    0x84
40 
41 #define BLE_HCI_EVENT_HDR_LEN               (2)
42 #define BLE_HCI_CMD_HDR_LEN                 (3)
43 
44 static volatile int ble_hci_cmd_pkts = 0;
45 static ble_hci_trans_rx_cmd_fn *ble_hci_rx_cmd_hs_cb;
46 static void *ble_hci_rx_cmd_hs_arg;
47 static ble_hci_trans_rx_acl_fn *ble_hci_rx_acl_hs_cb;
48 static void *ble_hci_rx_acl_hs_arg;
49 static struct os_mempool ble_hci_vuart_evt_hi_pool;
50 
51 #if MYNEWT_VAL(SYS_MEM_DYNAMIC)
52 static os_membuf_t *ble_hci_vuart_evt_hi_buf = NULL;
53 
54 #else
55 static os_membuf_t ble_hci_vuart_evt_hi_buf[
56     OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT), MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
57 ];
58 #endif
59 
60 static struct os_mempool ble_hci_vuart_evt_lo_pool;
61 
62 #if MYNEWT_VAL(SYS_MEM_DYNAMIC)
63 static os_membuf_t *ble_hci_vuart_evt_lo_buf = NULL;
64 #else
65 static os_membuf_t ble_hci_vuart_evt_lo_buf[
66     OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT), MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
67 ];
68 #endif
69 
70 static struct os_mempool ble_hci_vuart_cmd_pool;
71 
72 #if MYNEWT_VAL(SYS_MEM_DYNAMIC)
73 static os_membuf_t *ble_hci_vuart_cmd_buf = NULL;
74 #else
75 static os_membuf_t ble_hci_vuart_cmd_buf[OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ)];
76 #endif
77 
78 static struct os_mbuf_pool ble_hci_vuart_acl_mbuf_pool;
79 static struct os_mempool_ext ble_hci_vuart_acl_pool;
80 
81 /*
82  * The MBUF payload size must accommodate the HCI data header size plus the
83  * maximum ACL data packet length. The ACL block size is the size of the
84  * mbufs we will allocate.
85  */
86 #define ACL_BLOCK_SIZE  OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) \
87                                  + BLE_MBUF_MEMBLOCK_OVERHEAD \
88                                  + BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
89 
90 #if MYNEWT_VAL(SYS_MEM_DYNAMIC)
91 static os_membuf_t *ble_hci_vuart_acl_buf = NULL;
92 #else
93 static os_membuf_t ble_hci_vuart_acl_buf[OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_ACL_BUF_COUNT), ACL_BLOCK_SIZE)
94 ];
95 #endif
96 
97 #define HCI_VUART_RX_QUEUE 0
98 
99 #if HCI_VUART_RX_QUEUE
100 
101 #define HCI_RESP_QUEUE_FULL      (20)
102 #define HCI_RESP_QUEUE_HALF_FULL (10)
103 
104 struct QUEUE_ITEM {
105     int size;
106     uint8_t *payload;
107     TAILQ_ENTRY(QUEUE_ITEM) entries;
108 };
109 
110 static TAILQ_HEAD(, QUEUE_ITEM) hci_resp_queue;
111 static volatile uint8_t hci_resp_queue_counter = 0;
112 
113 static struct ble_npl_mutex hci_resp_queue_mutex;
114 static struct ble_npl_event ble_hs_ev_hci_rx;
115 static struct ble_npl_eventq hci_evt_rx_tx_queue;
116 
117 #endif
118 
119 #define HCI_DBG FALSE
120 
121 #ifndef HCI_DBG
122 #define HCI_DBG TRUE
123 #endif
124 
125 #if (HCI_DBG == TRUE)
126 #define HCIDBG(fmt, ...)  \
127     do { \
128         if (1) \
129             printf("%s(L%d): " fmt, __FUNCTION__, __LINE__,  ## __VA_ARGS__); \
130     } while (0)
131 #else
132 #define HCIDBG(param, ...)
133 #endif
134 
135 #if (HCI_DBG == TRUE)
hci_dbg_hexstring(const char * msg,const uint8_t * ptr,int a_length)136 static void  hci_dbg_hexstring(const char *msg, const uint8_t *ptr, int a_length)
137 {
138 #define DBG_TRACE_WARNING_MAX_SIZE_W  252
139     // 123
140 #define DBG_TRACE_WARNING_MAX_SIZE    256
141     // 128
142     char sbuffer[DBG_TRACE_WARNING_MAX_SIZE];
143     uint8_t offset = 0;
144     int i = 0;
145     int length = 0;
146 
147     if (msg) {
148         printf("[%d]%s", tls_os_get_time(), msg);
149     }
150 
151     if (a_length <= 0 || ptr == NULL) {
152         return;
153     }
154     length = a_length;
155 
156     do {
157         for (; i < length; i++) {
158             offset += sprintf_s(sbuffer + offset, sizeof(sbuffer + offset), "%02X ", (uint8_t)ptr[i]);
159             if (offset > DBG_TRACE_WARNING_MAX_SIZE_W) {
160                 break;
161             }
162         }
163 
164         sbuffer[offset - 1] = '\r';
165         sbuffer[offset] = '\n';
166         sbuffer[offset + 1] = 0;
167 
168         if (offset > DBG_TRACE_WARNING_MAX_SIZE_W) {
169             sbuffer[offset - 2] = '.'; // 2:byte alignment
170             sbuffer[offset - 3] = '.'; // 3:byte alignment
171         }
172 
173         printf("%s", sbuffer);
174         offset = 0;
175     } while (i < length);
176 }
177 #endif
178 
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)179 void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb,
180                           void *cmd_arg,
181                           ble_hci_trans_rx_acl_fn *acl_cb,
182                           void *acl_arg)
183 {
184     ble_hci_rx_cmd_hs_cb = cmd_cb;
185     ble_hci_rx_cmd_hs_arg = cmd_arg;
186     ble_hci_rx_acl_hs_cb = acl_cb;
187     ble_hci_rx_acl_hs_arg = acl_arg;
188 }
ble_hci_trans_hs_cmd_tx(uint8_t * cmd)189 int ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
190 {
191     uint16_t len;
192     assert(cmd != NULL);
193     *cmd = BLE_HCI_UART_H4_CMD;
194     len = BLE_HCI_CMD_HDR_LEN + cmd[3] + 1; // 3:array element
195 
196     while (ble_hci_cmd_pkts <= 0) {
197         tls_os_time_delay(1000 / HZ); // 1000:byte alignment
198     }
199     tls_bt_vuart_host_send_packet(cmd, len);
200     ble_hci_trans_buf_free(cmd);
201     return 0;
202 }
203 
ble_hci_trans_ll_evt_tx(uint8_t * hci_ev)204 int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev)
205 {
206     int rc = -1;
207 
208     if (ble_hci_rx_cmd_hs_cb) {
209         rc = ble_hci_rx_cmd_hs_cb(hci_ev, ble_hci_rx_cmd_hs_arg);
210     }
211 
212     return rc;
213 }
214 
ble_hci_trans_hs_acl_tx(struct os_mbuf * om)215 int ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
216 {
217     uint16_t len = 0;
218     uint8_t data[MYNEWT_VAL(BLE_ACL_BUF_SIZE) + 1];
219 
220     /* If this packet is zero length, just free it */
221     if (OS_MBUF_PKTLEN(om) == 0) {
222         os_mbuf_free_chain(om);
223         return 0;
224     }
225 
226     data[0] = BLE_HCI_UART_H4_ACL;
227     len++;
228 
229     while (ble_hci_cmd_pkts <= 0) {
230         tls_os_time_delay(1000 / HZ); // 1000:byte alignment
231     }
232 
233     os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), &data[1]);
234     len += OS_MBUF_PKTLEN(om);
235     tls_bt_vuart_host_send_packet(data, len);
236     os_mbuf_free_chain(om);
237     return 0;
238 }
239 
ble_hci_trans_buf_alloc(int type)240 uint8_t *ble_hci_trans_buf_alloc(int type)
241 {
242     uint8_t *buf;
243 
244     switch (type) {
245         case BLE_HCI_TRANS_BUF_CMD:
246             buf = os_memblock_get(&ble_hci_vuart_cmd_pool);
247             break;
248 
249         case BLE_HCI_TRANS_BUF_EVT_HI:
250             buf = os_memblock_get(&ble_hci_vuart_evt_hi_pool);
251             if (buf == NULL) {
252                 /* If no high-priority event buffers remain, try to grab a
253                  * low-priority one.
254                  */
255                 buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
256             }
257 
258             break;
259 
260         case BLE_HCI_TRANS_BUF_EVT_LO:
261             buf = os_memblock_get(&ble_hci_vuart_evt_lo_pool);
262             break;
263 
264         default:
265             assert(0);
266             buf = NULL;
267     }
268 
269     return buf;
270 }
271 
ble_hci_trans_buf_free(uint8_t * buf)272 void ble_hci_trans_buf_free(uint8_t *buf)
273 {
274     int rc;
275 
276     /*
277      * XXX: this may look a bit odd, but the controller uses the command
278      * buffer to send back the command complete/status as an immediate
279      * response to the command. This was done to insure that the controller
280      * could always send back one of these events when a command was received.
281      * Thus, we check to see which pool the buffer came from so we can free
282      * it to the appropriate pool
283      */
284     if (os_memblock_from(&ble_hci_vuart_evt_hi_pool, buf)) {
285         rc = os_memblock_put(&ble_hci_vuart_evt_hi_pool, buf);
286         assert(rc == 0);
287     } else if (os_memblock_from(&ble_hci_vuart_evt_lo_pool, buf)) {
288         rc = os_memblock_put(&ble_hci_vuart_evt_lo_pool, buf);
289         assert(rc == 0);
290     } else {
291         assert(os_memblock_from(&ble_hci_vuart_cmd_pool, buf));
292         rc = os_memblock_put(&ble_hci_vuart_cmd_pool, buf);
293         assert(rc == 0);
294     }
295 }
296 
297 /**
298  * Unsupported; the RAM transport does not have a dedicated ACL data packet
299  * pool.
300  */
ble_hci_trans_set_acl_free_cb(os_mempool_put_fn * cb,void * arg)301 int ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg)
302 {
303     return BLE_ERR_UNSUPPORTED;
304 }
305 
ble_hci_trans_reset(void)306 int ble_hci_trans_reset(void)
307 {
308     /* No work to do.  All allocated buffers are owned by the host or
309      * controller, and they will get freed by their owners.
310      */
311     return 0;
312 }
313 
314 /**
315  * Allocates a buffer (mbuf) for ACL operation.
316  *
317  * @return                      The allocated buffer on success;
318  *                              NULL on buffer exhaustion.
319  */
ble_hci_trans_acl_buf_alloc(void)320 static struct os_mbuf *ble_hci_trans_acl_buf_alloc(void)
321 {
322     struct os_mbuf *m;
323     uint8_t usrhdr_len;
324 #if MYNEWT_VAL(BLE_DEVICE)
325     usrhdr_len = sizeof(struct ble_mbuf_hdr);
326 #elif MYNEWT_VAL(BLE_HS_FLOW_CTRL)
327     usrhdr_len = BLE_MBUF_HS_HDR_LEN;
328 #else
329     usrhdr_len = 0;
330 #endif
331     m = os_mbuf_get_pkthdr(&ble_hci_vuart_acl_mbuf_pool, usrhdr_len);
332     return m;
333 }
334 
ble_hci_rx_acl(uint8_t * data,uint16_t len)335 static void ble_hci_rx_acl(uint8_t *data, uint16_t len)
336 {
337     struct os_mbuf *m;
338     int sr;
339 
340     if (len < BLE_HCI_DATA_HDR_SZ || len > MYNEWT_VAL(BLE_ACL_BUF_SIZE)) {
341         assert(0);
342         return;
343     }
344 
345     m = ble_hci_trans_acl_buf_alloc();
346     if (!m) {
347         assert(0);
348         return;
349     }
350 
351     if (os_mbuf_append(m, data, len)) {
352         assert(0);
353         os_mbuf_free_chain(m);
354         return;
355     }
356 
357     OS_ENTER_CRITICAL(sr);
358 
359     if (ble_hci_rx_acl_hs_cb) {
360         ble_hci_rx_acl_hs_cb(m, NULL);
361     }
362 
363     OS_EXIT_CRITICAL(sr);
364 }
365 
notify_host_send_available(int cnt)366 void notify_host_send_available(int cnt)
367 {
368     ble_hci_cmd_pkts = cnt;
369 }
370 
ble_hci_trans_hs_rx(uint8_t * data,uint16_t len)371 static int ble_hci_trans_hs_rx(uint8_t *data, uint16_t len)
372 {
373     if (data[0] == BLE_HCI_UART_H4_EVT) {
374         uint8_t *evbuf;
375         int totlen;
376         int rc;
377         totlen = BLE_HCI_EVENT_HDR_LEN + data[2]; // 2:byte alignment
378         assert(totlen <= UINT8_MAX + BLE_HCI_EVENT_HDR_LEN);
379 
380         if (data[1] == BLE_HCI_EVCODE_HW_ERROR) {
381             assert(0);
382         }
383 
384         /* Allocate LE Advertising Report Event from lo pool only */
385         if ((data[1] == BLE_HCI_EVCODE_LE_META) && (data[3] == BLE_HCI_LE_SUBEV_ADV_RPT)) { // 3:byte alignment
386             evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
387             /* Skip advertising report if we're out of memory */
388             if (!evbuf) {
389                 return 0;
390             }
391         } else {
392             evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
393             assert(evbuf != NULL);
394         }
395 
396         memcpy_s(evbuf, sizeof(*evbuf), &data[1], totlen);
397         rc = ble_hci_trans_ll_evt_tx(evbuf);
398         assert(rc == 0);
399     } else if (data[0] == BLE_HCI_UART_H4_ACL) {
400         ble_hci_rx_acl(data + 1, len - 1);
401     }
402 
403     return 0;
404 }
405 
406 #if HCI_VUART_RX_QUEUE
ble_hs_event_hci_rx_func(void * arg)407 static void ble_hs_event_hci_rx_func(void *arg)
408 {
409     uint32_t i = 0;
410     struct QUEUE_ITEM *item = NULL;
411     struct QUEUE_ITEM *item_next = NULL;
412     ble_npl_mutex_pend(&hci_resp_queue_mutex, 0);
413     item = TAILQ_FIRST(&hci_resp_queue);
414     if (item) {
415         TAILQ_REMOVE(&hci_resp_queue, item, entries);
416         item_next = TAILQ_FIRST(&hci_resp_queue);
417         hci_resp_queue_counter--;
418     }
419 
420     ble_npl_mutex_release(&hci_resp_queue_mutex);
421 
422     if (item) {
423         ble_hci_trans_hs_rx(item->payload, item->size);
424 #if (HCI_DBG == TRUE)
425         hci_dbg_hexstring("***", item->payload, item->size);
426 #endif
427         tls_mem_free(item->payload);
428         tls_mem_free(item);
429     }
430 
431     /* More hci response available, notify the host statck for reading again */
432 
433     if (item_next) {
434         ble_npl_eventq_put(&hci_evt_rx_tx_queue, &ble_hs_ev_hci_rx);
435     }
436 }
437 
438 #endif
439 
440 #define HCI_COMMAND_PKT         0x01
441 #define HCI_ACLDATA_PKT         0x02
442 #define HCI_SCODATA_PKT         0x03
443 #define HCI_EVENT_PKT           0x04
444 #define BT_HCI_EVT_LE_META_EVENT                0x3e
445 #define BT_HCI_EVT_LE_ADVERTISING_REPORT        0x02
446 
notify_host_recv(uint8_t * data,uint16_t len)447 static void notify_host_recv(uint8_t *data, uint16_t len)
448 {
449 #if HCI_VUART_RX_QUEUE
450 
451     if (data == NULL || len == 0) { return; }
452 
453 #if (HCI_DBG == TRUE)
454     hci_dbg_hexstring("<<<", data, len);
455 #endif
456 
457     if (data[0] == HCI_EVENT_PKT && data[1] == BT_HCI_EVT_LE_META_EVENT
458             && data[3] == BT_HCI_EVT_LE_ADVERTISING_REPORT) { // 3:byte alignment
459         if (hci_resp_queue_counter > HCI_RESP_QUEUE_HALF_FULL) {
460             HCIDBG("Too much hci_adv_report_evt, discard it");
461             ble_npl_eventq_put(&hci_evt_rx_tx_queue, &ble_hs_ev_hci_rx);
462             return;
463         }
464     }
465 
466     if (hci_resp_queue_counter > HCI_RESP_QUEUE_FULL) {
467         HCIDBG("Too much(%d) hci_response_evt, discard it", hci_resp_queue_counter);
468         ble_npl_eventq_put(&hci_evt_rx_tx_queue, &ble_hs_ev_hci_rx);
469         return;
470     }
471 
472     struct QUEUE_ITEM *item = tls_mem_alloc(sizeof(struct QUEUE_ITEM));
473 
474     if (item == NULL) {
475         MODLOG_DFLT(INFO, "Alloc queue item failed, no memory available");
476         return;
477     }
478 
479     item->payload = tls_mem_alloc(len);
480     if (item->payload == NULL) {
481         MODLOG_DFLT(INFO,  "Alloc queue item payload failed, no memory available");
482         tls_mem_free(item);
483         return;
484     }
485 
486     memcpy_s(item->payload, sizeof(*item->payload), data, len);
487     item->size = len;
488     ble_npl_mutex_pend(&hci_resp_queue_mutex, 0);
489     TAILQ_INSERT_TAIL(&hci_resp_queue, item, entries);
490     hci_resp_queue_counter++;
491     ble_npl_mutex_release(&hci_resp_queue_mutex);
492     ble_npl_eventq_put(&hci_evt_rx_tx_queue, &ble_hs_ev_hci_rx);
493 #else
494     ble_hci_trans_hs_rx(data, len);
495 #endif
496     return;
497 }
498 
499 static tls_bt_host_if_t vuart_hci_cb = {
500     .notify_controller_avaiable_hci_buffer = notify_host_send_available,
501     .notify_host_recv_h4 = notify_host_recv,
502 };
503 
wm_ble_controller_init(uint8_t uart_idx)504 static int wm_ble_controller_init(uint8_t uart_idx)
505 {
506     tls_bt_hci_if_t hci_if;
507     tls_bt_status_t status;
508     hci_if.uart_index = uart_idx;
509     status = tls_bt_ctrl_enable(&hci_if, 0);
510     if ((status != TLS_BT_STATUS_SUCCESS) && (status != TLS_BT_STATUS_DONE)) {
511         return TLS_BT_STATUS_CTRL_ENABLE_FAILED;
512     }
513 
514     status = tls_bt_ctrl_if_register(&vuart_hci_cb);
515     if (status != TLS_BT_STATUS_SUCCESS) {
516         return TLS_BT_STATUS_CTRL_ENABLE_FAILED;
517     }
518 
519     return 0;
520 }
wm_ble_controller_deinit(void)521 static int wm_ble_controller_deinit(void)
522 {
523     return tls_bt_ctrl_disable();
524 }
525 
526 /**
527  * Initializes the VUART HCI transport module.
528  *
529  * @return                      0 on success;
530  *                              A BLE_ERR_[...] error code on failure.
531  */
532 #if HCI_VUART_RX_QUEUE
533 
534 static void *tls_host_vuart_task_stack_ptr = NULL;
nimble_vhci_task(void)535 static void nimble_vhci_task(void)
536 {
537     struct ble_npl_event *ev;
538     int arg;
539 
540     while (1) {
541         ev = ble_npl_eventq_get(&hci_evt_rx_tx_queue, BLE_NPL_TIME_FOREVER);
542         ble_npl_event_run(ev);
543         arg = (int)ble_npl_event_get_arg(ev);
544     }
545 }
546 #endif
ble_hci_vuart_init(uint8_t uart_idx)547 int ble_hci_vuart_init(uint8_t uart_idx)
548 {
549     int rc;
550     /* Ensure this function only gets called by sysinit. */
551     SYSINIT_ASSERT_ACTIVE();
552 #if HCI_VUART_RX_QUEUE
553     /* Initialize default event queue */
554     ble_npl_eventq_init(&hci_evt_rx_tx_queue);
555     ble_npl_event_init(&ble_hs_ev_hci_rx, ble_hs_event_hci_rx_func, NULL);
556     rc = ble_npl_mutex_init(&hci_resp_queue_mutex);
557     assert(rc == BLE_NPL_OK);
558     TAILQ_INIT(&hci_resp_queue);
559     hci_resp_queue_counter = 0;
560     tls_host_vuart_task_stack_ptr = (void *)tls_mem_alloc(MYNEWT_VAL(OS_HS_VUART_STACK_SIZE) * sizeof(
561         uint32_t));
562     assert(tls_host_vuart_task_stack_ptr != NULL);
563     tls_os_task_create(NULL, "btv",
564                        nimble_vhci_task,
565                        (void *)0,
566                        (void *)tls_host_vuart_task_stack_ptr,
567                        MYNEWT_VAL(OS_HS_VUART_STACK_SIZE)*sizeof(uint32_t),
568                        MYNEWT_VAL(OS_HS_VUART_TASK_PRIO),
569                        0);
570 #endif
571     rc = wm_ble_controller_init(uart_idx);
572     assert(rc == 0);
573 #if MYNEWT_VAL(SYS_MEM_DYNAMIC)
574     ble_hci_vuart_acl_buf = (os_membuf_t *)tls_mem_alloc(
575         sizeof(os_membuf_t) *
576         OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_ACL_BUF_COUNT), ACL_BLOCK_SIZE));
577     assert(ble_hci_vuart_acl_buf != NULL);
578 #endif
579     rc = os_mempool_ext_init(&ble_hci_vuart_acl_pool,
580                              MYNEWT_VAL(BLE_ACL_BUF_COUNT),
581                              ACL_BLOCK_SIZE,
582                              ble_hci_vuart_acl_buf,
583                              "ble_hci_vuart_acl_pool");
584     SYSINIT_PANIC_ASSERT(rc == 0);
585     rc = os_mbuf_pool_init(&ble_hci_vuart_acl_mbuf_pool,
586                            &ble_hci_vuart_acl_pool.mpe_mp,
587                            ACL_BLOCK_SIZE,
588                            MYNEWT_VAL(BLE_ACL_BUF_COUNT));
589     SYSINIT_PANIC_ASSERT(rc == 0);
590     /*
591      * Create memory pool of HCI command buffers. NOTE: we currently dont
592      * allow this to be configured. The controller will only allow one
593      * outstanding command. We decided to keep this a pool in case we allow
594      * allow the controller to handle more than one outstanding command.
595      */
596 #if MYNEWT_VAL(SYS_MEM_DYNAMIC)
597     ble_hci_vuart_cmd_buf = (os_membuf_t *)tls_mem_alloc(
598         sizeof(os_membuf_t) *
599         OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ));
600     assert(ble_hci_vuart_cmd_buf != NULL);
601 #endif
602     rc = os_mempool_init(&ble_hci_vuart_cmd_pool,
603                          1,
604                          BLE_HCI_TRANS_CMD_SZ,
605                          ble_hci_vuart_cmd_buf,
606                          "ble_hci_vuart_cmd_pool");
607     SYSINIT_PANIC_ASSERT(rc == 0);
608 #if MYNEWT_VAL(SYS_MEM_DYNAMIC)
609     ble_hci_vuart_evt_hi_buf = (os_membuf_t *)tls_mem_alloc(
610         sizeof(os_membuf_t) *
611         OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
612                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)));
613     assert(ble_hci_vuart_evt_hi_buf != NULL);
614 #endif
615     rc = os_mempool_init(&ble_hci_vuart_evt_hi_pool,
616                          MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
617                          MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
618                          ble_hci_vuart_evt_hi_buf,
619                          "ble_hci_vuart_evt_hi_pool");
620     SYSINIT_PANIC_ASSERT(rc == 0);
621 #if MYNEWT_VAL(SYS_MEM_DYNAMIC)
622     ble_hci_vuart_evt_lo_buf = (os_membuf_t *)tls_mem_alloc(
623         sizeof(os_membuf_t) *
624         OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
625                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)));
626     assert(ble_hci_vuart_evt_lo_buf != NULL);
627 #endif
628     rc = os_mempool_init(&ble_hci_vuart_evt_lo_pool,
629                          MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
630                          MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
631                          ble_hci_vuart_evt_lo_buf,
632                          "ble_hci_vuart_evt_lo_pool");
633     SYSINIT_PANIC_ASSERT(rc == 0);
634 
635     return rc;
636 }
637 
ble_hci_vuart_deinit(void)638 int ble_hci_vuart_deinit(void)
639 {
640     int rc;
641     rc = wm_ble_controller_deinit();
642     assert(rc == 0);
643 #if MYNEWT_VAL(SYS_MEM_DYNAMIC)
644 
645     if (ble_hci_vuart_acl_buf) {
646         tls_mem_free(ble_hci_vuart_acl_buf);
647         ble_hci_vuart_acl_buf = NULL;
648     }
649 
650     if (ble_hci_vuart_cmd_buf) {
651         tls_mem_free(ble_hci_vuart_cmd_buf);
652         ble_hci_vuart_cmd_buf = NULL;
653     }
654 
655     if (ble_hci_vuart_evt_hi_buf) {
656         tls_mem_free(ble_hci_vuart_evt_hi_buf);
657         ble_hci_vuart_evt_hi_buf = NULL;
658     }
659 
660     if (ble_hci_vuart_evt_lo_buf) {
661         tls_mem_free(ble_hci_vuart_evt_lo_buf);
662         ble_hci_vuart_evt_lo_buf = NULL;
663     }
664 
665 #endif
666     return rc;
667 }