You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2015/11/04 04:00:50 UTC

[2/2] incubator-mynewt-larva git commit: Initial "scaffolding" for host-side data rx/tx.

Initial "scaffolding" for host-side data rx/tx.


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

Branch: refs/heads/master
Commit: 99feb02d0a4f7992c159951cb5e1f772b2d26bd8
Parents: 8a2e854
Author: Christopher Collins <cc...@gmail.com>
Authored: Tue Nov 3 19:00:07 2015 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Tue Nov 3 19:00:07 2015 -0800

----------------------------------------------------------------------
 net/nimble/host/include/host/attr.h      |  79 +++++++
 net/nimble/host/include/host/host_hci.h  |   2 +
 net/nimble/host/include/host/host_task.h |  48 +++++
 net/nimble/host/include/host/uuid.h      |  22 ++
 net/nimble/host/src/arch/sim/itf.c       | 290 ++++++++++++++++++++++++++
 net/nimble/host/src/attr.c               | 249 ++++++++++++++++++++++
 net/nimble/host/src/host_hci.c           |  83 +++++++-
 net/nimble/host/src/host_task.c          | 127 +++++++++++
 net/nimble/host/src/itf.h                |  14 ++
 net/nimble/host/src/l2cap.c              |  43 ++++
 net/nimble/host/src/l2cap.h              |  25 +++
 net/nimble/include/nimble/hci_common.h   |  11 +
 project/host_test/host_test.yml          |   5 +
 project/host_test/src/main.c             |  95 +++++++++
 14 files changed, 1090 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/net/nimble/host/include/host/attr.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/attr.h b/net/nimble/host/include/host/attr.h
new file mode 100644
index 0000000..2a37cbb
--- /dev/null
+++ b/net/nimble/host/include/host/attr.h
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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_HOST_ATTR_H 
+#define _BLE_HOST_ATTR_H 
+
+#include <host/uuid.h>
+#include <os/os.h>
+#include <os/queue.h>
+
+#define BLE_HOST_EVENT_NEW_ATTR_CONN (OS_EVENT_T_PERUSER)
+
+struct ble_att_chan {
+    int c_fd;
+    int c_state; 
+}; 
+
+struct host_attr;
+
+/**
+ * Called from host_attr_walk().  Called on each entry in the 
+ * host_attr_list.
+ *
+ * @param Contains the current host_attr being iterated through
+ * @param The user supplied argument to host_attr_walk()
+ *
+ * @return 0 on continue, 1 on stop
+ */
+typedef int (*host_attr_walk_func_t)(struct host_attr *, void *arg);
+
+/**
+ * Handles a host attribute request.
+ *
+ * @param The host attribute being requested 
+ * @param The request data associated with that host attribute
+ */
+typedef int (*host_attr_handle_func_t)(struct host_attr *, uint8_t *data);
+
+#define HA_FLAG_PERM_READ            (1 << 0)
+#define HA_FLAG_PERM_WRITE           (1 << 1) 
+#define HA_FLAG_PERM_RW              (1 << 2)
+#define HA_FLAG_ENC_REQ              (1 << 3)
+#define HA_FLAG_AUTHENTICATION_REQ   (1 << 4)
+#define HA_FLAG_AUTHORIZATION_REQ    (1 << 5)
+
+struct host_attr {
+    ble_uuid_t ha_uuid;
+    uint8_t ha_flags;
+    uint8_t ha_pad1;
+    uint16_t ha_handle_id;
+    STAILQ_ENTRY(host_attr) ha_next;
+};
+
+
+#define HA_OPCODE_METHOD_START (0)
+#define HA_OPCODE_METHOD_END (5)
+#define HA_OPCODE_COMMAND_FLAG (1 << 6) 
+#define HA_OPCODE_AUTH_SIG_FLAG (1 << 7) 
+
+
+#define HA_METH_ERROR_RSP        (0x01)
+#define HA_METH_EXCHANGE_MTU_REQ (0x02)
+#define HA_METH_EXCHANGE_MTU_RSP (0x03)
+
+
+#endif /* _BLE_HOST_ATTR_H */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/net/nimble/host/include/host/host_hci.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/host_hci.h b/net/nimble/host/include/host/host_hci.h
index 526c57e..d8716b4 100644
--- a/net/nimble/host/include/host/host_hci.h
+++ b/net/nimble/host/include/host/host_hci.h
@@ -37,4 +37,6 @@ int host_hci_cmd_le_add_to_whitelist(uint8_t *addr, uint8_t addr_type);
 int host_hci_cmd_le_rmv_from_whitelist(uint8_t *addr, uint8_t addr_type);
 
 
