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/16 23:18:31 UTC
incubator-mynewt-larva git commit: find-info ATT command.
Repository: incubator-mynewt-larva
Updated Branches:
refs/heads/master d1cb3225a -> a4cceb7ed
find-info ATT command.
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/a4cceb7e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/a4cceb7e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/a4cceb7e
Branch: refs/heads/master
Commit: a4cceb7eda31085d70b685b8b974b032e139dfe4
Parents: d1cb322
Author: Christopher Collins <cc...@gmail.com>
Authored: Mon Nov 16 14:18:16 2015 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Mon Nov 16 14:18:16 2015 -0800
----------------------------------------------------------------------
net/nimble/host/include/host/uuid.h | 22 --
net/nimble/host/src/ble_hs_att.c | 315 +++++++++++++++++-------
net/nimble/host/src/ble_hs_att.h | 18 +-
net/nimble/host/src/ble_hs_att_cmd.c | 82 ++++++
net/nimble/host/src/ble_hs_att_cmd.h | 81 ++++--
net/nimble/host/src/ble_hs_uuid.c | 41 +++
net/nimble/host/src/ble_hs_uuid.h | 22 ++
net/nimble/host/src/test/ble_gap_test.c | 16 ++
net/nimble/host/src/test/ble_hs_att_test.c | 66 ++++-
9 files changed, 531 insertions(+), 132 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a4cceb7e/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
deleted file mode 100644
index 7ff6820..0000000
--- a/net/nimble/host/include/host/uuid.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * 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/a4cceb7e/net/nimble/host/src/ble_hs_att.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_att.c b/net/nimble/host/src/ble_hs_att.c
index da4742d..2becbb8 100644
--- a/net/nimble/host/src/ble_hs_att.c
+++ b/net/nimble/host/src/ble_hs_att.c
@@ -4,7 +4,7 @@
* 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
@@ -22,9 +22,12 @@
#include "ble_l2cap.h"
#include "ble_l2cap_util.h"
#include "ble_hs_conn.h"
+#include "ble_hs_uuid.h"
#include "ble_hs_att_cmd.h"
#include "ble_hs_att.h"
+static uint8_t *ble_hs_att_tx_buf;
+
typedef int ble_hs_att_rx_fn(struct ble_hs_conn *conn,
struct ble_l2cap_chan *chan,
struct os_mbuf *om);
@@ -37,6 +40,9 @@ struct ble_hs_att_rx_dispatch_entry {
static int ble_hs_att_rx_mtu_req(struct ble_hs_conn *conn,
struct ble_l2cap_chan *chan,
struct os_mbuf *om);
+static int ble_hs_att_rx_find_info_req(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf *om);
static int ble_hs_att_rx_read_req(struct ble_hs_conn *conn,
struct ble_l2cap_chan *chan,
struct os_mbuf *om);
@@ -45,9 +51,10 @@ static int ble_hs_att_rx_write_req(struct ble_hs_conn *conn,
struct os_mbuf *om);
static struct ble_hs_att_rx_dispatch_entry ble_hs_att_rx_dispatch[] = {
- { BLE_HS_ATT_OP_MTU_REQ, ble_hs_att_rx_mtu_req },
- { BLE_HS_ATT_OP_READ_REQ, ble_hs_att_rx_read_req },
- { BLE_HS_ATT_OP_WRITE_REQ, ble_hs_att_rx_write_req },
+ { BLE_HS_ATT_OP_MTU_REQ, ble_hs_att_rx_mtu_req },
+ { BLE_HS_ATT_OP_FIND_INFO_REQ, ble_hs_att_rx_find_info_req },
+ { BLE_HS_ATT_OP_READ_REQ, ble_hs_att_rx_read_req },
+ { BLE_HS_ATT_OP_WRITE_REQ, ble_hs_att_rx_write_req },
};
#define BLE_HS_ATT_RX_DISPATCH_SZ \
@@ -63,43 +70,31 @@ static void *ble_hs_att_entry_mem;
static struct os_mempool ble_hs_att_entry_pool;
/**
- * Lock the host attribute list.
- *
+ * Locks the host attribute list.
+ *
* @return 0 on success, non-zero error code on failure.
*/
-static int
+static void
ble_hs_att_list_lock(void)
{
int rc;
rc = os_mutex_pend(&g_ble_hs_att_list_mutex, OS_WAIT_FOREVER);
- if (rc != 0 && rc != OS_NOT_STARTED) {
- goto err;
- }
-
- return (0);
-err:
- return (rc);
+ assert(rc == 0 || rc == OS_NOT_STARTED);
}
/**
- * Unlock the host attribute list
+ * Unlocks the host attribute list
*
* @return 0 on success, non-zero error code on failure.
*/
-static int
+static void
ble_hs_att_list_unlock(void)
{
int rc;
rc = os_mutex_release(&g_ble_hs_att_list_mutex);
- if (rc != 0 && rc != OS_NOT_STARTED) {
- goto err;
- }
-
- return (0);
-err:
- return (rc);
+ assert(rc == 0 || rc == OS_NOT_STARTED);
}
static struct ble_hs_att_entry *
@@ -134,24 +129,28 @@ ble_hs_att_entry_free(struct ble_hs_att_entry *entry)
static uint16_t
ble_hs_att_next_id(void)
{
+ /* Rollover is fatal. */
+ assert(g_ble_hs_att_id != UINT16_MAX);
+
return (++g_ble_hs_att_id);
}
/**
* Register a host attribute with the BLE stack.
*
- * @param ha A filled out ble_hs_att structure to register
- * @param handle_id A pointer to a 16-bit handle ID, which will be the
- * handle that is allocated.
+ * @param ha A filled out ble_hs_att structure to register
+ * @param handle_id A pointer to a 16-bit handle ID, which will be
+ * the handle that is allocated.
+ * @param fn The callback function that gets executed when
+ * the attribute is operated on.
*
* @return 0 on success, non-zero error code on failure.
*/
-int
+int
ble_hs_att_register(uint8_t *uuid, uint8_t flags, uint16_t *handle_id,
ble_hs_att_handle_func *fn)
{
struct ble_hs_att_entry *entry;
- int rc;
entry = ble_hs_att_entry_alloc();
if (entry == NULL) {
@@ -163,79 +162,58 @@ ble_hs_att_register(uint8_t *uuid, uint8_t flags, uint16_t *handle_id,
entry->ha_handle_id = ble_hs_att_next_id();
entry->ha_fn = fn;
- rc = ble_hs_att_list_lock();
- if (rc != 0) {
- goto err;
- }
-
+ ble_hs_att_list_lock();
STAILQ_INSERT_TAIL(&g_ble_hs_att_list, entry, ha_next);
-
- rc = ble_hs_att_list_unlock();
- if (rc != 0) {
- goto err;
- }
+ ble_hs_att_list_unlock();
if (handle_id != NULL) {
*handle_id = entry->ha_handle_id;
}
- return (0);
-
-err:
- return (rc);
+ return 0;
}
/**
* 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.
+ * 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
- * ble_hs_att element processed, or NULL if the entire list has
+ * @param ha_ptr A pointer to a pointer which will be set to the last
+ * ble_hs_att 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
-ble_hs_att_walk(ble_hs_att_walk_func_t walk_func, void *arg,
+ble_hs_att_walk(ble_hs_att_walk_func_t walk_func, void *arg,
struct ble_hs_att_entry **ha_ptr)
{
struct ble_hs_att_entry *ha;
int rc;
- rc = ble_hs_att_list_lock();
- if (rc != 0) {
- goto err;
- }
+ ble_hs_att_list_lock();
*ha_ptr = NULL;
ha = NULL;
STAILQ_FOREACH(ha, &g_ble_hs_att_list, ha_next) {
rc = walk_func(ha, arg);
if (rc == 1) {
- rc = ble_hs_att_list_unlock();
- if (rc != 0) {
- goto err;
- }
*ha_ptr = ha;
- return (1);
+ goto done;
}
}
- rc = ble_hs_att_list_unlock();
- if (rc != 0) {
- goto err;
- }
+ rc = 0;
- return (0);
-err:
- return (rc);
+done:
+ ble_hs_att_list_unlock();
+ return rc;
}
-static int
+static int
ble_hs_att_match_handle(struct ble_hs_att_entry *ha, void *arg)
{
if (ha->ha_handle_id == *(uint16_t *) arg) {
@@ -247,12 +225,12 @@ ble_hs_att_match_handle(struct ble_hs_att_entry *ha, void *arg)
/**
- * Find a host attribute by handle id.
+ * Find a host attribute by handle id.
*
* @param handle_id The handle_id to search for
* @param ble_hs_att 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
+ * @return 0 on success, BLE_ERR_ATTR_NOT_FOUND on not found, and non-zero on
* error.
*/
int
@@ -263,23 +241,21 @@ ble_hs_att_find_by_handle(uint16_t handle_id, struct ble_hs_att_entry **ha_ptr)
rc = ble_hs_att_walk(ble_hs_att_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);
+ return 0;
} else {
- return (rc);
+ /* Not found */
+ return ENOENT;
}
}
-static int
+static int
ble_hs_att_match_uuid(struct ble_hs_att_entry *ha, void *arg)
{
- ble_uuid_t *uuid;
+ uint8_t *uuid;
- uuid = (ble_uuid_t *) arg;
+ uuid = arg;
- if (memcmp(&ha->ha_uuid, uuid, sizeof(*uuid)) == 0) {
+ if (memcmp(ha->ha_uuid, uuid, sizeof ha->ha_uuid) == 0) {
return (1);
} else {
return (0);
@@ -289,17 +265,17 @@ ble_hs_att_match_uuid(struct ble_hs_att_entry *ha, void *arg)
/**
* Find a host attribute by UUID.
*
- * @param uuid The ble_uuid_t to search for
+ * @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
+ * @return 0 on success, BLE_ERR_ATTR_NOT_FOUND on not found, and non-zero on
* error.
*/
int
-ble_hs_att_find_by_uuid(ble_uuid_t *uuid, struct ble_hs_att_entry **ha_ptr)
+ble_hs_att_find_by_uuid(uint8_t *uuid, struct ble_hs_att_entry **ha_ptr)
{
int rc;
-
+
rc = ble_hs_att_walk(ble_hs_att_match_uuid, uuid, ha_ptr);
if (rc == 1) {
/* Found a matching handle */
@@ -378,6 +354,161 @@ ble_hs_att_rx_mtu_req(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
return 0;
}
+/**
+ * Fills the static ATT transmit buffer with the variable length Information
+ * Data field of a Find Information ATT response.
+ *
+ * @param req The Find Information request being responded
+ * to.
+ * @param buf The destination buffer where the Information
+ * Data field gets written.
+ * @param buf_sz The maximum size of the output data.
+ * @param rsp_sz On success, the number of bytes written gets
+ * stored here.
+ * @param format On success, the format field of the response
+ * gets stored here. One of:
+ * o BLE_HS_ATT_FIND_INFO_RSP_FORMAT_16BIT
+ * o BLE_HS_ATT_FIND_INFO_RSP_FORMAT_128BIT
+ *
+ * @return 0 on success; an ATT error code on failure.
+ */
+static int
+ble_hs_att_fill_info(struct ble_hs_att_find_info_req *req, uint8_t *buf,
+ int buf_sz, int *rsp_sz, uint8_t *format)
+{
+ struct ble_hs_att_entry *ha;
+ int new_rsp_sz;
+ int uuid16;
+
+ *format = 0;
+ *rsp_sz = 0;
+
+ ble_hs_att_list_lock();
+
+ STAILQ_FOREACH(ha, &g_ble_hs_att_list, ha_next) {
+ if (ha->ha_handle_id > req->bhafq_end_handle) {
+ goto done;
+ }
+ if (ha->ha_handle_id >= req->bhafq_start_handle) {
+ uuid16 = ble_hs_uuid_16bit(ha->ha_uuid);
+
+ if (*format == 0) {
+ if (uuid16 != -1) {
+ *format = BLE_HS_ATT_FIND_INFO_RSP_FORMAT_16BIT;
+ } else {
+ *format = BLE_HS_ATT_FIND_INFO_RSP_FORMAT_128BIT;
+ }
+ }
+
+ switch (*format) {
+ case BLE_HS_ATT_FIND_INFO_RSP_FORMAT_16BIT:
+ if (uuid16 == -1) {
+ goto done;
+ }
+
+ new_rsp_sz = *rsp_sz + 4;
+ if (new_rsp_sz > buf_sz) {
+ goto done;
+ }
+
+ htole16(buf + *rsp_sz, ha->ha_handle_id);
+ htole16(buf + *rsp_sz + 2, uuid16);
+ *rsp_sz = new_rsp_sz;
+ break;
+
+ case BLE_HS_ATT_FIND_INFO_RSP_FORMAT_128BIT:
+ if (uuid16 != -1) {
+ goto done;
+ }
+
+ new_rsp_sz = *rsp_sz + 16;
+ if (new_rsp_sz > buf_sz) {
+ goto done;
+ }
+
+ htole16(buf + *rsp_sz, ha->ha_handle_id);
+ memcpy(buf + *rsp_sz + 2, ha->ha_uuid, 16);
+ *rsp_sz = new_rsp_sz;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+ }
+ }
+
+done:
+ ble_hs_att_list_unlock();
+ if (*rsp_sz == 0) {
+ return ENOENT;
+ } else {
+ return 0;
+ }
+}
+
+static int
+ble_hs_att_rx_find_info_req(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf *om)
+{
+ struct ble_hs_att_find_info_req req;
+ struct ble_hs_att_find_info_rsp rsp;
+ uint8_t buf[BLE_HS_ATT_FIND_INFO_REQ_SZ];
+ int rsp_sz;
+ int rc;
+
+ rc = os_mbuf_copydata(om, 0, sizeof buf, buf);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = ble_hs_att_find_info_req_parse(buf, sizeof buf, &req);
+ assert(rc == 0);
+
+ /* Tx error response if start handle is greater than end handle or is 0.
+ * (Vol. 3, Part F, 3.4.3.1).
+ */
+ if (req.bhafq_start_handle > req.bhafq_end_handle ||
+ req.bhafq_start_handle == 0) {
+
+ ble_hs_att_tx_error_rsp(chan, BLE_HS_ATT_OP_FIND_INFO_REQ,
+ req.bhafq_start_handle,
+ BLE_HS_ATT_ERR_INVALID_HANDLE);
+ return EINVAL;
+ }
+
+ /* Write the variable length Information Data field, reserving room for the
+ * response base at the start of the buffer.
+ */
+ rc = ble_hs_att_fill_info(
+ &req, ble_hs_att_tx_buf + BLE_HS_ATT_FIND_INFO_RSP_MIN_SZ,
+ conn->bhc_att_mtu, &rsp_sz, &rsp.bhafp_format);
+ if (rc != 0) {
+ ble_hs_att_tx_error_rsp(chan, BLE_HS_ATT_OP_FIND_INFO_REQ,
+ req.bhafq_start_handle,
+ BLE_HS_ATT_ERR_ATTR_NOT_FOUND);
+ return rc;
+
+ }
+
+ /* Now that the value of the format field is known, write the response base
+ * at the start of the buffer.
+ */
+ rsp.bhafp_op = BLE_HS_ATT_OP_FIND_INFO_RSP;
+ rc = ble_hs_att_find_info_rsp_write(ble_hs_att_tx_buf,
+ BLE_HS_ATT_FIND_INFO_RSP_MIN_SZ, &rsp);
+ assert(rc == 0);
+
+ rc = ble_l2cap_tx(chan, ble_hs_att_tx_buf,
+ BLE_HS_ATT_FIND_INFO_RSP_MIN_SZ + rsp_sz);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
static int
ble_hs_att_tx_read_rsp(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
void *attr_data, int attr_len)
@@ -429,6 +560,7 @@ ble_hs_att_rx_read_req(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
rc = ble_hs_att_find_by_handle(req.bharq_handle, &entry);
if (rc != 0) {
+ rc = BLE_HS_ATT_ERR_INVALID_HANDLE;
goto send_err;
}
@@ -494,6 +626,7 @@ ble_hs_att_rx_write_req(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
rc = ble_hs_att_find_by_handle(req.bhawq_handle, &entry);
if (rc != 0) {
+ rc = BLE_HS_ATT_ERR_INVALID_HANDLE;
goto send_err;
}
@@ -506,7 +639,6 @@ ble_hs_att_rx_write_req(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
arg.aha_write.attr_len = OS_MBUF_PKTHDR(om)->omp_len;
rc = entry->ha_fn(entry, BLE_HS_ATT_OP_WRITE_REQ, &arg);
if (rc != 0) {
- rc = BLE_ERR_UNSPECIFIED;
goto send_err;
}
@@ -574,7 +706,7 @@ ble_hs_att_init(void)
rc = os_mutex_init(&g_ble_hs_att_list_mutex);
if (rc != 0) {
- return rc;
+ goto err;
}
free(ble_hs_att_entry_mem);
@@ -582,15 +714,32 @@ ble_hs_att_init(void)
OS_MEMPOOL_BYTES(BLE_HS_ATT_NUM_ENTRIES,
sizeof (struct ble_hs_att_entry)));
if (ble_hs_att_entry_mem == NULL) {
- return ENOMEM;
+ rc = ENOMEM;
+ goto err;
}
rc = os_mempool_init(&ble_hs_att_entry_pool, BLE_HS_ATT_NUM_ENTRIES,
sizeof (struct ble_hs_att_entry),
ble_hs_att_entry_mem, "ble_hs_att_entry_pool");
if (rc != 0) {
- return rc;
+ goto err;
+ }
+
+ free(ble_hs_att_tx_buf);
+ ble_hs_att_tx_buf = malloc(BLE_HS_ATT_MTU_MAX);
+ if (ble_hs_att_tx_buf == NULL) {
+ rc = ENOMEM;
+ goto err;
}
return 0;
+
+err:
+ free(ble_hs_att_entry_mem);
+ ble_hs_att_entry_mem = NULL;
+
+ free(ble_hs_att_tx_buf);
+ ble_hs_att_tx_buf = NULL;
+
+ return rc;
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a4cceb7e/net/nimble/host/src/ble_hs_att.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_att.h b/net/nimble/host/src/ble_hs_att.h
index 7373199..0323baa 100644
--- a/net/nimble/host/src/ble_hs_att.h
+++ b/net/nimble/host/src/ble_hs_att.h
@@ -17,9 +17,11 @@
#ifndef H_BLE_HS_ATT_
#define H_BLE_HS_ATT_
-#include "host/uuid.h"
-
#define BLE_HS_ATT_MTU_DFLT 23
+#define BLE_HS_ATT_MTU_MAX 256 /* XXX: I'm making this up! */
+
+#define BLE_HS_ATT_ERR_INVALID_HANDLE 0x01
+#define BLE_HS_ATT_ERR_ATTR_NOT_FOUND 0x0a
struct ble_hs_att_entry;
@@ -49,8 +51,14 @@ typedef int (*ble_hs_att_walk_func_t)(struct ble_hs_att_entry *, void *arg);
/**
* Handles a host attribute request.
*
- * @param entry The host attribute being requested
- * @param The request data associated with that host attribute
+ * @param entry The host attribute being requested.
+ * @param op The operation being performed on the attribute.
+ * @param arg The request data associated with that host
+ * attribute.
+ *
+ * @return 0 on success;
+ * One of the BLE_HS_ATT_ERR_[...] codes on
+ * failure.
*/
typedef int ble_hs_att_handle_func(struct ble_hs_att_entry *entry,
uint8_t op,
@@ -66,7 +74,7 @@ typedef int ble_hs_att_handle_func(struct ble_hs_att_entry *entry,
struct ble_hs_att_entry {
STAILQ_ENTRY(ble_hs_att_entry) ha_next;
- ble_uuid_t ha_uuid;
+ uint8_t ha_uuid[16];
uint8_t ha_flags;
uint8_t ha_pad1;
uint16_t ha_handle_id;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a4cceb7e/net/nimble/host/src/ble_hs_att_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_att_cmd.c b/net/nimble/host/src/ble_hs_att_cmd.c
index de1b0b6..0369cfd 100644
--- a/net/nimble/host/src/ble_hs_att_cmd.c
+++ b/net/nimble/host/src/ble_hs_att_cmd.c
@@ -88,6 +88,88 @@ ble_hs_att_mtu_req_parse(void *payload, int len,
}
int
+ble_hs_att_find_info_req_parse(void *payload, int len,
+ struct ble_hs_att_find_info_req *req)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_HS_ATT_FIND_INFO_REQ_SZ) {
+ return EMSGSIZE;
+ }
+
+ u8ptr = payload;
+
+ req->bhafq_op = u8ptr[0];
+ req->bhafq_start_handle = le16toh(u8ptr + 1);
+ req->bhafq_end_handle = le16toh(u8ptr + 3);
+
+ if (req->bhafq_op != BLE_HS_ATT_OP_FIND_INFO_REQ) {
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+int
+ble_hs_att_find_info_req_write(void *payload, int len,
+ struct ble_hs_att_find_info_req *req)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_HS_ATT_FIND_INFO_REQ_SZ) {
+ return EMSGSIZE;
+ }
+
+ u8ptr = payload;
+
+ u8ptr[0] = req->bhafq_op;
+ htole16(u8ptr + 1, req->bhafq_start_handle);
+ htole16(u8ptr + 3, req->bhafq_end_handle);
+
+ return 0;
+}
+
+int
+ble_hs_att_find_info_rsp_parse(void *payload, int len,
+ struct ble_hs_att_find_info_rsp *rsp)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_HS_ATT_FIND_INFO_RSP_MIN_SZ) {
+ return EMSGSIZE;
+ }
+
+ u8ptr = payload;
+
+ rsp->bhafp_op = u8ptr[0];
+ rsp->bhafp_format = u8ptr[1];
+
+ if (rsp->bhafp_op != BLE_HS_ATT_OP_FIND_INFO_RSP) {
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+int
+ble_hs_att_find_info_rsp_write(void *payload, int len,
+ struct ble_hs_att_find_info_rsp *rsp)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_HS_ATT_FIND_INFO_RSP_MIN_SZ) {
+ return EMSGSIZE;
+ }
+
+ u8ptr = payload;
+
+ u8ptr[0] = rsp->bhafp_op;
+ u8ptr[1] = rsp->bhafp_format;
+
+ return 0;
+}
+
+int
ble_hs_att_mtu_rsp_parse(void *payload, int len,
struct ble_hs_att_mtu_rsp *rsp)
{
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a4cceb7e/net/nimble/host/src/ble_hs_att_cmd.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_att_cmd.h b/net/nimble/host/src/ble_hs_att_cmd.h
index 3306e6f..a9caaf8 100644
--- a/net/nimble/host/src/ble_hs_att_cmd.h
+++ b/net/nimble/host/src/ble_hs_att_cmd.h
@@ -20,6 +20,8 @@ struct ble_l2cap_chan;
#define BLE_HS_ATT_OP_ERROR_RSP 0x01
#define BLE_HS_ATT_OP_MTU_REQ 0x02
#define BLE_HS_ATT_OP_MTU_RSP 0x03
+#define BLE_HS_ATT_OP_FIND_INFO_REQ 0x04
+#define BLE_HS_ATT_OP_FIND_INFO_RSP 0x05
#define BLE_HS_ATT_OP_READ_REQ 0x0a
#define BLE_HS_ATT_OP_READ_RSP 0x0b
#define BLE_HS_ATT_OP_WRITE_REQ 0x12
@@ -29,26 +31,6 @@ struct ble_l2cap_chan;
* | Parameter | Size (octets) |
* +------------------------------------+-------------------+
* | Attribute Opcode | 1 |
- * | Attribute Handle | 2 |
- */
-#define BLE_HS_ATT_READ_REQ_SZ 3
-struct ble_hs_att_read_req {
- uint8_t bharq_op;
- uint16_t bharq_handle;
-};
-
-/**
- * | Parameter | Size (octets) |
- * +------------------------------------+-------------------+
- * | Attribute Opcode | 1 |
- * | Attribute Value | 0 to (ATT_MTU-1) |
- */
-#define BLE_HS_ATT_READ_RSP_MIN_SZ 1
-
-/**
- * | Parameter | Size (octets) |
- * +------------------------------------+-------------------+
- * | Attribute Opcode | 1 |
* | Request Opcode In Error | 1 |
* | Attribute Handle In Error | 2 |
* | Error Code | 1 |
@@ -89,6 +71,57 @@ struct ble_hs_att_mtu_rsp {
* | Parameter | Size (octets) |
* +------------------------------------+-------------------+
* | Attribute Opcode | 1 |
+ * | Starting Handle | 2 |
+ * | Ending Handle | 2 |
+ */
+#define BLE_HS_ATT_FIND_INFO_REQ_SZ 5
+struct ble_hs_att_find_info_req {
+ uint8_t bhafq_op;
+ uint16_t bhafq_start_handle;
+ uint16_t bhafq_end_handle;
+};
+
+/**
+ * | Parameter | Size (octets) |
+ * +------------------------------------+-------------------+
+ * | Attribute Opcode | 1 |
+ * | Format | 1 |
+ * | Information Data | 4 to (ATT_MTU-2) |
+ */
+#define BLE_HS_ATT_FIND_INFO_RSP_MIN_SZ 2
+struct ble_hs_att_find_info_rsp {
+ uint8_t bhafp_op;
+ uint8_t bhafp_format;
+ /* Followed by information data. */
+};
+
+#define BLE_HS_ATT_FIND_INFO_RSP_FORMAT_16BIT 1
+#define BLE_HS_ATT_FIND_INFO_RSP_FORMAT_128BIT 2
+
+/**
+ * | Parameter | Size (octets) |
+ * +------------------------------------+-------------------+
+ * | Attribute Opcode | 1 |
+ * | Attribute Handle | 2 |
+ */
+#define BLE_HS_ATT_READ_REQ_SZ 3
+struct ble_hs_att_read_req {
+ uint8_t bharq_op;
+ uint16_t bharq_handle;
+};
+
+/**
+ * | Parameter | Size (octets) |
+ * +------------------------------------+-------------------+
+ * | Attribute Opcode | 1 |
+ * | Attribute Value | 0 to (ATT_MTU-1) |
+ */
+#define BLE_HS_ATT_READ_RSP_MIN_SZ 1
+
+/**
+ * | Parameter | Size (octets) |
+ * +------------------------------------+-------------------+
+ * | Attribute Opcode | 1 |
* | Attribute Handle | 2 |
* | Attribute Value | 0 to (ATT_MTU-3) |
*/
@@ -108,6 +141,14 @@ int ble_hs_att_mtu_req_parse(void *payload, int len,
struct ble_hs_att_mtu_req *req);
int ble_hs_att_mtu_rsp_parse(void *payload, int len,
struct ble_hs_att_mtu_rsp *rsp);
+int ble_hs_att_find_info_req_parse(void *payload, int len,
+ struct ble_hs_att_find_info_req *req);
+int ble_hs_att_find_info_req_write(void *payload, int len,
+ struct ble_hs_att_find_info_req *req);
+int ble_hs_att_find_info_rsp_parse(void *payload, int len,
+ struct ble_hs_att_find_info_rsp *rsp);
+int ble_hs_att_find_info_rsp_write(void *payload, int len,
+ struct ble_hs_att_find_info_rsp *rsp);
int ble_hs_att_read_req_parse(void *payload, int len,
struct ble_hs_att_read_req *req);
int ble_hs_att_read_req_write(void *payload, int len,
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a4cceb7e/net/nimble/host/src/ble_hs_uuid.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_uuid.c b/net/nimble/host/src/ble_hs_uuid.c
new file mode 100644
index 0000000..32a458b
--- /dev/null
+++ b/net/nimble/host/src/ble_hs_uuid.c
@@ -0,0 +1,41 @@
+/**
+ * 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 <inttypes.h>
+#include <string.h>
+#include "ble_hs_uuid.h"
+
+static uint8_t ble_hs_uuid_base[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
+};
+
+int
+ble_hs_uuid_16bit(uint8_t *uuid128)
+{
+ uint16_t uuid16;
+ int rc;
+
+ rc = memcmp(uuid128 + 2, ble_hs_uuid_base + 2,
+ sizeof ble_hs_uuid_base - 2);
+ if (rc != 0) {
+ return -1;
+ }
+
+ uuid16 = (uuid128[0] << 8) + uuid128[1];
+
+ return uuid16;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a4cceb7e/net/nimble/host/src/ble_hs_uuid.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_uuid.h b/net/nimble/host/src/ble_hs_uuid.h
new file mode 100644
index 0000000..013b5cb
--- /dev/null
+++ b/net/nimble/host/src/ble_hs_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 H_BLE_HS_UUID_
+#define H_BLE_HS_UUID_
+
+int ble_hs_uuid_16bit(uint8_t *uuid128);
+
+#endif /* _BLE_HOST_UUID_H */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a4cceb7e/net/nimble/host/src/test/ble_gap_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gap_test.c b/net/nimble/host/src/test/ble_gap_test.c
index b94d75f..a11b100 100644
--- a/net/nimble/host/src/test/ble_gap_test.c
+++ b/net/nimble/host/src/test/ble_gap_test.c
@@ -1,3 +1,19 @@
+/**
+ * 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 <string.h>
#include "os/os.h"
#include "testutil/testutil.h"
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/a4cceb7e/net/nimble/host/src/test/ble_hs_att_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_att_test.c b/net/nimble/host/src/test/ble_hs_att_test.c
index dbd5624..85084cc 100644
--- a/net/nimble/host/src/test/ble_hs_att_test.c
+++ b/net/nimble/host/src/test/ble_hs_att_test.c
@@ -164,7 +164,7 @@ TEST_CASE(ble_hs_att_test_read)
rc = ble_l2cap_rx_payload(conn, chan, buf, sizeof buf);
TEST_ASSERT(rc != 0);
ble_hs_att_test_misc_verify_tx_err_rsp(chan, BLE_HS_ATT_OP_READ_REQ, 0,
- BLE_ERR_ATTR_NOT_FOUND);
+ BLE_HS_ATT_ERR_INVALID_HANDLE);
/*** Successful read. */
ble_hs_att_test_attr_1 = (uint8_t[]){0,1,2,3,4,5,6,7};
@@ -228,7 +228,7 @@ TEST_CASE(ble_hs_att_test_write)
rc = ble_l2cap_rx_payload(conn, chan, buf, sizeof buf);
TEST_ASSERT(rc != 0);
ble_hs_att_test_misc_verify_tx_err_rsp(chan, BLE_HS_ATT_OP_WRITE_REQ, 0,
- BLE_ERR_ATTR_NOT_FOUND);
+ BLE_HS_ATT_ERR_INVALID_HANDLE);
/*** Successful write. */
rc = ble_hs_att_register(uuid, 0, &req.bhawq_handle,
@@ -246,10 +246,72 @@ TEST_CASE(ble_hs_att_test_write)
ble_hs_att_test_misc_verify_tx_write_rsp(chan);
}
+TEST_CASE(ble_hs_att_test_find_info)
+{
+ struct ble_hs_att_find_info_req req;
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+ uint8_t buf[BLE_HS_ATT_FIND_INFO_REQ_SZ];
+ int rc;
+
+ rc = ble_hs_init(10);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}));
+ conn = ble_hs_conn_find(2);
+ TEST_ASSERT_FATAL(conn != NULL);
+
+ chan = ble_l2cap_chan_find(conn, BLE_L2CAP_CID_ATT);
+ TEST_ASSERT_FATAL(chan != NULL);
+
+ /*** Start handle of 0. */
+ req.bhafq_op = BLE_HS_ATT_OP_FIND_INFO_REQ;
+ req.bhafq_start_handle = 0;
+ req.bhafq_end_handle = 0;
+
+ rc = ble_hs_att_find_info_req_write(buf, sizeof buf, &req);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_l2cap_rx_payload(conn, chan, buf, sizeof buf);
+ TEST_ASSERT(rc != 0);
+
+ ble_hs_att_test_misc_verify_tx_err_rsp(chan, BLE_HS_ATT_OP_FIND_INFO_REQ,
+ 0, BLE_HS_ATT_ERR_INVALID_HANDLE);
+
+ /*** Start handle > end handle. */
+ req.bhafq_start_handle = 101;
+ req.bhafq_end_handle = 100;
+
+ rc = ble_hs_att_find_info_req_write(buf, sizeof buf, &req);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_l2cap_rx_payload(conn, chan, buf, sizeof buf);
+ TEST_ASSERT(rc != 0);
+
+ ble_hs_att_test_misc_verify_tx_err_rsp(chan, BLE_HS_ATT_OP_FIND_INFO_REQ,
+ 101, BLE_HS_ATT_ERR_INVALID_HANDLE);
+
+ /*** No attributes. */
+ req.bhafq_start_handle = 200;
+ req.bhafq_end_handle = 300;
+
+ rc = ble_hs_att_find_info_req_write(buf, sizeof buf, &req);
+ TEST_ASSERT(rc == 0);
+
+ rc = ble_l2cap_rx_payload(conn, chan, buf, sizeof buf);
+ TEST_ASSERT(rc != 0);
+
+ ble_hs_att_test_misc_verify_tx_err_rsp(chan, BLE_HS_ATT_OP_FIND_INFO_REQ,
+ 200, BLE_HS_ATT_ERR_ATTR_NOT_FOUND);
+
+ /* XXX: Test successful responses. */
+}
+
TEST_SUITE(att_suite)
{
ble_hs_att_test_read();
ble_hs_att_test_write();
+ ble_hs_att_test_find_info();
}
int