You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2017/04/20 15:30:10 UTC

[1/3] incubator-mynewt-core git commit: net/nimble; add HCI transport which has Linux bluetooth socket, or TCP socket as it's target.

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/master 431e500ad -> a34f65387


net/nimble; add HCI transport which has Linux bluetooth socket,
or TCP socket as it's target.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/9fcbd0d0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/9fcbd0d0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/9fcbd0d0

Branch: refs/heads/master
Commit: 9fcbd0d0d5d45b4495a93f71fe17b23d7761e44f
Parents: 832fa2d
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Tue Apr 4 09:40:55 2017 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Tue Apr 4 09:40:55 2017 -0700

----------------------------------------------------------------------
 .../socket/include/socket/ble_hci_socket.h      |  34 +
 net/nimble/transport/socket/pkg.yml             |  38 +
 .../transport/socket/src/ble_hci_socket.c       | 797 +++++++++++++++++++
 net/nimble/transport/socket/syscfg.yml          |  66 ++
 4 files changed, 935 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fcbd0d0/net/nimble/transport/socket/include/socket/ble_hci_socket.h
----------------------------------------------------------------------
diff --git a/net/nimble/transport/socket/include/socket/ble_hci_socket.h b/net/nimble/transport/socket/include/socket/ble_hci_socket.h
new file mode 100644
index 0000000..d17074f
--- /dev/null
+++ b/net/nimble/transport/socket/include/socket/ble_hci_socket.h
@@ -0,0 +1,34 @@
+/*
+ * 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 _BLE_HCI_SOCKET_H_
+#define _BLE_HCI_SOCKET_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_eventq;
+void ble_hci_sock_set_evq(struct os_eventq *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fcbd0d0/net/nimble/transport/socket/pkg.yml
----------------------------------------------------------------------
diff --git a/net/nimble/transport/socket/pkg.yml b/net/nimble/transport/socket/pkg.yml
new file mode 100644
index 0000000..fe5d1bd
--- /dev/null
+++ b/net/nimble/transport/socket/pkg.yml
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+
+pkg.name: net/nimble/transport/socket
+pkg.description: Provides HCI transport over socket interface
+pkg.author: "Apache Mynewt <de...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - ble
+    - bluetooth
+
+pkg.deps:
+    - hw/hal
+    - kernel/os
+    - net/nimble
+    - util/mem
+
+pkg.apis:
+    - ble_transport
+
+pkg.init:
+    ble_hci_sock_init: 500

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fcbd0d0/net/nimble/transport/socket/src/ble_hci_socket.c
----------------------------------------------------------------------
diff --git a/net/nimble/transport/socket/src/ble_hci_socket.c b/net/nimble/transport/socket/src/ble_hci_socket.c
new file mode 100755
index 0000000..ff4b152
--- /dev/null
+++ b/net/nimble/transport/socket/src/ble_hci_socket.c
@@ -0,0 +1,797 @@
+/*
+ * 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.
+ */
+
+/*
+ * Provides HCI transport over sockets. Either over
+ * TCP sockets, or Linux bluetooth socket.
+ *
+ * E.g. to connect to TCP target, start in another window
+ * socat -x PIPE:/dev/ttyACM1 TCP4-LISTEN:14433,fork,reuseaddr
+ * When building this package, set BLE_SOCK_USE_TCP=1 and
+ * BLE_SOCK_TCP_PORT controls the target port this transport
+ * connects to.
+ *
+ * To use Linux Bluetooth sockets, create an interface:
+ * sudo hciattach -r -n /dev/ttyUSB0 any 57600
+ * And build this package with BLE_SOCK_USE_LINUX_BLUE=1,
+ * BLE_SOCK_LINUX_DEV=<interface index of the target interface>
+ *
+ */
+#include "syscfg/syscfg.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#if MYNEWT_VAL(BLE_SOCK_USE_TCP)
+#include <sys/errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#if MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
+#include <sys/errno.h>
+#define BTPROTO_HCI 1
+#define HCI_CHANNEL_RAW		0
+#define HCI_CHANNEL_USER	1
+#define HCIDEVUP	_IOW('H', 201, int)
+#define HCIGETDEVLIST	_IOR('H', 210, int)
+
+struct sockaddr_hci {
+        sa_family_t    hci_family;
+        unsigned short hci_dev;
+        unsigned short hci_channel;
+};
+#endif
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include "sysinit/sysinit.h"
+#include "os/os.h"
+#include "mem/mem.h"
+
+#include "stats/stats.h"
+
+/* BLE */
+#include "nimble/ble.h"
+#include "nimble/nimble_opt.h"
+#include "nimble/hci_common.h"
+#include "nimble/ble_hci_trans.h"
+#include "socket/ble_hci_socket.h"
+
+/***
+ * 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.
+ */
+
+STATS_SECT_START(hci_sock_stats)
+    STATS_SECT_ENTRY(imsg)
+    STATS_SECT_ENTRY(icmd)
+    STATS_SECT_ENTRY(ievt)
+    STATS_SECT_ENTRY(iacl)
+    STATS_SECT_ENTRY(ibytes)
+    STATS_SECT_ENTRY(ierr)
+    STATS_SECT_ENTRY(imem)
+    STATS_SECT_ENTRY(omsg)
+    STATS_SECT_ENTRY(oacl)
+    STATS_SECT_ENTRY(ocmd)
+    STATS_SECT_ENTRY(oevt)
+    STATS_SECT_ENTRY(obytes)
+    STATS_SECT_ENTRY(oerr)
+STATS_SECT_END
+
+STATS_SECT_DECL(hci_sock_stats) hci_sock_stats;
+STATS_NAME_START(hci_sock_stats)
+    STATS_NAME(hci_sock_stats, imsg)
+    STATS_NAME(hci_sock_stats, icmd)
+    STATS_NAME(hci_sock_stats, ievt)
+    STATS_NAME(hci_sock_stats, iacl)
+    STATS_NAME(hci_sock_stats, ibytes)
+    STATS_NAME(hci_sock_stats, ierr)
+    STATS_NAME(hci_sock_stats, imem)
+    STATS_NAME(hci_sock_stats, omsg)
+    STATS_NAME(hci_sock_stats, oacl)
+    STATS_NAME(hci_sock_stats, ocmd)
+    STATS_NAME(hci_sock_stats, oevt)
+    STATS_NAME(hci_sock_stats, obytes)
+    STATS_NAME(hci_sock_stats, oerr)
+STATS_NAME_END(hci_sock_stats)
+
+/***
+ * 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
+
+static struct os_mempool ble_hci_sock_evt_hi_pool;
+static void *ble_hci_sock_evt_hi_buf;
+static struct os_mempool ble_hci_sock_evt_lo_pool;
+static void *ble_hci_sock_evt_lo_buf;
+
+static struct os_mempool ble_hci_sock_cmd_pool;
+static void *ble_hci_sock_cmd_buf;
+
+static struct os_mbuf_pool ble_hci_sock_acl_mbuf_pool;
+static struct os_mempool ble_hci_sock_acl_pool;
+static void *ble_hci_sock_acl_buf;
+
+static ble_hci_trans_rx_cmd_fn *ble_hci_sock_rx_cmd_cb;
+static void *ble_hci_sock_rx_cmd_arg;
+static ble_hci_trans_rx_acl_fn *ble_hci_sock_rx_acl_cb;
+static void *ble_hci_sock_rx_acl_arg;
+
+static struct ble_hci_sock_state {
+    int sock;
+    struct os_eventq *evq;
+    struct os_event ev;
+    struct os_callout timer;
+
+    uint8_t rx_off;
+    uint8_t rx_data[512];
+} ble_hci_sock_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;
+
+    /*
+     * XXX: note that for host only there would be no need to allocate
+     * a user header. Address this later.
+     */
+    m = os_mbuf_get_pkthdr(&ble_hci_sock_acl_mbuf_pool,
+                           sizeof(struct ble_mbuf_hdr));
+    return m;
+}
+
+static int
+ble_hci_sock_acl_tx(struct os_mbuf *om)
+{
+    struct msghdr msg;
+    struct iovec iov[8];
+    int i;
+    struct os_mbuf *m;
+    uint8_t ch;
+
+    memset(&msg, 0, sizeof(msg));
+    memset(iov, 0, sizeof(iov));
+
+    msg.msg_iov = iov;
+
+    ch = BLE_HCI_UART_H4_ACL;
+    iov[0].iov_len = 1;
+    iov[0].iov_base = &ch;
+    i = 1;
+    for (m = om; m; m = SLIST_NEXT(m, om_next)) {
+        iov[i].iov_base = m->om_data;
+        iov[i].iov_len = m->om_len;
+        i++;
+    }
+    msg.msg_iovlen = i;
+
+    STATS_INC(hci_sock_stats, omsg);
+    STATS_INC(hci_sock_stats, oacl);
+    STATS_INCN(hci_sock_stats, obytes, OS_MBUF_PKTLEN(om) + 1);
+    i = sendmsg(ble_hci_sock_state.sock, &msg, 0);
+    os_mbuf_free_chain(om);
+    if (i != OS_MBUF_PKTLEN(om) + 1) {
+        if (i < 0) {
+            dprintf(1, "sendmsg() failed : %d\n", errno);
+        } else {
+            dprintf(1, "sendmsg() partial write: %d\n", i);
+        }
+        STATS_INC(hci_sock_stats, oerr);
+        return BLE_ERR_MEM_CAPACITY;
+    }
+    return 0;
+}
+
+static int
+ble_hci_sock_cmdevt_tx(uint8_t *hci_ev, uint8_t h4_type)
+{
+    struct msghdr msg;
+    struct iovec iov[8];
+    int len;
+    int i;
+    uint8_t ch;
+
+    memset(&msg, 0, sizeof(msg));
+    memset(iov, 0, sizeof(iov));
+
+    msg.msg_iov = iov;
+    msg.msg_iovlen = 2;
+
+    ch = h4_type;
+    iov[0].iov_len = 1;
+    iov[0].iov_base = &ch;
+    iov[1].iov_base = hci_ev;
+    if (h4_type == BLE_HCI_UART_H4_CMD) {
+        len = BLE_HCI_CMD_HDR_LEN + hci_ev[2];
+        STATS_INC(hci_sock_stats, ocmd);
+    } else if (h4_type == BLE_HCI_UART_H4_EVT) {
+        len = BLE_HCI_EVENT_HDR_LEN + hci_ev[1];
+        STATS_INC(hci_sock_stats, oevt);
+    } else {
+        assert(0);
+    }
+    iov[1].iov_len = len;
+
+    STATS_INC(hci_sock_stats, omsg);
+    STATS_INCN(hci_sock_stats, obytes, len + 1);
+
+    i = sendmsg(ble_hci_sock_state.sock, &msg, 0);
+    ble_hci_trans_buf_free(hci_ev);
+    if (i != len + 1) {
+        if (i < 0) {
+            dprintf(1, "sendmsg() failed : %d\n", errno);
+        } else {
+            dprintf(1, "sendmsg() partial write: %d\n", i);
+        }
+        STATS_INC(hci_sock_stats, oerr);
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
+    return 0;
+}
+
+static int
+ble_hci_sock_rx_msg(void)
+{
+    struct ble_hci_sock_state *bhss;
+    int len;
+    struct os_mbuf *m;
+    uint8_t *data;
+    int sr;
+    int rc;
+
+    bhss = &ble_hci_sock_state;
+    if (bhss->sock < 0) {
+        return -1;
+    }
+    len = read(bhss->sock, bhss->rx_data + bhss->rx_off,
+               sizeof(bhss->rx_data) - bhss->rx_off);
+    if (len < 0) {
+        return -2;
+    }
+    if (len == 0) {
+        return -1;
+    }
+    bhss->rx_off += len;
+    STATS_INCN(hci_sock_stats, ibytes, len);
+
+    while (bhss->rx_off > 0) {
+        switch (bhss->rx_data[0]) {
+#if MYNEWT_VAL(BLE_DEVICE)
+        case BLE_HCI_UART_H4_CMD:
+            if (bhss->rx_off < BLE_HCI_CMD_HDR_LEN) {
+                return -1;
+            }
+            len = 1 + BLE_HCI_CMD_HDR_LEN + bhss->rx_data[3];
+            if (bhss->rx_off < len) {
+                return -1;
+            }
+            STATS_INC(hci_sock_stats, imsg);
+            STATS_INC(hci_sock_stats, icmd);
+            data = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+            if (!data) {
+                STATS_INC(hci_sock_stats, ierr);
+                break;
+            }
+            memcpy(data, &bhss->rx_data[1], len - 1);
+            OS_ENTER_CRITICAL(sr);
+            rc = ble_hci_sock_rx_cmd_cb(data, ble_hci_sock_rx_cmd_arg);
+            OS_EXIT_CRITICAL(sr);
+            if (rc) {
+                ble_hci_trans_buf_free(data);
+                STATS_INC(hci_sock_stats, ierr);
+                break;
+            }
+            break;
+#endif
+#if MYNEWT_VAL(BLE_HOST)
+        case BLE_HCI_UART_H4_EVT:
+            if (bhss->rx_off < BLE_HCI_EVENT_HDR_LEN) {
+                return -1;
+            }
+            len = 1 + BLE_HCI_EVENT_HDR_LEN + bhss->rx_data[2];
+            if (bhss->rx_off < len) {
+                return -1;
+            }
+            STATS_INC(hci_sock_stats, imsg);
+            STATS_INC(hci_sock_stats, ievt);
+            data = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+            if (!data) {
+                STATS_INC(hci_sock_stats, ierr);
+                break;
+            }
+            memcpy(data, &bhss->rx_data[1], len - 1);
+            OS_ENTER_CRITICAL(sr);
+            rc = ble_hci_sock_rx_cmd_cb(data, ble_hci_sock_rx_cmd_arg);
+            OS_EXIT_CRITICAL(sr);
+            if (rc) {
+                ble_hci_trans_buf_free(data);
+                STATS_INC(hci_sock_stats, ierr);
+                return 0;
+            }
+            break;
+#endif
+        case BLE_HCI_UART_H4_ACL:
+            if (bhss->rx_off < BLE_HCI_DATA_HDR_SZ) {
+                return -1;
+            }
+            len = 1 + BLE_HCI_DATA_HDR_SZ + (bhss->rx_data[4] << 8) +
+              bhss->rx_data[3];
+            if (bhss->rx_off < len) {
+                return -1;
+            }
+            STATS_INC(hci_sock_stats, imsg);
+            STATS_INC(hci_sock_stats, iacl);
+            m = ble_hci_trans_acl_buf_alloc();
+            if (!m) {
+                STATS_INC(hci_sock_stats, imem);
+                break;
+            }
+            if (os_mbuf_append(m, &bhss->rx_data[1], len - 1)) {
+                STATS_INC(hci_sock_stats, imem);
+                os_mbuf_free_chain(m);
+                break;
+            }
+            OS_ENTER_CRITICAL(sr);
+            ble_hci_sock_rx_acl_cb(m, ble_hci_sock_rx_acl_arg);
+            OS_EXIT_CRITICAL(sr);
+            break;
+        default:
+            STATS_INC(hci_sock_stats, ierr);
+            break;
+        }
+        memmove(bhss->rx_data, &bhss->rx_data[len], bhss->rx_off - len);
+        bhss->rx_off -= len;
+    }
+    return 0;
+}
+
+static void
+ble_hci_sock_rx_ev(struct os_event *ev)
+{
+    int rc;
+
+    rc = ble_hci_sock_rx_msg();
+    if (rc == 0) {
+        os_eventq_put(ble_hci_sock_state.evq, &ble_hci_sock_state.ev);
+    } else {
+        os_callout_reset(&ble_hci_sock_state.timer, OS_TICKS_PER_SEC / 100);
+    }
+}
+
+#if MYNEWT_VAL(BLE_SOCK_USE_TCP)
+static int
+ble_hci_sock_config(void)
+{
+    struct ble_hci_sock_state *bhss = &ble_hci_sock_state;
+    struct sockaddr_in sin;
+    int s;
+    int rc;
+
+    memset(&sin, 0, sizeof(sin));
+    sin.sin_family = AF_INET;
+    sin.sin_port = htons(MYNEWT_VAL(BLE_SOCK_TCP_PORT));
+    sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+#ifdef MN_OSX
+    sin.sin_len = sizeof(sin);
+#endif
+
+#if 0
+    if (bhss->sock >= 0) {
+        close(bhss->sock);
+        bhss->sock = -1;
+    }
+#endif
+    if (bhss->sock < 0) {
+        s = socket(PF_INET, SOCK_STREAM, 0);
+        if (s < 0) {
+            goto err;
+        }
+
+        rc = connect(s, (struct sockaddr *)&sin, sizeof(sin));
+        if (rc) {
+            dprintf(1, "connect() failed: %d\n", errno);
+            goto err;
+        }
+
+        rc = 1;
+
+        rc = ioctl(s, FIONBIO, (char *)&rc);
+        if (rc) {
+            goto err;
+        }
+        bhss->sock = s;
+    }
+    os_callout_reset(&ble_hci_sock_state.timer, OS_TICKS_PER_SEC / 100);
+
+    return 0;
+err:
+    if (s >= 0) {
+        close(s);
+    }
+    return BLE_ERR_HW_FAIL;
+}
+#endif
+
+#if MYNEWT_VAL(BLE_SOCK_USE_LINUX_BLUE)
+static int
+ble_hci_sock_config(void)
+{
+    struct sockaddr_hci shci;
+    int s;
+    int rc;
+
+    memset(&shci, 0, sizeof(shci));
+    shci.hci_family = AF_BLUETOOTH;
+    shci.hci_dev = MYNEWT_VAL(BLE_SOCK_LINUX_DEV);
+    shci.hci_channel = HCI_CHANNEL_USER;
+
+    if (ble_hci_sock_state.sock >= 0) {
+        close(ble_hci_sock_state.sock);
+        ble_hci_sock_state.sock = -1;
+    }
+
+    s = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+    if (s < 0) {
+        dprintf(1, "socket() failed %d\n", errno);
+        goto err;
+    }
+
+    rc = bind(s, (struct sockaddr *)&shci, sizeof(shci));
+    if (rc) {
+        dprintf(1, "bind() failed %d\n", errno);
+        goto err;
+    }
+
+    rc = 1;
+
+    rc = ioctl(s, FIONBIO, (char *)&rc);
+    if (rc) {
+        goto err;
+    }
+    ble_hci_sock_state.sock = s;
+
+    os_callout_reset(&ble_hci_sock_state.timer, OS_TICKS_PER_SEC / 100);
+
+    return 0;
+err:
+    if (s >= 0) {
+        close(s);
+    }
+    return BLE_ERR_HW_FAIL;
+}
+#endif
+/**
+ * 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)
+{
+    return ble_hci_sock_cmdevt_tx(cmd, BLE_HCI_UART_H4_EVT);
+}
+
+/**
+ * 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)
+{
+    return ble_hci_sock_acl_tx(om);
+}
+
+/**
+ * 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)
+{
+    return ble_hci_sock_cmdevt_tx(cmd, BLE_HCI_UART_H4_CMD);
+}
+
+/**
+ * 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)
+{
+    return ble_hci_sock_acl_tx(om);
+}
+
+/**
+ * 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_sock_rx_cmd_cb = cmd_cb;
+    ble_hci_sock_rx_cmd_arg = cmd_arg;
+    ble_hci_sock_rx_acl_cb = acl_cb;
+    ble_hci_sock_rx_acl_arg = acl_arg;
+}
+
+/**
+ * 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_sock_rx_cmd_cb = cmd_cb;
+    ble_hci_sock_rx_cmd_arg = cmd_arg;
+    ble_hci_sock_rx_acl_cb = acl_cb;
+    ble_hci_sock_rx_acl_arg = 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_sock_cmd_pool);
+        break;
+    case BLE_HCI_TRANS_BUF_EVT_HI:
+        buf = os_memblock_get(&ble_hci_sock_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_sock_evt_lo_pool);
+        }
+        break;
+
+    case BLE_HCI_TRANS_BUF_EVT_LO:
+        buf = os_memblock_get(&ble_hci_sock_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_sock_evt_hi_pool, buf)) {
+        rc = os_memblock_put(&ble_hci_sock_evt_hi_pool, buf);
+        assert(rc == 0);
+    } else if (os_memblock_from(&ble_hci_sock_evt_lo_pool, buf)) {
+        rc = os_memblock_put(&ble_hci_sock_evt_lo_pool, buf);
+        assert(rc == 0);
+    } else {
+        assert(os_memblock_from(&ble_hci_sock_cmd_pool, buf));
+        rc = os_memblock_put(&ble_hci_sock_cmd_pool, buf);
+        assert(rc == 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)
+{
+    int rc;
+
+    os_callout_stop(&ble_hci_sock_state.timer);
+
+    /* Reopen the UART. */
+    rc = ble_hci_sock_config();
+    if (rc != 0) {
+        dprintf(1, "Failure restarting socket HCI\n");
+        return rc;
+    }
+
+    return 0;
+}
+
+void
+ble_hci_sock_set_evq(struct os_eventq *evq)
+{
+    ble_hci_sock_state.evq = evq;
+    os_callout_stop(&ble_hci_sock_state.timer);
+    os_callout_init(&ble_hci_sock_state.timer, ble_hci_sock_state.evq,
+                    ble_hci_sock_rx_ev, NULL);
+}
+
+/**
+ * Initializes the UART HCI transport module.
+ *
+ * @return                      0 on success;
+ *                              A BLE_ERR_[...] error code on failure.
+ */
+void
+ble_hci_sock_init(void)
+{
+    int acl_data_length;
+    int acl_block_size;
+    int rc;
+
+    /* Ensure this function only gets called by sysinit. */
+    SYSINIT_ASSERT_ACTIVE();
+
+    memset(&ble_hci_sock_state, 0, sizeof(ble_hci_sock_state));
+    ble_hci_sock_state.sock = -1;
+
+    ble_hci_sock_set_evq(os_eventq_dflt_get());
+    ble_hci_sock_state.ev.ev_cb = ble_hci_sock_rx_ev;
+
+    /*
+     * 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.
+     */
+    acl_data_length = MYNEWT_VAL(BLE_ACL_BUF_SIZE);
+    acl_block_size = acl_data_length + BLE_MBUF_MEMBLOCK_OVERHEAD +
+                     BLE_HCI_DATA_HDR_SZ;
+    acl_block_size = OS_ALIGN(acl_block_size, OS_ALIGNMENT);
+    rc = mem_malloc_mempool(&ble_hci_sock_acl_pool,
+                            MYNEWT_VAL(BLE_ACL_BUF_COUNT),
+                            acl_block_size,
+                            "ble_hci_sock_acl_pool",
+                            &ble_hci_sock_acl_buf);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_mbuf_pool_init(&ble_hci_sock_acl_mbuf_pool,
+                           &ble_hci_sock_acl_pool,
+                           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 = mem_malloc_mempool(&ble_hci_sock_cmd_pool,
+                            1,
+                            BLE_HCI_TRANS_CMD_SZ,
+                            "ble_hci_sock_cmd_pool",
+                            &ble_hci_sock_cmd_buf);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = mem_malloc_mempool(&ble_hci_sock_evt_hi_pool,
+                            MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
+                            MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+                            "ble_hci_sock_evt_hi_pool",
+                            &ble_hci_sock_evt_hi_buf);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = mem_malloc_mempool(&ble_hci_sock_evt_lo_pool,
+                            MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
+                            MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
+                            "ble_hci_sock_evt_lo_pool",
+                            &ble_hci_sock_evt_lo_buf);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = ble_hci_sock_config();
+    SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failure configuring socket HCI");
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/9fcbd0d0/net/nimble/transport/socket/syscfg.yml
----------------------------------------------------------------------
diff --git a/net/nimble/transport/socket/syscfg.yml b/net/nimble/transport/socket/syscfg.yml
new file mode 100644
index 0000000..477d493
--- /dev/null
+++ b/net/nimble/transport/socket/syscfg.yml
@@ -0,0 +1,66 @@
+# 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.
+#
+
+# Package: net/nimble/transport/uart
+
+syscfg.defs:
+    BLE_HCI_EVT_BUF_SIZE:
+        description: 'The size of the allocated event buffers'
+        # The largest event the nimble controller will send is 70 bytes.
+        value: 70
+    BLE_HCI_EVT_HI_BUF_COUNT:
+        description: 'The number of high priority event buffers'
+        value: 8
+    BLE_HCI_EVT_LO_BUF_COUNT:
+        description: 'The number of low priority event buffers'
+        value: 8
+    BLE_ACL_BUF_COUNT:
+        description: 'The number of ACL data buffers'
+        value: 24
+    BLE_ACL_BUF_SIZE:
+        description: >
+            This is the maximum size of the data portion of HCI ACL data
+            packets. It does not include the HCI data header (of 4 bytes).
+        value: 255
+
+    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_SOCK_USE_TCP:
+        description: 'Use TCP socket, connects to BLE_SOCK_TCP_PORT'
+        value: 1
+
+    BLE_SOCK_TCP_PORT:
+        description: 'ipv4 tcp port to connect to'
+        value: 14433
+
+    BLE_SOCK_USE_LINUX_BLUE:
+        description: 'Use Linux bluetooth raw socket'
+        value: 0
+
+    BLE_SOCK_LINUX_DEV:
+        description: 'linux kernel device'
+        value: 0
+


[2/3] incubator-mynewt-core git commit: nimble/transport/socket; forgot to register with stats package.

Posted by ma...@apache.org.
nimble/transport/socket; forgot to register with stats package.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/52a585c1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/52a585c1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/52a585c1

Branch: refs/heads/master
Commit: 52a585c13b9b60d28bfa5d2b0f3193f0d59cee03
Parents: 9fcbd0d
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Thu Apr 6 14:32:47 2017 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Thu Apr 6 14:32:47 2017 -0700

----------------------------------------------------------------------
 net/nimble/transport/socket/src/ble_hci_socket.c | 5 +++++
 1 file changed, 5 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/52a585c1/net/nimble/transport/socket/src/ble_hci_socket.c
----------------------------------------------------------------------
diff --git a/net/nimble/transport/socket/src/ble_hci_socket.c b/net/nimble/transport/socket/src/ble_hci_socket.c
index ff4b152..be12a91 100755
--- a/net/nimble/transport/socket/src/ble_hci_socket.c
+++ b/net/nimble/transport/socket/src/ble_hci_socket.c
@@ -794,4 +794,9 @@ ble_hci_sock_init(void)
 
     rc = ble_hci_sock_config();
     SYSINIT_PANIC_ASSERT_MSG(rc == 0, "Failure configuring socket HCI");
+
+    rc = stats_init_and_reg(STATS_HDR(hci_sock_stats),
+                          STATS_SIZE_INIT_PARMS(hci_sock_stats, STATS_SIZE_32),
+                          STATS_NAME_INIT_PARMS(hci_sock_stats), "hci_socket");
+    SYSINIT_PANIC_ASSERT(rc == 0);
 }


[3/3] incubator-mynewt-core git commit: This closes #221.

Posted by ma...@apache.org.
This closes #221.

Merge branch 'hcioversocket' of https://github.com/mkiiskila/incubator-mynewt-core


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/a34f6538
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/a34f6538
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/a34f6538

Branch: refs/heads/master
Commit: a34f65387d3b5299ad68380f87558d4cce944bee
Parents: 431e500 52a585c
Author: Marko Kiiskila <ma...@runtime.io>
Authored: Thu Apr 20 08:29:39 2017 -0700
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Thu Apr 20 08:29:39 2017 -0700

----------------------------------------------------------------------
 .../socket/include/socket/ble_hci_socket.h      |  34 +
 net/nimble/transport/socket/pkg.yml             |  38 +
 .../transport/socket/src/ble_hci_socket.c       | 802 +++++++++++++++++++
 net/nimble/transport/socket/syscfg.yml          |  66 ++
 4 files changed, 940 insertions(+)
----------------------------------------------------------------------