+int host_hci_data_rx(void *pkt, uint16_t len);
+
 #endif /* H_HOST_HCI_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/net/nimble/host/include/host/host_task.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/host_task.h b/net/nimble/host/include/host/host_task.h
new file mode 100644
index 0000000..e90bd7a
--- /dev/null
+++ b/net/nimble/host/include/host/host_task.h
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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_HOST_H 
+#define _BLE_HOST_H 
+
+#include <inttypes.h>
+
+
+/**
+ * ---
+ * XXX: This is all temporary.
+ */
+#define BLE_HOST_MAX_CONNECTIONS 16
+
+struct ble_host_connection {
+    uint16_t bc_handle;
+    int bc_fd;
+};
+
+extern int ble_host_listen_enabled;
+extern struct ble_host_connection
+    ble_host_connections[BLE_HOST_MAX_CONNECTIONS];
+extern int ble_host_num_connections;
+
+struct ble_host_connection *ble_host_find_connection(uint16_t con_handle);
+/** --- */
+
+void ble_host_task_handler(void *arg);
+int ble_host_send_data_connectionless(uint16_t con_handle, uint16_t cid,
+                                      uint8_t *data, uint16_t len);
+int ble_host_poll(void);
+int host_init(void);
+
+#endif /* _BLE_HOST_H */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/net/nimble/host/include/host/uuid.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/uuid.h b/net/nimble/host/include/host/uuid.h
new file mode 100644
index 0000000..7ff6820
--- /dev/null
+++ b/net/nimble/host/include/host/uuid.h
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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_HOST_UUID_H 
+#define _BLE_HOST_UUID_H 
+
+typedef struct ble_uuid { uint8_t uuid[128]; } ble_uuid_t;
+
+#endif /* _BLE_HOST_UUID_H */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/net/nimble/host/src/arch/sim/itf.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/arch/sim/itf.c b/net/nimble/host/src/arch/sim/itf.c
new file mode 100644
index 0000000..b3c6f29
--- /dev/null
+++ b/net/nimble/host/src/arch/sim/itf.c
@@ -0,0 +1,290 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <os/os.h>
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h> 
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <unistd.h>
+#include "nimble/ble.h"
+#include "nimble/hci_common.h"
+#include "host/attr.h"
+#include "host/host_task.h"
+#include "host/host_hci.h"
+#include "itf.h"
+
+#define BLE_L2CAP_CID_ATT       4
+#define BLE_L2CAP_CID_SIG       5
+
+#define BLE_SIM_BASE_PORT       10000
+
+static void
+set_nonblock(int fd)
+{
+    int flags;
+    int rc;
+
+    flags = fcntl(fd, F_GETFL, 0);
+    rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+    assert(rc >= 0);
+}
+
+
+int
+ble_sim_listen(uint16_t con_handle)
+{
+    struct ble_host_connection *connection;
+    struct sockaddr_in sin;
+    struct hostent *ent;
+    int fd;
+    int rc;
+
+    if (ble_host_num_connections >= BLE_HOST_MAX_CONNECTIONS) {
+        return EINVAL; // XXX
+    }
+    connection = ble_host_connections + ble_host_num_connections;
+
+    /* resolve host addr first, then create a socket and bind() to 
+     * that address.
+     */
+    ent = gethostbyname("localhost");
+    if (ent == NULL) {
+        return errno;
+    }
+
+    memset(&sin, 0, sizeof(sin));
+    memcpy(&sin.sin_addr, ent->h_addr_list[0], ent->h_length);
+    sin.sin_family = AF_INET;
+    sin.sin_port = htons(BLE_SIM_BASE_PORT + con_handle);
+
+    fd = socket(AF_INET, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        return errno;
+    }
+
+    set_nonblock(fd);
+
+    rc = bind(fd, (struct sockaddr *)&sin, sizeof sin);
+    if (rc != 0) {
+        close(fd);
+        return errno;
+    }
+
+    memset(connection, 0, sizeof *connection);
+    connection->bc_handle = con_handle;
+    connection->bc_fd = fd;
+
+    ble_host_num_connections++;
+
+    return 0;
+}
+
+static int
+ble_sim_connect(uint16_t con_handle)
+{
+    struct ble_host_connection *connection;
+    struct sockaddr_in sin;
+    struct hostent *ent;
+    int fd;
+    int rc;
+
+    if (ble_host_num_connections >= BLE_HOST_MAX_CONNECTIONS) {
+        return EINVAL; // XXX
+    }
+    connection = ble_host_connections + ble_host_num_connections;
+
+    /* resolve host addr first, then create a socket and bind() to 
+     * that address.
+     */
+    ent = gethostbyname("localhost");
+    if (ent == NULL) {
+        rc = errno;
+        goto err;
+    }
+
+    memset(&sin, 0, sizeof(sin));
+    memcpy(&sin.sin_addr, ent->h_addr_list[0], ent->h_length);
+    sin.sin_family = AF_INET;
+    sin.sin_port = htons(BLE_SIM_BASE_PORT + con_handle);
+
+    fd = socket(AF_INET, SOCK_DGRAM, 0);
+    if (fd < 0) {
+        rc = errno;
+        goto err;
+    }
+
+    set_nonblock(fd);
+
+    rc = connect(fd, (struct sockaddr *)&sin, sizeof sin);
+    if (rc != 0 && errno != EINPROGRESS) {
+        rc = errno;
+        goto err;
+    }
+
+    memset(connection, 0, sizeof *connection);
+    connection->bc_handle = con_handle;
+    connection->bc_fd = fd;
+
+    ble_host_num_connections++;
+
+    return 0;
+
+err:
+    return rc;
+}
+
+static int
+ble_sim_ensure_connection(uint16_t con_handle,
+                          struct ble_host_connection **connection)
+{
+    int rc;
+
+    *connection = ble_host_find_connection(con_handle);
+    if (*connection != NULL) {
+        return 0;
+    }
+
+    rc = ble_sim_connect(con_handle);
+    if (rc != 0) {
+        return rc;
+    }
+
+    *connection = ble_host_connections + ble_host_num_connections - 1;
+    return 0;
+}
+
+static int
+ble_sim_send(uint16_t con_handle, const void *data, uint16_t len)
+{
+    struct ble_host_connection *connection;
+    int rc;
+    int i;
+
+    rc = ble_sim_ensure_connection(con_handle, &connection);
+    if (rc != 0) {
+        return rc;
+    }
+
+    printf("sending %d bytes: ", len);
+    for (i = 0; i < len; i++) {
+        printf("%02x ", ((const uint8_t *)data)[i]);
+    }
+    printf("\n");
+
+    while (len > 0) {
+        rc = send(connection->bc_fd, data, len, 0);
+        if (rc >= 0) {
+            data += rc;
+            len -= rc;
+        } else {
+            return errno;
+        }
+    }
+
+    return 0;
+}
+
+int
+ble_host_sim_send_data_connectionless(uint16_t con_handle, uint16_t cid,
+                                      uint8_t *data, uint16_t len)
+{
+    static uint8_t buf[1024];
+    int off;
+    int rc;
+
+    off = 0;
+
+    htole16(buf + off, con_handle | (0 << 12) | (0 << 14));
+    off += 2;
+
+    htole16(buf + off, len + 4);
+    off += 2;
+
+    htole16(buf + off, len);
+    off += 2;
+
+    htole16(buf + off, cid);
+    off += 2;
+
+    memcpy(buf + off, data, len);
+    off += len;
+
+    rc = ble_sim_send(con_handle, buf, off);
+    return rc;
+}
+
+int 
+ble_host_sim_poll(void)
+{
+    static uint8_t buf[1024];
+    struct ble_host_connection *conn;
+    fd_set r_fd_set;
+    fd_set w_fd_set;
+    uint16_t pkt_size;
+    int nevents;
+    int max_fd;
+    int fd;
+    int rc;
+    int i;
+
+    FD_ZERO(&r_fd_set);
+    FD_ZERO(&w_fd_set);
+
+    max_fd = 0;
+    for (i = 0; i < ble_host_num_connections; i++) {
+        fd = ble_host_connections[i].bc_fd;
+        FD_SET(fd, &r_fd_set);
+        FD_SET(fd, &w_fd_set);
+        if (fd > max_fd) {
+            max_fd = fd;
+        }
+    }
+
+    do {
+        nevents = select(max_fd + 1, &r_fd_set, &w_fd_set, NULL, NULL);
+    } while (nevents < 0 && errno == EINTR);
+
+    if (nevents > 0) {
+        for (i = 0; i < ble_host_num_connections; i++) {
+            if (FD_ISSET(ble_host_connections[i].bc_fd, &r_fd_set)) {
+                conn = ble_host_connections + i;
+                while (1) {
+                    rc = recv(conn->bc_fd, buf, sizeof buf, 0);
+                    if (rc <= 0) {
+                        break;
+                    }
+                    pkt_size = rc;
+
+                    printf("received HCI data packet (%d bytes): ", pkt_size);
+                    for (i = 0; i < pkt_size; i++) {
+                        printf("%02x ", buf[i]);
+                    }
+                    printf("\n");
+
+                    rc = host_hci_data_rx(buf, pkt_size);
+                }
+            }
+        }
+    }
+
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/net/nimble/host/src/attr.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/attr.c b/net/nimble/host/src/attr.c
new file mode 100644
index 0000000..35a04ab
--- /dev/null
+++ b/net/nimble/host/src/attr.c
@@ -0,0 +1,249 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 <os/os.h>
+#include <string.h>
+
+#include <nimble/ble.h>
+#include <host/attr.h>
+
+static STAILQ_HEAD(, host_attr) g_host_attr_list = 
+    STAILQ_HEAD_INITIALIZER(g_host_attr_list);
+static uint16_t g_host_attr_id;
+
+static struct os_mutex g_host_attr_list_mutex;
+
+/**
+ * Lock the host attribute list.
+ * 
+ * @return 0 on success, non-zero error code on failure.
+ */
+static int 
+host_attr_list_lock(void)
+{
+    int rc;
+
+    rc = os_mutex_pend(&g_host_attr_list_mutex, OS_WAIT_FOREVER);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Unlock the host attribute list
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+static int 
+host_attr_list_unlock(void)
+{
+    int rc;
+
+    rc = os_mutex_release(&g_host_attr_list_mutex);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+
+/**
+ * Allocate the next handle id and return it.
+ *
+ * @return A new 16-bit handle ID.
+ */
+static uint16_t
+host_attr_next_id(void)
+{
+    return (++g_host_attr_id);
+}
+
+/**
+ * Register a host attribute with the BLE stack.
+ *
+ * @param ha A filled out host_attr structure to register
+ * @param handle_id A pointer to a 16-bit handle ID, which will be the 
+ *                  handle that is allocated.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+int 
+host_attr_register(struct host_attr *ha, uint16_t *handle_id)
+{
+    int rc;
+
+    *handle_id = host_attr_next_id();
+    ha->ha_handle_id = *handle_id;
+
+    rc = host_attr_list_lock();
+    if (rc != 0) {
+        goto err;
+    }
+
+    STAILQ_INSERT_TAIL(&g_host_attr_list, ha, ha_next);
+
+    rc = host_attr_list_unlock();
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Walk the host attribute list, calling walk_func on each entry with argument.
+ * If walk_func wants to stop iteration, it returns 1.  To continue iteration 
+ * it returns 0.  
+ *
+ * @param walk_func The function to call for each element in the host attribute
+ *                  list.
+ * @param arg       The argument to provide to walk_func
+ * @param ha_ptr    A pointer to a pointer which will be set to the last 
+ *                  host_attr element processed, or NULL if the entire list has 
+ *                  been processed
+ *
+ * @return 1 on stopped, 0 on fully processed and an error code otherwise.
+ */
+int
+host_attr_walk(host_attr_walk_func_t walk_func, void *arg, 
+        struct host_attr **ha_ptr)
+{
+    struct host_attr *ha;
+    int rc;
+
+    rc = host_attr_list_lock();
+    if (rc != 0) {
+        goto err;
+    }
+
+    *ha_ptr = NULL;
+    ha = NULL;
+    STAILQ_FOREACH(ha, &g_host_attr_list, ha_next) {
+        rc = walk_func(ha, arg);
+        if (rc == 1) {
+            rc = host_attr_list_unlock();
+            if (rc != 0) {
+                goto err;
+            }
+            *ha_ptr = ha;
+            return (1);
+        }
+    }
+
+    rc = host_attr_list_unlock();
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+static int 
+host_attr_match_handle(struct host_attr *ha, void *arg)
+{
+    if (ha->ha_handle_id == *(uint16_t *) arg) {
+        return (1);
+    } else {
+        return (0);
+    }
+}
+
+
+/**
+ * Find a host attribute by handle id. 
+ *
+ * @param handle_id The handle_id to search for
+ * @param host_attr A pointer to a pointer to put the matching host attr into.
+ *
+ * @return 0 on success, BLE_ERR_ATTR_NOT_FOUND on not found, and non-zero on 
+ *         error.
+ */
+int
+host_attr_find_by_handle(uint16_t handle_id, struct host_attr **ha_ptr)
+{
+    int rc;
+
+    rc = host_attr_walk(host_attr_match_handle, &handle_id, ha_ptr);
+    if (rc == 1) {
+        /* Found a matching handle */
+        return (0);
+    } else if (rc == 0) {
+        /* Not found */
+        return (BLE_ERR_ATTR_NOT_FOUND);
+    } else {
+        return (rc);
+    }
+}
+
+static int 
+host_attr_match_uuid(struct host_attr *ha, void *arg)
+{
+    ble_uuid_t *uuid;
+
+    uuid = (ble_uuid_t *) arg;
+
+    if (memcmp(&ha->ha_uuid, uuid, sizeof(*uuid)) == 0) {
+        return (1);
+    } else {
+        return (0);
+    }
+}
+
+
+/**
+ * Find a host attribute by UUID.
+ *
+ * @param uuid The ble_uuid_t to search for 
+ * @param ha_ptr A pointer to a pointer to put the matching host attr into.
+ *
+ * @return 0 on success, BLE_ERR_ATTR_NOT_FOUND on not found, and non-zero on 
+ *         error.
+ */
+int
+host_attr_find_by_uuid(ble_uuid_t *uuid, struct host_attr **ha_ptr) 
+{
+    int rc;
+    
+    rc = host_attr_walk(host_attr_match_uuid, uuid, ha_ptr);
+    if (rc == 1) {
+        /* Found a matching handle */
+        return (0);
+    } else if (rc == 0) {
+        /* No match */
+        return (BLE_ERR_ATTR_NOT_FOUND);
+    } else {
+        return (rc);
+    }
+}
+
+#if 0
+int
+ble_host_att_rx(void *pkt, int len)
+{
+
+}
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/net/nimble/host/src/host_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_hci.c b/net/nimble/host/src/host_hci.c
index 08b18ae..4f736db 100644
--- a/net/nimble/host/src/host_hci.c
+++ b/net/nimble/host/src/host_hci.c
@@ -16,11 +16,15 @@
 #include <stdint.h>
 #include <assert.h>
 #include <string.h>
+#include <errno.h>
+#include <stdio.h>
 #include "os/os.h"
 #include "console/console.h"
 #include "nimble/hci_common.h"
 #include "nimble/hci_transport.h"
+#include "host/host_task.h"
 #include "host_dbg.h"
+#include "l2cap.h"
 
 #define HCI_CMD_BUFS        (8)
 #define HCI_CMD_BUF_SIZE    (260)       /* XXX: temporary, Fix later */
@@ -52,11 +56,13 @@ struct host_hci_stats g_host_hci_stats;
 extern void bletest_execute(void);
 struct os_callout_func g_ble_host_hci_timer;
 
+#if 0
 static int
 host_hci_cmd_send(uint8_t *cmdbuf)
 {
     return ble_hci_transport_host_cmd_send(cmdbuf);
 }
+#endif
 
 static int
 host_hci_le_cmd_send(uint16_t ocf, uint8_t len, void *cmddata)
@@ -74,7 +80,7 @@ host_hci_le_cmd_send(uint16_t ocf, uint8_t len, void *cmddata)
         if (len) {
             memcpy(cmd + BLE_HCI_CMD_HDR_LEN, cmddata, len);
         }
-        rc = host_hci_cmd_send(cmd);
+        //rc = host_hci_cmd_send(cmd);
     }
 
     return rc;
@@ -412,10 +418,10 @@ void
 host_hci_timer_cb(void *arg)
 {
     /* Call the bletest code */
-    bletest_execute();
+    //bletest_execute();
 
     /* Re-start the timer */
-    os_callout_reset(&g_ble_host_hci_timer.cf_c, OS_TICKS_PER_SEC);
+    //os_callout_reset(&g_ble_host_hci_timer.cf_c, OS_TICKS_PER_SEC);
 }
 
 void
@@ -445,6 +451,77 @@ host_hci_task(void *arg)
     }
 }
 
+static int
+host_hci_data_parse_hdr(void *pkt, uint16_t len, struct hci_data_hdr *hdr)
+{
+    uint8_t *u8ptr;
+    uint16_t off;
+
+    if (len < BLE_HCI_DATA_HDR_SZ) {
+        return EMSGSIZE;
+    }
+
+    off = 0;
+    u8ptr = pkt;
+
+    hdr->hdh_handle_pb_bc = le16toh(u8ptr + off);
+    off += 2;
+
+    hdr->hdh_len = le16toh(u8ptr + off);
+    off += 2;
+
+    return 0;
+}
+
+int
+host_hci_data_rx(void *pkt, uint16_t len)
+{
+    struct ble_host_connection *connection;
+    struct ble_l2cap_hdr l2cap_hdr;
+    struct hci_data_hdr hci_hdr;
+    uint16_t handle;
+    uint16_t off;
+    uint8_t *u8ptr;
+    int rc;
+
+    u8ptr = pkt;
+    off = 0;
+
+    rc = host_hci_data_parse_hdr(u8ptr + off, len - off, &hci_hdr);
+    if (rc != 0) {
+        return rc;
+    }
+    off += BLE_HCI_DATA_HDR_SZ;
+    if (len < off + hci_hdr.hdh_len) {
+        return EMSGSIZE;
+    }
+
+    handle = BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc);
+    connection = ble_host_find_connection(handle);
+    if (connection == NULL) {
+        return ENOTCONN;
+    }
+
+    rc = ble_l2cap_parse_hdr(u8ptr + off, len - off, &l2cap_hdr);
+    if (rc != 0) {
+        return rc;
+    }
+    off += BLE_L2CAP_HDR_SZ;
+    if (l2cap_hdr.blh_len != hci_hdr.hdh_len - BLE_L2CAP_HDR_SZ) {
+        return EMSGSIZE;
+    }
+
+    printf("hci-handle-pb-bc=%d\n", hci_hdr.hdh_handle_pb_bc);
+    printf("hci-len=%d\n", hci_hdr.hdh_len);
+    printf("l2cap-len=%d\n", l2cap_hdr.blh_len);
+    printf("l2cap-cid=%d\n", l2cap_hdr.blh_cid);
+    printf("\n");
+
+    ble_l2cap_rx(connection, &hci_hdr, &l2cap_hdr, u8ptr + off);
+
+    return 0;
+}
+
 int
 host_hci_init(void)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/net/nimble/host/src/host_task.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_task.c b/net/nimble/host/src/host_task.c
