You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by an...@apache.org on 2022/03/17 10:50:18 UTC

[mynewt-nimble] 08/22: nimble/transport: Update UART transport

This is an automated email from the ASF dual-hosted git repository.

andk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit aefb9d4a90effefc77500e8968eafd3f336c7d06
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Thu Mar 3 18:06:04 2022 +0100

    nimble/transport: Update UART transport
---
 .../uart/include/transport/uart/ble_hci_uart.h     |   33 -
 nimble/transport/uart/pkg.yml                      |   11 +-
 nimble/transport/uart/src/ble_hci_uart.c           | 1187 --------------------
 nimble/transport/uart/src/hci_uart.c               |  247 ++++
 nimble/transport/uart/syscfg.yml                   |   62 +-
 5 files changed, 270 insertions(+), 1270 deletions(-)

diff --git a/nimble/transport/uart/include/transport/uart/ble_hci_uart.h b/nimble/transport/uart/include/transport/uart/ble_hci_uart.h
deleted file mode 100644
index e5e1084..0000000
--- a/nimble/transport/uart/include/transport/uart/ble_hci_uart.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#ifndef H_BLE_HCI_UART_
-#define H_BLE_HCI_UART_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void ble_hci_uart_init(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/nimble/transport/uart/pkg.yml b/nimble/transport/uart/pkg.yml
index fd16a08..2802961 100644
--- a/nimble/transport/uart/pkg.yml
+++ b/nimble/transport/uart/pkg.yml
@@ -18,20 +18,15 @@
 #
 
 pkg.name: nimble/transport/uart
-pkg.description: XXX
+pkg.description: HCI H4 transport over UART
 pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
-pkg.homepage: "http://mynewt.apache.org/"
-pkg.keywords:
-    - ble
-    - bluetooth
+pkg.homepage: "https://mynewt.apache.org/"
 
 pkg.deps:
     - "@apache-mynewt-core/hw/hal"
     - "@apache-mynewt-core/kernel/os"
     - nimble
+    - nimble/transport/common/hci_h4
 
 pkg.apis:
     - ble_transport