new file mode 100644
index 0000000..a5148d2
--- /dev/null
+++ b/net/nimble/host/src/host_task.c
@@ -0,0 +1,127 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 "os/os.h"
+#include "host/attr.h"
+#include "host/host_task.h"
+#ifdef ARCH_sim
+#include "itf.h"
+#endif
+
+
+int ble_host_listen_enabled;
+
+struct ble_host_connection ble_host_connections[BLE_HOST_MAX_CONNECTIONS];
+int ble_host_num_connections;
+
+static struct os_eventq host_task_evq;
+//static struct ble_att_chan default_attr_chan; 
+static struct os_callout ble_host_task_timer;
+
+/**
+ * Initialize the host portion of the BLE stack.
+ */
+int 
+host_init(void)
+{
+    os_eventq_init(&host_task_evq);
+    os_callout_init(&ble_host_task_timer, &host_task_evq, NULL);
+
+#ifdef ARCH_sim
+    if (ble_host_listen_enabled) {
+        int rc;
+
+        rc = ble_sim_listen(1);
+        assert(rc == 0);
+    }
+#endif
+
+    return 0;
+}
+
+struct ble_host_connection *
+ble_host_find_connection(uint16_t con_handle)
+{
+    int i;
+
+    for (i = 0; i < BLE_HOST_MAX_CONNECTIONS; i++) {
+        if (ble_host_connections[i].bc_handle == con_handle) {
+            return ble_host_connections + i;
+        }
+    }
+
+    return NULL;
+}
+
+int
+ble_host_send_data_connectionless(uint16_t con_handle, uint16_t cid,
+                                  uint8_t *data, uint16_t len)
+{
+    int rc;
+
+#ifdef ARCH_sim
+    rc = ble_host_sim_send_data_connectionless(con_handle, cid, data, len);
+#else
+    rc = -1;
+#endif
+
+    return rc;
+}
+
+/**
+ * XXX: This is only here for testing.
+ */
+int 
+ble_host_poll(void)
+{
+    int rc;
+
+#ifdef ARCH_sim
+    rc = ble_host_sim_poll();
+#else
+    rc = -1;
+#endif
+
+    return rc;
+}
+
+void
+ble_host_task_handler(void *arg)
+{
+    struct os_event *ev;
+
+    os_callout_reset(&ble_host_task_timer, 50);
+
+    /**
+     * How do we decide what channels to listen on for data?  This must be 
+     * configured to the host task.  Maintain a list of channels to 
+     *
+     */
+    while (1) {
+        ev = os_eventq_get(&host_task_evq);
+        switch (ev->ev_type) {
+            case OS_EVENT_T_TIMER:
+                /* Poll the attribute channel */
+                //ble_att_chan_poll(&default_attr_chan, &host_task_evq);            
+                /* Reset callout, wakeup every 50ms */
+                os_callout_reset(&ble_host_task_timer, 50);
+                break;
+            case BLE_HOST_EVENT_NEW_ATTR_CONN: 
+                break;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/net/nimble/host/src/itf.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/itf.h b/net/nimble/host/src/itf.h
new file mode 100644
index 0000000..cd11cf9
--- /dev/null
+++ b/net/nimble/host/src/itf.h
@@ -0,0 +1,14 @@
+#ifndef H_ITF_
+#define H_ITF_
+
+struct ble_att_chan;
+struct os_eventq;
+
+int ble_att_chan_open_default(struct ble_att_chan *ac);
+int ble_att_chan_poll(struct ble_att_chan *c, struct os_eventq *evq);
+int ble_host_sim_send_data_connectionless(uint16_t con_handle, uint16_t cid,
+                                          uint8_t *data, uint16_t len);
+int ble_sim_listen(uint16_t con_handle);
+int ble_host_sim_poll(void);
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/net/nimble/host/src/l2cap.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/l2cap.c b/net/nimble/host/src/l2cap.c
new file mode 100644
index 0000000..c4490a1
--- /dev/null
+++ b/net/nimble/host/src/l2cap.c
@@ -0,0 +1,43 @@
+#include <errno.h>
+#include "nimble/ble.h"
+#include "nimble/hci_common.h"
+#include "l2cap.h"
+
+int
+ble_l2cap_parse_hdr(void *pkt, uint16_t len, struct ble_l2cap_hdr *l2cap_hdr)
+{
+    uint8_t *u8ptr;
+    uint16_t off;
+
+    if (len < BLE_L2CAP_HDR_SZ) {
+        return EMSGSIZE;
+    }
+
+    off = 0;
+    u8ptr = pkt;
+
+    l2cap_hdr->blh_len = le16toh(u8ptr + off);
+    off += 2;
+
+    l2cap_hdr->blh_cid = le16toh(u8ptr + off);
+    off += 2;
+
+    if (len < BLE_L2CAP_HDR_SZ + l2cap_hdr->blh_len) {
+        return EMSGSIZE;
+    }
+
+    return 0;
+}
+
+int
+ble_l2cap_rx(struct ble_host_connection *connection,
+             struct hci_data_hdr *hci_hdr,
+             struct ble_l2cap_hdr *l2cap_hdr,
+             void *pkt)
+{
+    /* XXX: Look up L2CAP channel by connection-cid pair. */
+    /* XXX: Append incoming data to channel buffer. */
+    /* XXX: Call channel-specific rx callback. */
+
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/net/nimble/host/src/l2cap.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/l2cap.h b/net/nimble/host/src/l2cap.h
new file mode 100644
index 0000000..0390beb
--- /dev/null
+++ b/net/nimble/host/src/l2cap.h
@@ -0,0 +1,25 @@
+#ifndef H_L2CAP_
+#define H_L2CAP_
+
+struct ble_host_connection;
+struct hci_data_hdr;
+
+#define BLE_L2CAP_CID_SIG   1
+#define BLE_L2CAP_CID_ATT   4
+
+#define BLE_L2CAP_HDR_SZ    4
+
+struct ble_l2cap_hdr
+{
+    uint16_t blh_len;
+    uint16_t blh_cid;
+};
+
+int ble_l2cap_parse_hdr(void *pkt, uint16_t len,
+                        struct ble_l2cap_hdr *l2cap_hdr);
+int ble_l2cap_rx(struct ble_host_connection *connection,
+                 struct hci_data_hdr *hci_hdr,
+                 struct ble_l2cap_hdr *l2cap_hdr,
+                 void *pkt);
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/net/nimble/include/nimble/hci_common.h
----------------------------------------------------------------------
diff --git a/net/nimble/include/nimble/hci_common.h b/net/nimble/include/nimble/hci_common.h
index 03af0de..b02ecdd 100644
--- a/net/nimble/include/nimble/hci_common.h
+++ b/net/nimble/include/nimble/hci_common.h
@@ -267,4 +267,15 @@ struct hci_adv_params
     uint8_t peer_addr[BLE_DEV_ADDR_LEN];
 };
 
+#define BLE_HCI_DATA_HDR_SZ         4
+#define BLE_HCI_DATA_HANDLE(handle_pb_bc)   (((handle_pb_bc) & 0x0fff) >> 0)
+#define BLE_HCI_DATA_PB(handle_pb_bc)       (((handle_pb_bc) & 0x3000) >> 12)
+#define BLE_HCI_DATA_BC(handle_pb_bc)       (((handle_pb_bc) & 0xc000) >> 14)
+
+struct hci_data_hdr
+{
+    uint16_t hdh_handle_pb_bc;
+    uint16_t hdh_len;
+};
+
 #endif /* H_BLE_HCI_COMMON_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/project/host_test/host_test.yml
----------------------------------------------------------------------
diff --git a/project/host_test/host_test.yml b/project/host_test/host_test.yml
new file mode 100644
index 0000000..75a63a2
--- /dev/null
+++ b/project/host_test/host_test.yml
@@ -0,0 +1,5 @@
+project.name: host_test
+project.eggs: 
+    - libs/os 
+    - net/nimble/host
+    - libs/console/full

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/99feb02d/project/host_test/src/main.c
----------------------------------------------------------------------
diff --git a/project/host_test/src/main.c b/project/host_test/src/main.c
new file mode 100755
index 0000000..c981581
--- /dev/null
+++ b/project/host_test/src/main.c
@@ -0,0 +1,95 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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 "os/os.h"
+#include "nimble/ble.h"
+#include "host/host_hci.h"
+#include "host/host_task.h"
+
+#define HOST_TASK_PRIO (1) 
+#define HOST_STACK_SIZE (OS_STACK_ALIGN(4096))
+
+static struct os_task host_task;
+static os_stack_t host_stack[HOST_STACK_SIZE];
+
+static void
+host_test_task_handler(void *arg)
+{
+    int rc;
+
+    host_init();
+
+    while (1) {
+        os_time_delay(1000);
+        if (!ble_host_listen_enabled) {
+            rc = ble_host_send_data_connectionless(1, 4, (uint8_t *)"BLAH", 4);
+            printf("ble_host_send_data_connectionless(); rc=%d\n", rc);
+        } else {
+            ble_host_poll();
+        }
+    }
+}
+
+
+/**
+ * init_tasks
+ *  
+ * Called by main.c after os_init(). This function performs initializations 
+ * that are required before tasks are running. 
+ *  
+ * @return int 0 success; error otherwise.
+ */
+int
+init_tasks(void)
+{
+    os_task_init(&host_task, "host", host_test_task_handler, NULL, 
+            HOST_TASK_PRIO, OS_WAIT_FOREVER, host_stack, HOST_STACK_SIZE);
+
+    return (0);
+}
+
+/**
+ * main
+ *  
+ * The main function for the project. This function initializes the os, calls 
+ * init_tasks to initialize tasks (and possibly other objects), then starts the 
+ * OS. We should not return from os start. 
+ *  
+ * @return int NOTE: this function should never return!
+ */
+int
+main(int argc, char **argv)
+{
+    /* Initialize OS */
+    os_init();
+
+    /* Init tasks */
+    init_tasks();
+
+    if (argc > 1 && strcmp(argv[1], "-l") == 0) {
+        ble_host_listen_enabled = 1;
+    }
+
+    /* Start the OS */
+    os_start();
+
+    /* os start should never return. If it does, this should be an error */
+    assert(0);
+
+    return (0);
+}