-
-pkg.init:
-    ble_hci_uart_init: 'MYNEWT_VAL(BLE_TRANS_UART_SYSINIT_STAGE)'
diff --git a/nimble/transport/uart/src/ble_hci_uart.c b/nimble/transport/uart/src/ble_hci_uart.c
deleted file mode 100644
index 0b6e0e5..0000000
--- a/nimble/transport/uart/src/ble_hci_uart.c
+++ /dev/null
@@ -1,1187 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdint.h>
-#include "sysinit/sysinit.h"
-#include "syscfg/syscfg.h"
-#include "os/os_cputime.h"
-#include "bsp/bsp.h"
-#include "os/os.h"
-#include "hal/hal_uart.h"
-
-/* BLE */
-#include "nimble/ble.h"
-#include "nimble/nimble_opt.h"
-#include "nimble/hci_common.h"
-#include "nimble/ble_hci_trans.h"
-
-#include "transport/uart/ble_hci_uart.h"
-
-#define BLE_HCI_UART_EVT_COUNT  \
-    (MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT) + MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT))
-
-/***
- * NOTES:
- * The UART HCI transport doesn't use event buffer priorities.  All incoming
- * and outgoing events use buffers from the same pool.
- *
- * The "skip" definitions are here so that when buffers cannot be allocated,
- * the command or acl packets are simply skipped so that the HCI interface
- * does not lose synchronization and resets dont (necessarily) occur.
- */
-
-/* XXX: for now, define this here */
-#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE)
-extern void ble_ll_data_buffer_overflow(void);
-extern void ble_ll_hw_error(void);
-
-static const uint8_t ble_hci_uart_reset_cmd[4] = { 0x01, 0x03, 0x0C, 0x00 };
-#endif
-
-/***
- * NOTES:
- * The "skip" definitions are here so that when buffers cannot be allocated,
- * the command or acl packets are simply skipped so that the HCI interface
- * does not lose synchronization and resets dont (necessarily) occur.
- */
-#define BLE_HCI_UART_H4_NONE        0x00
-#define BLE_HCI_UART_H4_CMD         0x01
-#define BLE_HCI_UART_H4_ACL         0x02
-#define BLE_HCI_UART_H4_SCO         0x03
-#define BLE_HCI_UART_H4_EVT         0x04
-#define BLE_HCI_UART_H4_SYNC_LOSS   0x80
-#define BLE_HCI_UART_H4_SKIP_CMD    0x81
-#define BLE_HCI_UART_H4_SKIP_ACL    0x82
-#define BLE_HCI_UART_H4_LE_EVT      0x83
-#define BLE_HCI_UART_H4_SKIP_EVT    0x84
-
-static ble_hci_trans_rx_cmd_fn *ble_hci_uart_rx_cmd_cb;
-static void *ble_hci_uart_rx_cmd_arg;
-
-static ble_hci_trans_rx_acl_fn *ble_hci_uart_rx_acl_cb;
-static void *ble_hci_uart_rx_acl_arg;
-
-static struct os_mempool ble_hci_uart_evt_hi_pool;
-static os_membuf_t ble_hci_uart_evt_hi_buf[
-        OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
-                        MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
-];
-
-static struct os_mempool ble_hci_uart_evt_lo_pool;
-static os_membuf_t ble_hci_uart_evt_lo_buf[
-        OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
-                        MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))
-];
-
-static struct os_mempool ble_hci_uart_cmd_pool;
-static os_membuf_t ble_hci_uart_cmd_buf[
-	OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ)
-];
-
-static struct os_mbuf_pool ble_hci_uart_acl_mbuf_pool;
-static struct os_mempool_ext ble_hci_uart_acl_pool;
-
-/*
- * The MBUF payload size must accommodate the HCI data header size plus the
- * maximum ACL data packet length. The ACL block size is the size of the
- * mbufs we will allocate.
- */
-#define ACL_BLOCK_SIZE  OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) \
-                                 + BLE_MBUF_MEMBLOCK_OVERHEAD \
-                                 + BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
-
-static os_membuf_t ble_hci_uart_acl_buf[
-	OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_ACL_BUF_COUNT),
-                        ACL_BLOCK_SIZE)
-];
-
-/**
- * A packet to be sent over the UART.  This can be a command, an event, or ACL
- * data.
- */
-struct ble_hci_uart_pkt {
-    STAILQ_ENTRY(ble_hci_uart_pkt) next;
-    void *data;
-    uint8_t type;
-};
-
-static struct os_mempool ble_hci_uart_pkt_pool;
-static os_membuf_t ble_hci_uart_pkt_buf[
-        OS_MEMPOOL_SIZE(BLE_HCI_UART_EVT_COUNT + 1 +
-                        MYNEWT_VAL(BLE_HCI_ACL_OUT_COUNT),
-                        sizeof (struct ble_hci_uart_pkt))
-];
-
-/**
- * An incoming or outgoing command or event.
- */
-struct ble_hci_uart_cmd {
-    uint8_t *data;      /* Pointer to ble_hci_uart_cmd data */
-    uint16_t cur;       /* Number of bytes read/written */
-    uint16_t len;       /* Total number of bytes to read/write */
-};
-
-/**
- * An incoming ACL data packet.
- */
-struct ble_hci_uart_acl {
-    struct os_mbuf *buf; /* Buffer containing the data */
-    uint8_t *dptr;       /* Pointer to where bytes should be placed */
-    uint16_t len;        /* Target size when buf is considered complete */
-    uint16_t rxd_bytes;  /* current count of bytes received for packet */
-};
-
-/**
- * Structure for transmitting ACL packets over UART
- *
- */
-struct ble_hci_uart_h4_acl_tx
-{
-    uint8_t *dptr;
-    struct os_mbuf *tx_acl;
-};
-
-static struct {
-    /*** State of data received over UART. */
-    uint8_t rx_type;    /* Pending packet type. 0 means nothing pending */
-    union {
-        struct ble_hci_uart_cmd rx_cmd;
-        struct ble_hci_uart_acl rx_acl;
-    };
-
-    /*** State of data transmitted over UART. */
-    uint8_t tx_type;    /* Pending packet type. 0 means nothing pending */
-    uint16_t rem_tx_len; /* Used for acl tx only currently */
-    union {
-        struct ble_hci_uart_cmd tx_cmd;
-        struct ble_hci_uart_h4_acl_tx tx_pkt;
-    };
-    STAILQ_HEAD(, ble_hci_uart_pkt) tx_pkts; /* Packet queue to send to UART */
-} ble_hci_uart_state;
-
-/**
- * Allocates a buffer (mbuf) for ACL operation.
- *
- * @return                      The allocated buffer on success;
- *                              NULL on buffer exhaustion.
- */
-static struct os_mbuf *
-ble_hci_trans_acl_buf_alloc(void)
-{
-    struct os_mbuf *m;
-    uint8_t usrhdr_len;
-
-#if MYNEWT_VAL(BLE_CONTROLLER)
-    usrhdr_len = sizeof(struct ble_mbuf_hdr);
-#else
-    usrhdr_len = 0;
-#endif
-
-    m = os_mbuf_get_pkthdr(&ble_hci_uart_acl_mbuf_pool, usrhdr_len);
-    return m;
-}
-
-static int
-ble_hci_uart_acl_tx(struct os_mbuf *om)
-{
-    struct ble_hci_uart_pkt *pkt;
-    os_sr_t sr;
-
-    /* If this packet is zero length, just free it */
-    if (OS_MBUF_PKTLEN(om) == 0) {
-        os_mbuf_free_chain(om);
-        return 0;
-    }
-
-    pkt = os_memblock_get(&ble_hci_uart_pkt_pool);
-    if (pkt == NULL) {
-        os_mbuf_free_chain(om);
-        return BLE_ERR_MEM_CAPACITY;
-    }
-
-    pkt->type = BLE_HCI_UART_H4_ACL;
-    pkt->data = om;
-
-    OS_ENTER_CRITICAL(sr);
-    STAILQ_INSERT_TAIL(&ble_hci_uart_state.tx_pkts, pkt, next);
-    OS_EXIT_CRITICAL(sr);
-
-    hal_uart_start_tx(MYNEWT_VAL(BLE_HCI_UART_PORT));
-
-    return 0;
-}
-
-static int
-ble_hci_uart_cmdevt_tx(uint8_t *hci_ev, uint8_t h4_type)
-{
-    struct ble_hci_uart_pkt *pkt;
-    os_sr_t sr;
-
-    pkt = os_memblock_get(&ble_hci_uart_pkt_pool);
-    if (pkt == NULL) {
-        ble_hci_trans_buf_free(hci_ev);
-        return BLE_ERR_MEM_CAPACITY;
-    }
-
-    pkt->type = h4_type;
-    pkt->data = hci_ev;
-
-    OS_ENTER_CRITICAL(sr);
-    STAILQ_INSERT_TAIL(&ble_hci_uart_state.tx_pkts, pkt, next);
-    OS_EXIT_CRITICAL(sr);
-
-    hal_uart_start_tx(MYNEWT_VAL(BLE_HCI_UART_PORT));
-
-    return 0;
-}
-
-/**
- * @return                      The packet type to transmit on success;
- *                              -1 if there is nothing to send.
- */
-static int
-ble_hci_uart_tx_pkt_type(void)
-{
-    struct ble_hci_uart_pkt *pkt;
-    struct os_mbuf *om;
-    os_sr_t sr;
-    int rc;
-
-    OS_ENTER_CRITICAL(sr);
-
-    pkt = STAILQ_FIRST(&ble_hci_uart_state.tx_pkts);
-    if (!pkt) {
-        OS_EXIT_CRITICAL(sr);
-        return -1;
-    }
-
-    STAILQ_REMOVE(&ble_hci_uart_state.tx_pkts, pkt, ble_hci_uart_pkt, next);
-
-    OS_EXIT_CRITICAL(sr);
-
-    rc = pkt->type;
-    switch (pkt->type) {
-    case BLE_HCI_UART_H4_CMD:
-        ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_CMD;
-        ble_hci_uart_state.tx_cmd.data = pkt->data;
-        ble_hci_uart_state.tx_cmd.cur = 0;
-        ble_hci_uart_state.tx_cmd.len = ble_hci_uart_state.tx_cmd.data[2] +
-                                        sizeof(struct ble_hci_cmd);
-        break;
-
-    case BLE_HCI_UART_H4_EVT:
-        ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_EVT;
-        ble_hci_uart_state.tx_cmd.data = pkt->data;
-        ble_hci_uart_state.tx_cmd.cur = 0;
-        ble_hci_uart_state.tx_cmd.len = ble_hci_uart_state.tx_cmd.data[1] +
-                                        sizeof(struct ble_hci_ev);
-        break;
-
-    case BLE_HCI_UART_H4_ACL:
-        ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_ACL;
-        om = (struct os_mbuf *)pkt->data;
-        /* NOTE: first mbuf must have non-zero length */
-        os_mbuf_trim_front(om);
-        ble_hci_uart_state.tx_pkt.tx_acl = om;
-        ble_hci_uart_state.tx_pkt.dptr = om->om_data;
-        ble_hci_uart_state.rem_tx_len = OS_MBUF_PKTLEN(om);
-        break;
-
-    default:
-        rc = -1;
-        break;
-    }
-
-    os_memblock_put(&ble_hci_uart_pkt_pool, pkt);
-
-    return rc;
-}
-
-/**
- * @return                      The byte to transmit on success;
- *                              -1 if there is nothing to send.
- */
-static int
-ble_hci_uart_tx_char(void *arg)
-{
-    uint8_t u8;
-    int rc;
-    struct os_mbuf *om;
-
-    switch (ble_hci_uart_state.tx_type) {
-    case BLE_HCI_UART_H4_NONE: /* No pending packet, pick one from the queue */
-        rc = ble_hci_uart_tx_pkt_type();
-        break;
-
-    case BLE_HCI_UART_H4_CMD:
-    case BLE_HCI_UART_H4_EVT:
-        rc = ble_hci_uart_state.tx_cmd.data[ble_hci_uart_state.tx_cmd.cur++];
-
-        if (ble_hci_uart_state.tx_cmd.cur == ble_hci_uart_state.tx_cmd.len) {
-            ble_hci_trans_buf_free(ble_hci_uart_state.tx_cmd.data);
-            ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_NONE;
-        }
-        break;
-
-    case BLE_HCI_UART_H4_ACL:
-        /* Copy the first unsent byte from the tx buffer and remove it from the
-         * source.
-         */
-        u8 = ble_hci_uart_state.tx_pkt.dptr[0];
-        --ble_hci_uart_state.rem_tx_len;
-        if (ble_hci_uart_state.rem_tx_len == 0) {
-            os_mbuf_free_chain(ble_hci_uart_state.tx_pkt.tx_acl);
-            ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_NONE;
-        } else {
-            om = ble_hci_uart_state.tx_pkt.tx_acl;
-            --om->om_len;
-            if (om->om_len == 0) {
-                /* Remove and free any zero mbufs */
-                while ((om != NULL) && (om->om_len == 0)) {
-                    ble_hci_uart_state.tx_pkt.tx_acl = SLIST_NEXT(om, om_next);
-                    os_mbuf_free(om);
-                    om = ble_hci_uart_state.tx_pkt.tx_acl;
-                }
-                /* NOTE: om should never be NULL! What to do? */
-                if (om == NULL) {
-                    assert(0);
-                    ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_NONE;
-                } else {
-                    ble_hci_uart_state.tx_pkt.dptr = om->om_data;
-                }
-            } else {
-                ble_hci_uart_state.tx_pkt.dptr++;
-            }
-        }
-        rc = u8;
-        break;
-    default:
-        rc = -1;
-        break;
-    }
-
-    return rc;
-}
-
-#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE)
-/**
- * HCI uart sync lost.
- *
- * This occurs when the controller receives an invalid packet type or a length
- * field that is out of range. The controller needs to send a HW error to the
- * host and wait to find a LL reset command.
- */
-static void
-ble_hci_uart_sync_lost(void)
-{
-    ble_hci_uart_state.rx_cmd.len = 0;
-    ble_hci_uart_state.rx_cmd.cur = 0;
-    ble_hci_uart_state.rx_cmd.data =
-        ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
-    ble_ll_hw_error();
-    ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_SYNC_LOSS;
-}
-#endif
-
-/**
- * @return                      The type of packet to follow success;
- *                              -1 if there is no valid packet to receive.
- */
-static int
-ble_hci_uart_rx_pkt_type(uint8_t data)
-{
-    struct os_mbuf *m;
-
-    ble_hci_uart_state.rx_type = data;
-
-    switch (ble_hci_uart_state.rx_type) {
-    /* Host should never receive a command! */
-#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE)
-    case BLE_HCI_UART_H4_CMD:
-        ble_hci_uart_state.rx_cmd.len = 0;
-        ble_hci_uart_state.rx_cmd.cur = 0;
-        ble_hci_uart_state.rx_cmd.data =
-            ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
-        if (ble_hci_uart_state.rx_cmd.data == NULL) {
-            ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_SKIP_CMD;
-        }
-        break;
-#endif
-
-        /* Controller should never receive an event */
-#if MYNEWT_VAL(BLE_HOST)
-    case BLE_HCI_UART_H4_EVT:
-        /*
-         * The event code is unknown at the moment. Depending on event priority,
-         * buffer *shall* be allocated from ble_hci_uart_evt_hi_pool
-         * or "may* be allocated from ble_hci_uart_evt_lo_pool.
-         * Thus do not allocate the buffer yet.
-         */
-        ble_hci_uart_state.rx_cmd.data = NULL;
-        ble_hci_uart_state.rx_cmd.len = 0;
-        ble_hci_uart_state.rx_cmd.cur = 0;
-        break;
-#endif
-
-    case BLE_HCI_UART_H4_ACL:
-        ble_hci_uart_state.rx_acl.len = 0;
-        ble_hci_uart_state.rx_acl.rxd_bytes = 0;
-        m = ble_hci_trans_acl_buf_alloc();
-        if (m) {
-            ble_hci_uart_state.rx_acl.dptr = m->om_data;
-        } else {
-            ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_SKIP_ACL;
-        }
-        ble_hci_uart_state.rx_acl.buf = m;
-        break;
-
-    default:
-#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE)
-        /*
-         * If we receive an unknown HCI packet type this is considered a loss
-         * of sync.
-         */
-        ble_hci_uart_sync_lost();
-#else
-        /*
-         * XXX: not sure what to do about host in this case. Just go back to
-         * none for now.
-         */
-        ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
-#endif
-        break;
-    }
-
-    return 0;
-}
-
-#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE)
-/**
- * HCI uart sync loss.
- *
- * Find a LL reset command in the byte stream. The LL reset command is a
- * sequence of 4 bytes:
- *  0x01    HCI Packet Type = HCI CMD
- *  0x03    OCF for reset command
- *  0x0C    OGF for reset command (0x03 shifted left by two bits as the OGF
- *          occupies the uopper 6 bits of this byte.
- *  0x00    Parameter length of reset command (no parameters).
- *
- * @param data Byte received over serial port
- */
-void
-ble_hci_uart_rx_sync_loss(uint8_t data)
-{
-    int rc;
-    int index;
-
-    /*
-     * If we couldnt allocate a command buffer (should not occur but
-     * possible) try to allocate one on each received character. If we get
-     * a reset and buffer is not available we have to ignore reset.
-     */
-    if (ble_hci_uart_state.rx_cmd.data == NULL) {
-        ble_hci_uart_state.rx_cmd.data =
-            ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
-    }
-
-    index = ble_hci_uart_state.rx_cmd.cur;
-    if (data == ble_hci_uart_reset_cmd[index]) {
-        if (index == 3) {
-            if (ble_hci_uart_state.rx_cmd.data == NULL) {
-                index = 0;
-            } else {
-                assert(ble_hci_uart_rx_cmd_cb != NULL);
-                ble_hci_uart_state.rx_cmd.data[0] = 0x03;
-                ble_hci_uart_state.rx_cmd.data[1] = 0x0C;
-                ble_hci_uart_state.rx_cmd.data[2] = 0x00;
-                rc = ble_hci_uart_rx_cmd_cb(ble_hci_uart_state.rx_cmd.data,
-                                            ble_hci_uart_rx_cmd_arg);
-                if (rc != 0) {
-                    ble_hci_trans_buf_free(ble_hci_uart_state.rx_cmd.data);
-                }
-                ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
-            }
-        } else {
-            ++index;
-        }
-    } else {
-        index = 0;
-    }
-
-    ble_hci_uart_state.rx_cmd.cur = index;
-}
-
-static void
-ble_hci_uart_rx_cmd(uint8_t data)
-{
-    int rc;
-
-    ble_hci_uart_state.rx_cmd.data[ble_hci_uart_state.rx_cmd.cur++] = data;
-
-    if (ble_hci_uart_state.rx_cmd.cur < sizeof(struct ble_hci_cmd)) {
-        return;
-    }
-
-    if (ble_hci_uart_state.rx_cmd.cur == sizeof(struct ble_hci_cmd)) {
-        ble_hci_uart_state.rx_cmd.len = ble_hci_uart_state.rx_cmd.data[2] +
-                                        sizeof(struct ble_hci_cmd);
-    }
-
-    if (ble_hci_uart_state.rx_cmd.cur == ble_hci_uart_state.rx_cmd.len) {
-        assert(ble_hci_uart_rx_cmd_cb != NULL);
-        rc = ble_hci_uart_rx_cmd_cb(ble_hci_uart_state.rx_cmd.data,
-                                    ble_hci_uart_rx_cmd_arg);
-        if (rc != 0) {
-            ble_hci_trans_buf_free(ble_hci_uart_state.rx_cmd.data);
-        }
-        ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
-    }
-}
-
-static void
-ble_hci_uart_rx_skip_cmd(uint8_t data)
-{
-    ble_hci_uart_state.rx_cmd.cur++;
-
-    if (ble_hci_uart_state.rx_cmd.cur < sizeof(struct ble_hci_cmd)) {
-        return;
-    }
-
-    if (ble_hci_uart_state.rx_cmd.cur == sizeof(struct ble_hci_cmd)) {
-        ble_hci_uart_state.rx_cmd.len = data + sizeof(struct ble_hci_cmd);
-    }
-
-    if (ble_hci_uart_state.rx_cmd.cur == ble_hci_uart_state.rx_cmd.len) {
-        /*
-         * XXX: for now we simply skip the command and do nothing. This
-         * should not happen but at least we retain HCI synch. The host
-         * can decide what to do in this case. It may be appropriate for
-         * the controller to attempt to send back a command complete or
-         * command status in this case.
-         */
-        ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
-    }
-}
-#endif
-
-#if MYNEWT_VAL(BLE_HOST)
-static inline void
-ble_hci_uart_rx_evt_cb(void)
-{
-    int rc;
-
-    if (ble_hci_uart_state.rx_cmd.cur == ble_hci_uart_state.rx_cmd.len) {
-        assert(ble_hci_uart_rx_cmd_cb != NULL);
-        rc = ble_hci_uart_rx_cmd_cb(ble_hci_uart_state.rx_cmd.data,
-                                    ble_hci_uart_rx_cmd_arg);
-        if (rc != 0) {
-            ble_hci_trans_buf_free(ble_hci_uart_state.rx_cmd.data);
-        }
-        ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
-    }
-}
-
-static void
-ble_hci_uart_rx_evt(uint8_t data)
-{
-    /* Determine event priority to allocate buffer */
-    if (!ble_hci_uart_state.rx_cmd.data) {
-        /* In case of LE Meta Event priority might be still unknown */
-        if (data == BLE_HCI_EVCODE_LE_META) {
-            ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_LE_EVT;
-            ble_hci_uart_state.rx_cmd.cur++;
-            return;
-        }
-
-        ble_hci_uart_state.rx_cmd.data =
-            ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
-        assert(ble_hci_uart_state.rx_cmd.data != NULL);
-    }
-
-    ble_hci_uart_state.rx_cmd.data[ble_hci_uart_state.rx_cmd.cur++] = data;
-
-    if (ble_hci_uart_state.rx_cmd.cur < sizeof(struct ble_hci_ev)) {
-        return;
-    }
-
-    if (ble_hci_uart_state.rx_cmd.cur == sizeof(struct ble_hci_ev)) {
-        ble_hci_uart_state.rx_cmd.len = ble_hci_uart_state.rx_cmd.data[1] +
-                                        sizeof(struct ble_hci_ev);
-    }
-
-    ble_hci_uart_rx_evt_cb();
-}
-
-static void
-ble_hci_uart_rx_le_evt(uint8_t data)
-{
-    ble_hci_uart_state.rx_cmd.cur++;
-
-    if (ble_hci_uart_state.rx_cmd.cur == sizeof(struct ble_hci_ev)) {
-        /* LE Meta Event parameter length is never 0 */
-        assert(data != 0);
-        ble_hci_uart_state.rx_cmd.len = data + sizeof(struct ble_hci_ev);
-        return;
-    }
-
-    /* Determine event priority to allocate buffer */
-    if (!ble_hci_uart_state.rx_cmd.data) {
-        /* Determine event priority to allocate buffer */
-        if (data == BLE_HCI_LE_SUBEV_ADV_RPT ||
-                data == BLE_HCI_LE_SUBEV_EXT_ADV_RPT) {
-            ble_hci_uart_state.rx_cmd.data =
-                ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
-            if (ble_hci_uart_state.rx_cmd.data == NULL) {
-                ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_SKIP_EVT;
-                return;
-            }
-        } else {
-            ble_hci_uart_state.rx_cmd.data =
-                ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
-            assert(ble_hci_uart_state.rx_cmd.data != NULL);
-        }
-
-        ble_hci_uart_state.rx_cmd.data[0] = BLE_HCI_EVCODE_LE_META;
-        ble_hci_uart_state.rx_cmd.data[1] =
-                ble_hci_uart_state.rx_cmd.len - sizeof(struct ble_hci_ev);
-    }
-
-    ble_hci_uart_state.rx_cmd.data[ble_hci_uart_state.rx_cmd.cur - 1] = data;
-    ble_hci_uart_rx_evt_cb();
-}
-
-static void
-ble_hci_uart_rx_skip_evt(uint8_t data)
-{
-    if (++ble_hci_uart_state.rx_cmd.cur == ble_hci_uart_state.rx_cmd.len) {
-        ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
-    }
-}
-#endif
-
-static void
-ble_hci_uart_rx_acl(uint8_t data)
-{
-    uint16_t rxd_bytes;
-    uint16_t pktlen;
-
-    rxd_bytes = ble_hci_uart_state.rx_acl.rxd_bytes;
-    ble_hci_uart_state.rx_acl.dptr[rxd_bytes] = data;
-    ++rxd_bytes;
-    ble_hci_uart_state.rx_acl.rxd_bytes = rxd_bytes;
-
-    if (rxd_bytes < BLE_HCI_DATA_HDR_SZ) {
-        return;
-    }
-
-    if (rxd_bytes == BLE_HCI_DATA_HDR_SZ) {
-        pktlen = ble_hci_uart_state.rx_acl.dptr[3];
-        pktlen = (pktlen << 8) + ble_hci_uart_state.rx_acl.dptr[2];
-        ble_hci_uart_state.rx_acl.len = pktlen + BLE_HCI_DATA_HDR_SZ;
-
-        /*
-         * Data portion cannot exceed data length of acl buffer. If it does
-         * this is considered to be a loss of sync.
-         */
-        if (pktlen > MYNEWT_VAL(BLE_ACL_BUF_SIZE)) {
-            os_mbuf_free_chain(ble_hci_uart_state.rx_acl.buf);
-#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE)
-            ble_hci_uart_sync_lost();
-#else
-        /*
-         * XXX: not sure what to do about host in this case. Just go back to
-         * none for now.
-         */
-        ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
-#endif
-        }
-    }
-
-    if (rxd_bytes == ble_hci_uart_state.rx_acl.len) {
-        assert(ble_hci_uart_rx_acl_cb != NULL);
-        /* XXX: can this callback fail? What if it does? */
-        OS_MBUF_PKTLEN(ble_hci_uart_state.rx_acl.buf) = rxd_bytes;
-        ble_hci_uart_state.rx_acl.buf->om_len = rxd_bytes;
-        ble_hci_uart_rx_acl_cb(ble_hci_uart_state.rx_acl.buf,
-                               ble_hci_uart_rx_acl_arg);
-        ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
-    }
-}
-
-static void
-ble_hci_uart_rx_skip_acl(uint8_t data)
-{
-    uint16_t rxd_bytes;
-    uint16_t pktlen;
-
-    rxd_bytes = ble_hci_uart_state.rx_acl.rxd_bytes;
-    ++rxd_bytes;
-    ble_hci_uart_state.rx_acl.rxd_bytes = rxd_bytes;
-
-    if (rxd_bytes == (BLE_HCI_DATA_HDR_SZ - 1)) {
-        ble_hci_uart_state.rx_acl.len = data;
-        return;
-    }
-
-    if (rxd_bytes == BLE_HCI_DATA_HDR_SZ) {
-        pktlen = data;
-        pktlen = (pktlen << 8) + ble_hci_uart_state.rx_acl.len;
-        ble_hci_uart_state.rx_acl.len = pktlen + BLE_HCI_DATA_HDR_SZ;
-    }
-
-    if (rxd_bytes == ble_hci_uart_state.rx_acl.len) {
-/* XXX: I dont like this but for now this denotes controller only */
-#if MYNEWT_VAL(BLE_CONTROLLER)
-#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL)
-        ble_ll_data_buffer_overflow();
-#endif
-#endif
-        ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
-    }
-}
-
-static int
-ble_hci_uart_rx_char(void *arg, uint8_t data)
-{
-    switch (ble_hci_uart_state.rx_type) {
-    case BLE_HCI_UART_H4_NONE:
-        return ble_hci_uart_rx_pkt_type(data);
-#if MYNEWT_VAL(BLE_CONTROLLER) || MYNEWT_VAL(BLE_HCI_BRIDGE)
-    case BLE_HCI_UART_H4_CMD:
-        ble_hci_uart_rx_cmd(data);
-        return 0;
-    case BLE_HCI_UART_H4_SKIP_CMD:
-        ble_hci_uart_rx_skip_cmd(data);
-        return 0;
-    case BLE_HCI_UART_H4_SYNC_LOSS:
-        ble_hci_uart_rx_sync_loss(data);
-        return 0;
-#endif
-#if MYNEWT_VAL(BLE_HOST)
-    case BLE_HCI_UART_H4_EVT:
-        ble_hci_uart_rx_evt(data);
-        return 0;
-    case BLE_HCI_UART_H4_LE_EVT:
-        ble_hci_uart_rx_le_evt(data);
-        return 0;
-    case BLE_HCI_UART_H4_SKIP_EVT:
-        ble_hci_uart_rx_skip_evt(data);
-        return 0;
-#endif
-    case BLE_HCI_UART_H4_ACL:
-        ble_hci_uart_rx_acl(data);
-        return 0;
-    case BLE_HCI_UART_H4_SKIP_ACL:
-        ble_hci_uart_rx_skip_acl(data);
-        return 0;
-    default:
-        /* This should never happen! */
-        assert(0);
-        return 0;
-    }
-}
-
-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)
-{
-    ble_hci_uart_rx_cmd_cb = cmd_cb;
-    ble_hci_uart_rx_cmd_arg = cmd_arg;
-    ble_hci_uart_rx_acl_cb = acl_cb;
-    ble_hci_uart_rx_acl_arg = acl_arg;
-}
-
-static void
-ble_hci_uart_free_pkt(uint8_t type, uint8_t *cmdevt, struct os_mbuf *acl)
-{
-    switch (type) {
-    case BLE_HCI_UART_H4_NONE:
-        break;
-
-    case BLE_HCI_UART_H4_CMD:
-    case BLE_HCI_UART_H4_EVT:
-        ble_hci_trans_buf_free(cmdevt);
-        break;
-
-    case BLE_HCI_UART_H4_ACL:
-        os_mbuf_free_chain(acl);
-        break;
-
-    default:
-        assert(0);
-        break;
-    }
-}
-
-static int
-ble_hci_uart_config(void)
-{
-    int rc;
-
-    rc = hal_uart_init_cbs(MYNEWT_VAL(BLE_HCI_UART_PORT),
-                           ble_hci_uart_tx_char, NULL,
-                           ble_hci_uart_rx_char, NULL);
-    if (rc != 0) {
-        return BLE_ERR_UNSPECIFIED;
-    }
-
-    rc = hal_uart_config(MYNEWT_VAL(BLE_HCI_UART_PORT),
-                         MYNEWT_VAL(BLE_HCI_UART_BAUD),
-                         MYNEWT_VAL(BLE_HCI_UART_DATA_BITS),
-                         MYNEWT_VAL(BLE_HCI_UART_STOP_BITS),
-                         MYNEWT_VAL(BLE_HCI_UART_PARITY),
-                         MYNEWT_VAL(BLE_HCI_UART_FLOW_CTRL));
-    if (rc != 0) {
-        return BLE_ERR_HW_FAIL;
-    }
-
-    return 0;
-}
-
-/**
- * Sends an HCI event from the controller to the host.
- *
- * @param cmd                   The HCI event to send.  This buffer must be
- *                                  allocated via ble_hci_trans_buf_alloc().
- *
- * @return                      0 on success;
- *                              A BLE_ERR_[...] error code on failure.
- */
-int
-ble_hci_trans_ll_evt_tx(uint8_t *cmd)
-{
-    int rc;
-
-    rc = ble_hci_uart_cmdevt_tx(cmd, BLE_HCI_UART_H4_EVT);
-    return rc;
-}
-
-/**
- * Sends ACL data from controller to host.
- *
- * @param om                    The ACL data packet to send.
- *
- * @return                      0 on success;
- *                              A BLE_ERR_[...] error code on failure.
- */
-int
-ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
-{
-    int rc;
-
-    rc = ble_hci_uart_acl_tx(om);
-    return rc;
-}
-
-#if MYNEWT_VAL(BLE_HOST)
-/**
- * Sends an HCI command from the host to the controller.
- *
- * @param cmd                   The HCI command to send.  This buffer must be
- *                                  allocated via ble_hci_trans_buf_alloc().
- *
- * @return                      0 on success;
- *                              A BLE_ERR_[...] error code on failure.
- */
-int
-ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
-{
-    int rc;
-
-    rc = ble_hci_uart_cmdevt_tx(cmd, BLE_HCI_UART_H4_CMD);
-    return rc;
-}
-
-/**
- * Sends ACL data from host to controller.
- *
- * @param om                    The ACL data packet to send.
- *
- * @return                      0 on success;
- *                              A BLE_ERR_[...] error code on failure.
- */
-int
-ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
-{
-    int rc;
-
-    rc = ble_hci_uart_acl_tx(om);
-    return rc;
-}
-
-/**
- * Configures the HCI transport to call the specified callback upon receiving
- * HCI packets from the controller.  This function should only be called by by
- * host.
- *
- * @param cmd_cb                The callback to execute upon receiving an HCI
- *                                  event.
- * @param cmd_arg               Optional argument to pass to the command
- *                                  callback.
- * @param acl_cb                The callback to execute upon receiving ACL
- *                                  data.
- * @param acl_arg               Optional argument to pass to the ACL
- *                                  callback.
- */
-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)
-{
-    ble_hci_uart_set_rx_cbs(cmd_cb, cmd_arg, acl_cb, acl_arg);
-}
-#endif
-
-/**
- * Configures the HCI transport to operate with a host.  The transport will
- * execute specified callbacks upon receiving HCI packets from the controller.
- *
- * @param cmd_cb                The callback to execute upon receiving an HCI
- *                                  event.
- * @param cmd_arg               Optional argument to pass to the command
- *                                  callback.
- * @param acl_cb                The callback to execute upon receiving ACL
- *                                  data.
- * @param acl_arg               Optional argument to pass to the ACL
- *                                  callback.
- */
-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)
-{
-    ble_hci_uart_set_rx_cbs(cmd_cb, cmd_arg, acl_cb, acl_arg);
-}
-
-/**
- * Allocates a flat buffer of the specified type.
- *
- * @param type                  The type of buffer to allocate; one of the
- *                                  BLE_HCI_TRANS_BUF_[...] constants.
- *
- * @return                      The allocated buffer on success;
- *                              NULL on buffer exhaustion.
- */
-uint8_t *
-ble_hci_trans_buf_alloc(int type)
-{
-    uint8_t *buf;
-
-    switch (type) {
-    case BLE_HCI_TRANS_BUF_CMD:
-        buf = os_memblock_get(&ble_hci_uart_cmd_pool);
-        break;
-    case BLE_HCI_TRANS_BUF_EVT_HI:
-        buf = os_memblock_get(&ble_hci_uart_evt_hi_pool);
-        if (buf == NULL) {
-            /* If no high-priority event buffers remain, try to grab a
-             * low-priority one.
-             */
-            buf = os_memblock_get(&ble_hci_uart_evt_lo_pool);
-        }
-        break;
-
-    case BLE_HCI_TRANS_BUF_EVT_LO:
-        buf = os_memblock_get(&ble_hci_uart_evt_lo_pool);
-        break;
-
-    default:
-        assert(0);
-        buf = NULL;
-    }
-
-    return buf;
-}
-
-/**
- * Frees the specified flat buffer.  The buffer must have been allocated via
- * ble_hci_trans_buf_alloc().
- *
- * @param buf                   The buffer to free.
- */
-void
-ble_hci_trans_buf_free(uint8_t *buf)
-{
-    int rc;
-
-    /*
-     * XXX: this may look a bit odd, but the controller uses the command
-     * buffer to send back the command complete/status as an immediate
-     * response to the command. This was done to insure that the controller
-     * could always send back one of these events when a command was received.
-     * Thus, we check to see which pool the buffer came from so we can free
-     * it to the appropriate pool
-     */
-    if (os_memblock_from(&ble_hci_uart_evt_hi_pool, buf)) {
-        rc = os_memblock_put(&ble_hci_uart_evt_hi_pool, buf);
-        assert(rc == 0);
-    } else if (os_memblock_from(&ble_hci_uart_evt_lo_pool, buf)) {
-        rc = os_memblock_put(&ble_hci_uart_evt_lo_pool, buf);
-        assert(rc == 0);
-    } else {
-        assert(os_memblock_from(&ble_hci_uart_cmd_pool, buf));
-        rc = os_memblock_put(&ble_hci_uart_cmd_pool, buf);
-        assert(rc == 0);
-    }
-}
-
-/**
- * Configures a callback to get executed whenever an ACL data packet is freed.
- * The function is called in lieu of actually freeing the packet.
- *
- * @param cb                    The callback to configure.
- *
- * @return                      0 on success.
- */
-int
-ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg)
-{
-    ble_hci_uart_acl_pool.mpe_put_cb = cb;
-    ble_hci_uart_acl_pool.mpe_put_arg = arg;
-    return 0;
-}
-
-/**
- * Resets the HCI UART transport to a clean state.  Frees all buffers and
- * reconfigures the UART.
- *
- * @return                      0 on success;
- *                              A BLE_ERR_[...] error code on failure.
- */
-int
-ble_hci_trans_reset(void)
-{
-    struct ble_hci_uart_pkt *pkt;
-    int rc;
-
-    /* Close the UART to prevent race conditions as the buffers are freed. */
-    rc = hal_uart_close(MYNEWT_VAL(BLE_HCI_UART_PORT));
-    if (rc != 0) {
-        return BLE_ERR_HW_FAIL;
-    }
-
-    ble_hci_uart_free_pkt(ble_hci_uart_state.rx_type,
-                          ble_hci_uart_state.rx_cmd.data,
-                          ble_hci_uart_state.rx_acl.buf);
-    ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
-
-    ble_hci_uart_free_pkt(ble_hci_uart_state.tx_type,
-                          ble_hci_uart_state.tx_cmd.data,
-                          ble_hci_uart_state.tx_pkt.tx_acl);
-    ble_hci_uart_state.tx_type = BLE_HCI_UART_H4_NONE;
-
-    while ((pkt = STAILQ_FIRST(&ble_hci_uart_state.tx_pkts)) != NULL) {
-        STAILQ_REMOVE(&ble_hci_uart_state.tx_pkts, pkt, ble_hci_uart_pkt,
-                      next);
-        ble_hci_uart_free_pkt(pkt->type, pkt->data, pkt->data);
-        os_memblock_put(&ble_hci_uart_pkt_pool, pkt);
-    }
-
-    /* Reopen the UART. */
-    rc = ble_hci_uart_config();
-    if (rc != 0) {
-        return rc;
-    }
-
-    return 0;
-}
-
-/**
- * Initializes the UART HCI transport module.
- *
- * @return                      0 on success;
- *                              A BLE_ERR_[...] error code on failure.
- */
-void
-ble_hci_uart_init(void)
-{
-    int rc;
-
-    /* Ensure this function only gets called by sysinit. */
-    SYSINIT_ASSERT_ACTIVE();
-
-    rc = os_mempool_ext_init(&ble_hci_uart_acl_pool,
-                             MYNEWT_VAL(BLE_ACL_BUF_COUNT),
-                             ACL_BLOCK_SIZE,
-                             ble_hci_uart_acl_buf,
-                             "ble_hci_uart_acl_pool");
-    SYSINIT_PANIC_ASSERT(rc == 0);
-
-    rc = os_mbuf_pool_init(&ble_hci_uart_acl_mbuf_pool,
-                           &ble_hci_uart_acl_pool.mpe_mp,
-                           ACL_BLOCK_SIZE,
-                           MYNEWT_VAL(BLE_ACL_BUF_COUNT));
-    SYSINIT_PANIC_ASSERT(rc == 0);
-
-    /*
-     * Create memory pool of HCI command buffers. NOTE: we currently dont
-     * allow this to be configured. The controller will only allow one
-     * outstanding command. We decided to keep this a pool in case we allow
-     * allow the controller to handle more than one outstanding command.
-     */
-    rc = os_mempool_init(&ble_hci_uart_cmd_pool,
-                         1,
-                         BLE_HCI_TRANS_CMD_SZ,
-                         ble_hci_uart_cmd_buf,
-                         "ble_hci_uart_cmd_pool");
-    SYSINIT_PANIC_ASSERT(rc == 0);
-
-    rc = os_mempool_init(&ble_hci_uart_evt_hi_pool,
-                         MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
-                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
-                         ble_hci_uart_evt_hi_buf,
-                         "ble_hci_uart_evt_hi_pool");
-    SYSINIT_PANIC_ASSERT(rc == 0);
-
-    rc = os_mempool_init(&ble_hci_uart_evt_lo_pool,
-                         MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
-                         MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
-                         ble_hci_uart_evt_lo_buf,
-                         "ble_hci_uart_evt_lo_pool");
-    SYSINIT_PANIC_ASSERT(rc == 0);
-
-    /*
-     * Create memory pool of packet list nodes. NOTE: the number of these
-     * buffers should be, at least, the total number of event buffers (hi
-     * and lo), the number of command buffers (currently 1) and the total
-     * number of buffers that the controller could possibly hand to the host.
-     */
-    rc = os_mempool_init(&ble_hci_uart_pkt_pool,
-                         BLE_HCI_UART_EVT_COUNT + 1 +
-                         MYNEWT_VAL(BLE_HCI_ACL_OUT_COUNT),
-                         sizeof (struct ble_hci_uart_pkt),
-                         ble_hci_uart_pkt_buf,
-                         "ble_hci_uart_pkt_pool");
-    SYSINIT_PANIC_ASSERT(rc == 0);
-
-    rc = ble_hci_uart_config();
-    SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failure configuring UART HCI");
-
-    memset(&ble_hci_uart_state, 0, sizeof ble_hci_uart_state);
-    STAILQ_INIT(&ble_hci_uart_state.tx_pkts);
-}
diff --git a/nimble/transport/uart/src/hci_uart.c b/nimble/transport/uart/src/hci_uart.c
new file mode 100644
index 0000000..9ffcc90
--- /dev/null
+++ b/nimble/transport/uart/src/hci_uart.c
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <sysinit/sysinit.h>
+#include <syscfg/syscfg.h>
+#include "os/os_mbuf.h"
+#include "os/os_mempool.h"
+#include "hal/hal_uart.h"
+#include "nimble/transport.h"
+#include "nimble/transport/hci_h4.h"
+
+#define TX_Q_SIZE   (MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT) + \
+                     MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT) + \
+                     MYNEWT_VAL(BLE_TRANSPORT_EVT_DISCARDABLE_COUNT))
+
+struct hci_uart_tx {
+    uint8_t type;
+    uint8_t sent_type;
+    uint16_t len;
+    uint16_t idx;
+
+    struct os_mbuf *om;
+    uint8_t *buf;
+
+    STAILQ_ENTRY(hci_uart_tx) tx_q_next;
+};
+
+static STAILQ_HEAD(, hci_uart_tx) tx_q;
+
+static struct os_mempool pool_tx_q;
+static uint8_t pool_tx_q_buf[ OS_MEMPOOL_BYTES(TX_Q_SIZE,
+                                               sizeof(struct hci_uart_tx)) ];
+
+struct hci_h4_sm hci_uart_h4sm;
+
+static int
+hci_uart_frame_cb(uint8_t pkt_type, void *data)
+{
+    switch (pkt_type) {
+    case HCI_H4_CMD:
+        return ble_transport_to_ll_cmd(data);
+    case HCI_H4_ACL:
+        return ble_transport_to_ll_acl(data);
+    default:
+        assert(0);
+        break;
+    }
+
+    return -1;
+}
+
+static int
+hci_uart_rx_char(void *arg, uint8_t data)
+{
+    hci_h4_sm_rx(&hci_uart_h4sm, &data, 1);
+
+    return 0;
+}
+
+static int
+hci_uart_tx_char(void *arg)
+{
+    struct hci_uart_tx *tx;
+    uint8_t ch;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    tx = STAILQ_FIRST(&tx_q);
+    OS_EXIT_CRITICAL(sr);
+    if (!tx) {
+        return -1;
+    }
+
+    if (!tx->sent_type) {
+        tx->sent_type = 1;
+        return tx->type;
+    }
+
+    switch (tx->type) {
+    case HCI_H4_EVT:
+        ch = tx->buf[tx->idx];
+        tx->idx++;
+        if (tx->idx == tx->len) {
+            ble_transport_free(tx->buf);
+            OS_ENTER_CRITICAL(sr);
+            STAILQ_REMOVE_HEAD(&tx_q, tx_q_next);
+            OS_EXIT_CRITICAL(sr);
+            os_memblock_put(&pool_tx_q, tx);
+        }
+        break;
+    case HCI_H4_ACL:
+        os_mbuf_copydata(tx->om, 0, 1, &ch);
+        os_mbuf_adj(tx->om, 1);
+        tx->len--;
+        if (tx->len == 0) {
+            os_mbuf_free_chain(tx->om);
+            OS_ENTER_CRITICAL(sr);
+            STAILQ_REMOVE_HEAD(&tx_q, tx_q_next);
+            OS_EXIT_CRITICAL(sr);
+            os_memblock_put(&pool_tx_q, tx);
+        }
+        break;
+    default:
+        assert(0);
+        OS_ENTER_CRITICAL(sr);
+        STAILQ_REMOVE_HEAD(&tx_q, tx_q_next);
+        OS_EXIT_CRITICAL(sr);
+        os_memblock_put(&pool_tx_q, tx);
+    }
+
+    return ch;
+}
+
+static int
+hci_uart_configure(void)
+{
+    enum hal_uart_parity parity;
+    enum hal_uart_flow_ctl flowctl;
+    int rc;
+
+    rc = hal_uart_init_cbs(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT),
+                           hci_uart_tx_char, NULL,
+                           hci_uart_rx_char, NULL);
+    if (rc != 0) {
+        return -1;
+    }
+
+    if (MYNEWT_VAL_CHOICE(BLE_TRANSPORT_UART_PARITY, odd)) {
+        parity = HAL_UART_PARITY_ODD;
+    } else if (MYNEWT_VAL_CHOICE(BLE_TRANSPORT_UART_PARITY, even)) {
+        parity = HAL_UART_PARITY_EVEN;
+    } else {
+        parity = HAL_UART_PARITY_NONE;
+    }
+
+    if (MYNEWT_VAL_CHOICE(BLE_TRANSPORT_UART_FLOW_CONTROL, rtscts)) {
+        flowctl = HAL_UART_FLOW_CTL_RTS_CTS;
+    } else {
+        flowctl = HAL_UART_FLOW_CTL_NONE;
+    }
+
+    rc = hal_uart_config(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT),
+                         MYNEWT_VAL(BLE_TRANSPORT_UART_BAUDRATE),
+                         MYNEWT_VAL(BLE_TRANSPORT_UART_DATA_BITS),
+                         MYNEWT_VAL(BLE_TRANSPORT_UART_STOP_BITS),
+                         parity, flowctl);
+    if (rc != 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+ble_transport_to_hs_evt(void *buf)
+{
+    struct hci_uart_tx *txe;
+    os_sr_t sr;
+
+    txe = os_memblock_get(&pool_tx_q);
+    if (!txe) {
+        assert(0);
+        return -ENOMEM;
+    }
+
+    txe->type = HCI_H4_EVT;
+    txe->sent_type = 0;
+    txe->len = 2 + ((uint8_t *)buf)[1];
+    txe->buf = buf;
+    txe->idx = 0;
+    txe->om = NULL;
+
+    OS_ENTER_CRITICAL(sr);
+    STAILQ_INSERT_TAIL(&tx_q, txe, tx_q_next);
+    OS_EXIT_CRITICAL(sr);
+
+    hal_uart_start_tx(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT));
+
+    return 0;
+}
+
+int
+ble_transport_to_hs_acl(struct os_mbuf *om)
+{
+    struct hci_uart_tx *txe;
+    os_sr_t sr;
+
+    txe = os_memblock_get(&pool_tx_q);
+    if (!txe) {
+        assert(0);
+        return -ENOMEM;
+    }
+
+    txe->type = HCI_H4_ACL;
+    txe->sent_type = 0;
+    txe->len = 2 + OS_MBUF_PKTLEN(om);
+    txe->idx = 0;
+    txe->buf = NULL;
+    txe->om = om;
+
+    OS_ENTER_CRITICAL(sr);
+    STAILQ_INSERT_TAIL(&tx_q, txe, tx_q_next);
+    OS_EXIT_CRITICAL(sr);
+
+    hal_uart_start_tx(MYNEWT_VAL(BLE_TRANSPORT_UART_PORT));
+
+    return 0;
+}
+
+void
+ble_transport_hs_init(void)
+{
+    int rc;
+
+    SYSINIT_ASSERT_ACTIVE();
+
+    rc = hci_uart_configure();
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mempool_init(&pool_tx_q, TX_Q_SIZE, sizeof(struct hci_uart_tx),
+                         pool_tx_q_buf, "hci_uart_tx_q");
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    hci_h4_sm_init(&hci_uart_h4sm, &hci_h4_allocs_from_hs, hci_uart_frame_cb);
+
+    STAILQ_INIT(&tx_q);
+}
diff --git a/nimble/transport/uart/syscfg.yml b/nimble/transport/uart/syscfg.yml
index 7eff951..21d2177 100644
--- a/nimble/transport/uart/syscfg.yml
+++ b/nimble/transport/uart/syscfg.yml
@@ -17,45 +17,23 @@
 #
 
 syscfg.defs:
-    BLE_HCI_ACL_OUT_COUNT:
-        description: >
-            This count is used in creating a pool of elements used by the
-            code to enqueue various elements. In the case of the controller
-            only HCI, this number should be equal to the number of mbufs in
-            the msys pool. For host only, it is really dependent on the
-            number of ACL buffers that the controller tells the host it
-            has.
-        value: 12
-
-    BLE_HCI_UART_PORT:
-        description: 'The uart to use for the HCI uart interface'
-        value:            0
-    BLE_HCI_UART_BAUD:
-        description: 'The baud rate of the HCI uart interface'
-        value:            1000000
-    BLE_HCI_UART_DATA_BITS:
-        description: 'Number of data bits used for HCI uart interface'
-        value:       8
-    BLE_HCI_UART_STOP_BITS:
-        description: 'Number of stop bits used for HCI uart interface'
-        value:       1
-    BLE_HCI_UART_PARITY:
-        description: 'Parity used for HCI uart interface'
-        value:          HAL_UART_PARITY_NONE
-    BLE_HCI_UART_FLOW_CTRL:
-        description: 'Flow control used for HCI uart interface'
-        value:       HAL_UART_FLOW_CTL_RTS_CTS
-    BLE_TRANS_UART_SYSINIT_STAGE:
-        description: >
-            Sysinit stage for the UART BLE transport.
-        value: 500
-
-syscfg.vals.BLE_EXT_ADV:
-    BLE_HCI_EVT_BUF_SIZE: 257
-
-syscfg.vals:
-    BLE_HCI_EVT_BUF_SIZE: 70
-    BLE_HCI_EVT_HI_BUF_COUNT: 8
-    BLE_HCI_EVT_LO_BUF_COUNT: 8
-    BLE_ACL_BUF_COUNT: 12
-    BLE_ACL_BUF_SIZE: 255
+    BLE_TRANSPORT_UART_PORT:
+        description: UART index to use for HCI interface
+        value: 0
+    BLE_TRANSPORT_UART_BAUDRATE:
+        description: Baudrate on UART
+        value: 1000000
+    BLE_TRANSPORT_UART_DATA_BITS:
+        description: Number of data bits on UART
+        value: 8
+    BLE_TRANSPORT_UART_STOP_BITS:
+        description: Number of stop bits on UART
+        value: 1
+    BLE_TRANSPORT_UART_PARITY:
+        description: Parity on UART
+        value: none
+        choices: none,even,odd
+    BLE_TRANSPORT_UART_FLOW_CONTROL:
+        description: Flow control on UART
+        choices: off,rtscts
+        value: rtscts