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/12/04 23:41:50 UTC
incubator-mynewt-larva git commit: GATT Discover Primary Service by
Service UUID proc
Repository: incubator-mynewt-larva
Updated Branches:
refs/heads/master 21a7e74ab -> 941319ca0
GATT Discover Primary Service by Service UUID proc
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/941319ca
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/941319ca
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/941319ca
Branch: refs/heads/master
Commit: 941319ca0a1a360680be8d3c96683f9e296bc7da
Parents: 21a7e74
Author: Christopher Collins <cc...@gmail.com>
Authored: Fri Dec 4 14:41:29 2015 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Fri Dec 4 14:41:29 2015 -0800
----------------------------------------------------------------------
net/nimble/host/include/host/ble_gatt.h | 8 +-
net/nimble/host/src/ble_att.c | 2 +
net/nimble/host/src/ble_att.h | 9 +
net/nimble/host/src/ble_att_clt.c | 135 +++++++++++-
net/nimble/host/src/ble_att_cmd.c | 4 +-
net/nimble/host/src/ble_att_cmd.h | 5 +-
net/nimble/host/src/ble_att_svr.c | 10 +-
net/nimble/host/src/ble_gatt.c | 218 ++++++++++++++++++--
net/nimble/host/src/test/ble_gatt_test.c | 207 ++++++++++++++++++-
net/nimble/host/src/test/ble_hs_att_svr_test.c | 4 +-
10 files changed, 552 insertions(+), 50 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/941319ca/net/nimble/host/include/host/ble_gatt.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_gatt.h b/net/nimble/host/include/host/ble_gatt.h
index 7aa3c98..b76389e 100644
--- a/net/nimble/host/include/host/ble_gatt.h
+++ b/net/nimble/host/include/host/ble_gatt.h
@@ -19,9 +19,10 @@ typedef int ble_gatt_disc_service_fn(uint16_t conn_handle, int status,
int ble_gatt_disc_all_services(uint16_t conn_handle,
ble_gatt_disc_service_fn *cb,
void *cb_arg);
+int ble_gatt_disc_service_by_uuid(uint16_t conn_handle, void *service_uuid128,
+ ble_gatt_disc_service_fn *cb, void *cb_arg);
-void ble_gatt_rx_error(struct ble_hs_conn *conn,
- struct ble_att_error_rsp *rsp);
+void ble_gatt_rx_err(struct ble_hs_conn *conn, struct ble_att_error_rsp *rsp);
void ble_gatt_wakeup(void);
void ble_gatt_rx_mtu(struct ble_hs_conn *conn, uint16_t chan_mtu);
int ble_gatt_mtu(uint16_t conn_handle);
@@ -30,6 +31,9 @@ void ble_gatt_rx_find_info(struct ble_hs_conn *conn, int status,
void ble_gatt_rx_read_group_type_adata(struct ble_hs_conn *conn,
struct ble_att_clt_adata *adata);
void ble_gatt_rx_read_group_type_complete(struct ble_hs_conn *conn, int rc);
+void ble_gatt_rx_find_type_value_hinfo(struct ble_hs_conn *conn,
+ struct ble_att_clt_adata *adata);
+void ble_gatt_rx_find_type_value_complete(struct ble_hs_conn *conn, int rc);
int ble_gatt_find_info(uint16_t conn_handle_id, uint16_t att_start_handle,
uint16_t att_end_handle);
int ble_gatt_init(void);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/941319ca/net/nimble/host/src/ble_att.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att.c b/net/nimble/host/src/ble_att.c
index 71abd6f..afef850 100644
--- a/net/nimble/host/src/ble_att.c
+++ b/net/nimble/host/src/ble_att.c
@@ -30,11 +30,13 @@ struct ble_att_rx_dispatch_entry {
};
static struct ble_att_rx_dispatch_entry ble_att_rx_dispatch[] = {
+ { BLE_ATT_OP_ERROR_RSP, ble_att_clt_rx_error },
{ BLE_ATT_OP_MTU_REQ, ble_att_svr_rx_mtu },
{ BLE_ATT_OP_MTU_RSP, ble_att_clt_rx_mtu },
{ BLE_ATT_OP_FIND_INFO_REQ, ble_att_svr_rx_find_info },
{ BLE_ATT_OP_FIND_INFO_RSP, ble_att_clt_rx_find_info },
{ BLE_ATT_OP_FIND_TYPE_VALUE_REQ, ble_att_svr_rx_find_type_value },
+ { BLE_ATT_OP_FIND_TYPE_VALUE_RSP, ble_att_clt_rx_find_type_value },
{ BLE_ATT_OP_READ_TYPE_REQ, ble_att_svr_rx_read_type },
{ BLE_ATT_OP_READ_REQ, ble_att_svr_rx_read },
{ BLE_ATT_OP_READ_GROUP_TYPE_RSP, ble_att_clt_rx_read_group_type_rsp },
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/941319ca/net/nimble/host/src/ble_att.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att.h b/net/nimble/host/src/ble_att.h
index b8e6439..93c74c2 100644
--- a/net/nimble/host/src/ble_att.h
+++ b/net/nimble/host/src/ble_att.h
@@ -28,6 +28,7 @@ struct ble_att_mtu_cmd;
struct ble_att_read_req;
struct ble_att_read_group_type_req;
struct ble_att_read_group_type_rsp;
+struct ble_att_find_type_value_req;
#define BLE_ATT_MTU_DFLT 23 /* Also the minimum. */
#define BLE_ATT_MTU_MAX 256 /* XXX: I'm making this up! */
@@ -139,6 +140,8 @@ int ble_att_svr_rx_write(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
int ble_att_svr_init(void);
/*** @clt */
+int ble_att_clt_rx_error(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
+ struct os_mbuf **om);
int ble_att_clt_tx_mtu(struct ble_hs_conn *conn,
struct ble_att_mtu_cmd *req);
int ble_att_clt_rx_mtu(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
@@ -149,6 +152,12 @@ int ble_att_clt_tx_find_info(struct ble_hs_conn *conn,
struct ble_att_find_info_req *req);
int ble_att_clt_rx_find_info(struct ble_hs_conn *conn,
struct ble_l2cap_chan *chan, struct os_mbuf **om);
+int ble_att_clt_tx_find_type_value(struct ble_hs_conn *conn,
+ struct ble_att_find_type_value_req *req,
+ void *attribute_value, int value_len);
+int ble_att_clt_rx_find_type_value(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf **rxom);
int ble_att_clt_tx_read_group_type(struct ble_hs_conn *conn,
struct ble_att_read_group_type_req *req,
void *uuid128);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/941319ca/net/nimble/host/src/ble_att_clt.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_clt.c b/net/nimble/host/src/ble_att_clt.c
index 05684b6..20b584d 100644
--- a/net/nimble/host/src/ble_att_clt.c
+++ b/net/nimble/host/src/ble_att_clt.c
@@ -61,6 +61,28 @@ err:
}
int
+ble_att_clt_rx_error(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
+ struct os_mbuf **om)
+{
+ struct ble_att_error_rsp rsp;
+ int rc;
+
+ *om = os_mbuf_pullup(*om, BLE_ATT_ERROR_RSP_SZ);
+ if (*om == NULL) {
+ return ENOMEM;
+ }
+
+ rc = ble_att_error_rsp_parse((*om)->om_data, (*om)->om_len, &rsp);
+ if (rc != 0) {
+ return rc;
+ }
+
+ ble_gatt_rx_err(conn, &rsp);
+
+ return 0;
+}
+
+int
ble_att_clt_tx_mtu(struct ble_hs_conn *conn, struct ble_att_mtu_cmd *req)
{
struct ble_l2cap_chan *chan;
@@ -273,6 +295,104 @@ err:
}
int
+ble_att_clt_tx_find_type_value(struct ble_hs_conn *conn,
+ struct ble_att_find_type_value_req *req,
+ void *attribute_value, int value_len)
+{
+ struct ble_l2cap_chan *chan;
+ struct os_mbuf *txom;
+ int rc;
+
+ txom = NULL;
+
+ if (req->bhavq_start_handle == 0 ||
+ req->bhavq_start_handle > req->bhavq_end_handle) {
+
+ rc = EINVAL;
+ goto err;
+ }
+
+ rc = ble_att_clt_prep_req(conn, &chan, &txom,
+ BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ);
+ if (rc != 0) {
+ goto err;
+ }
+
+ rc = ble_att_find_type_value_req_write(txom->om_data, txom->om_len, req);
+ if (rc != 0) {
+ goto err;
+ }
+
+ rc = os_mbuf_append(txom, attribute_value, value_len);
+ if (rc != 0) {
+ rc = EMSGSIZE;
+ goto err;
+ }
+
+ rc = ble_l2cap_tx(chan, txom);
+ txom = NULL;
+ if (rc != 0) {
+ goto err;
+ }
+
+ return 0;
+
+err:
+ os_mbuf_free_chain(txom);
+ return rc;
+}
+
+static int
+ble_att_clt_parse_handles_info(struct os_mbuf **om,
+ struct ble_att_clt_adata *adata)
+{
+ *om = os_mbuf_pullup(*om, BLE_ATT_FIND_TYPE_VALUE_HINFO_BASE_SZ);
+ if (*om == NULL) {
+ return ENOMEM;
+ }
+
+ adata->att_handle = le16toh((*om)->om_data + 0);
+ adata->end_group_handle = le16toh((*om)->om_data + 2);
+ adata->value_len = 0;
+ adata->value = NULL;
+
+ return 0;
+}
+
+int
+ble_att_clt_rx_find_type_value(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct os_mbuf **rxom)
+{
+ struct ble_att_clt_adata adata;
+ int rc;
+
+ /* Reponse consists of a one-byte opcode (already verified) and a variable
+ * length Handles Information List field. Strip the opcode from the
+ * response.
+ */
+ os_mbuf_adj(*rxom, BLE_ATT_FIND_TYPE_VALUE_RSP_BASE_SZ);
+
+ /* Parse the Handles Information List field, passing each entry to the
+ * GATT.
+ */
+ while (OS_MBUF_PKTLEN(*rxom) > 0) {
+ rc = ble_att_clt_parse_handles_info(rxom, &adata);
+ if (rc != 0) {
+ break;
+ }
+
+ ble_gatt_rx_find_type_value_hinfo(conn, &adata);
+ os_mbuf_adj(*rxom, BLE_ATT_FIND_TYPE_VALUE_HINFO_BASE_SZ);
+ }
+
+ /* Notify GATT that the full response has been parsed. */
+ ble_gatt_rx_find_type_value_complete(conn, rc);
+
+ return 0;
+}
+
+int
ble_att_clt_tx_read_group_type(struct ble_hs_conn *conn,
struct ble_att_read_group_type_req *req,
void *uuid128)
@@ -348,31 +468,32 @@ ble_att_clt_rx_read_group_type_rsp(struct ble_hs_conn *conn,
*rxom = os_mbuf_pullup(*rxom, BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ);
if (*rxom == NULL) {
- return ENOMEM;
+ rc = ENOMEM;
+ goto done;
}
rc = ble_att_read_group_type_rsp_parse((*rxom)->om_data, (*rxom)->om_len,
&rsp);
if (rc != 0) {
- return rc;
+ goto done;
}
+ /* Strip the base from the front of the response. */
os_mbuf_adj(*rxom, BLE_ATT_READ_GROUP_TYPE_RSP_BASE_SZ);
- /* XXX: Verify group handle is valid. */
-
+ /* Parse the Attribute Data List field, passing each entry to the GATT. */
while (OS_MBUF_PKTLEN(*rxom) > 0) {
rc = ble_att_clt_parse_attribute_data(rxom, rsp.bhagp_length, &adata);
if (rc != 0) {
- break;
+ goto done;
}
- /* Pass attribute data to GATT callback. */
ble_gatt_rx_read_group_type_adata(conn, &adata);
-
os_mbuf_adj(*rxom, rsp.bhagp_length);
}
+done:
+ /* Notify GATT that the response is done being parsed. */
ble_gatt_rx_read_group_type_complete(conn, rc);
return 0;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/941319ca/net/nimble/host/src/ble_att_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_cmd.c b/net/nimble/host/src/ble_att_cmd.c
index 87ade7b..09718d8 100644
--- a/net/nimble/host/src/ble_att_cmd.c
+++ b/net/nimble/host/src/ble_att_cmd.c
@@ -206,7 +206,7 @@ ble_att_find_type_value_req_parse(void *payload, int len,
{
uint8_t *u8ptr;
- if (len < BLE_ATT_FIND_TYPE_VALUE_REQ_MIN_SZ) {
+ if (len < BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ) {
return EMSGSIZE;
}
@@ -229,7 +229,7 @@ ble_att_find_type_value_req_write(void *payload, int len,
{
uint8_t *u8ptr;
- if (len < BLE_ATT_FIND_TYPE_VALUE_REQ_MIN_SZ) {
+ if (len < BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ) {
return EMSGSIZE;
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/941319ca/net/nimble/host/src/ble_att_cmd.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_cmd.h b/net/nimble/host/src/ble_att_cmd.h
index 443e684..3b4cdf6 100644
--- a/net/nimble/host/src/ble_att_cmd.h
+++ b/net/nimble/host/src/ble_att_cmd.h
@@ -97,7 +97,7 @@ struct ble_att_find_info_rsp {
* | Attribute Type | 2 |
* | Attribute Value | 0 to (ATT_MTU-7) |
*/
-#define BLE_ATT_FIND_TYPE_VALUE_REQ_MIN_SZ 7
+#define BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ 7
struct ble_att_find_type_value_req {
uint16_t bhavq_start_handle;
uint16_t bhavq_end_handle;
@@ -110,7 +110,8 @@ struct ble_att_find_type_value_req {
* | Attribute Opcode | 1 |
* | Information Data | 4 to (ATT_MTU-1) |
*/
-#define BLE_ATT_FIND_TYPE_VALUE_RSP_MIN_SZ 1
+#define BLE_ATT_FIND_TYPE_VALUE_RSP_BASE_SZ 1
+#define BLE_ATT_FIND_TYPE_VALUE_HINFO_BASE_SZ 4
/**
* | Parameter | Size (octets) |
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/941319ca/net/nimble/host/src/ble_att_svr.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_svr.c b/net/nimble/host/src/ble_att_svr.c
index 90d3e3b..25f9cb8 100644
--- a/net/nimble/host/src/ble_att_svr.c
+++ b/net/nimble/host/src/ble_att_svr.c
@@ -734,7 +734,7 @@ ble_att_svr_fill_type_value(struct ble_att_find_type_value_req *req,
goto done;
}
rc = os_mbuf_memcmp(rxom,
- BLE_ATT_FIND_TYPE_VALUE_REQ_MIN_SZ,
+ BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ,
arg.aha_read.attr_data,
arg.aha_read.attr_len);
if (rc == 0) {
@@ -745,10 +745,10 @@ ble_att_svr_fill_type_value(struct ble_att_find_type_value_req *req,
if (match) {
rc = ble_att_svr_fill_type_value_match(txom, &first, &prev,
- ha->ha_handle_id, mtu);
+ ha->ha_handle_id, mtu);
} else {
rc = ble_att_svr_fill_type_value_no_match(txom, &first, &prev,
- mtu);
+ mtu);
}
if (rc == 0) {
@@ -774,7 +774,7 @@ done:
ble_att_svr_list_unlock();
any_entries = OS_MBUF_PKTHDR(txom)->omp_len >
- BLE_ATT_FIND_TYPE_VALUE_RSP_MIN_SZ;
+ BLE_ATT_FIND_TYPE_VALUE_RSP_BASE_SZ;
if (rc == 0 && !any_entries) {
return BLE_ATT_ERR_ATTR_NOT_FOUND;
} else {
@@ -820,7 +820,7 @@ ble_att_svr_rx_find_type_value(struct ble_hs_conn *conn,
}
/* Write the response base at the start of the buffer. */
- buf = os_mbuf_extend(txom, BLE_ATT_FIND_TYPE_VALUE_RSP_MIN_SZ);
+ buf = os_mbuf_extend(txom, BLE_ATT_FIND_TYPE_VALUE_RSP_BASE_SZ);
if (buf == NULL) {
rc = BLE_ATT_ERR_INSUFFICIENT_RES;
goto err;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/941319ca/net/nimble/host/src/ble_gatt.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gatt.c b/net/nimble/host/src/ble_gatt.c
index f472730..e357240 100644
--- a/net/nimble/host/src/ble_gatt.c
+++ b/net/nimble/host/src/ble_gatt.c
@@ -55,6 +55,13 @@ struct ble_gatt_entry {
ble_gatt_disc_service_fn *cb;
void *cb_arg;
} disc_all_services;
+
+ struct {
+ uint8_t service_uuid[16];
+ uint16_t prev_handle;
+ ble_gatt_disc_service_fn *cb;
+ void *cb_arg;
+ } disc_service_uuid;
};
};
@@ -62,18 +69,50 @@ struct ble_gatt_entry {
#define BLE_GATT_OP_MTU 0
#define BLE_GATT_OP_FIND_INFO 1
#define BLE_GATT_OP_DISC_ALL_SERVICES 2
-#define BLE_GATT_OP_MAX 3
+#define BLE_GATT_OP_DISC_SERVICE_UUID 3
+#define BLE_GATT_OP_MAX 4
typedef int ble_gatt_kick_fn(struct ble_gatt_entry *entry);
+typedef int ble_gatt_rx_err_fn(struct ble_gatt_entry *entry,
+ struct ble_hs_conn *conn,
+ struct ble_att_error_rsp *rsp);
static int ble_gatt_kick_mtu(struct ble_gatt_entry *entry);
static int ble_gatt_kick_find_info(struct ble_gatt_entry *entry);
static int ble_gatt_kick_disc_all_services(struct ble_gatt_entry *entry);
+static int ble_gatt_kick_disc_service_uuid(struct ble_gatt_entry *entry);
+
+static int ble_gatt_rx_err_disc_all_services(struct ble_gatt_entry *entry,
+ struct ble_hs_conn *conn,
+ struct ble_att_error_rsp *rsp);
+static int ble_gatt_rx_err_disc_service_uuid(struct ble_gatt_entry *entry,
+ struct ble_hs_conn *conn,
+ struct ble_att_error_rsp *rsp);
+
+struct ble_gatt_dispatch_entry {
+ ble_gatt_kick_fn *kick_cb;
+ ble_gatt_rx_err_fn *rx_err_cb;
+};
-static ble_gatt_kick_fn *ble_gatt_kick_fns[BLE_GATT_OP_MAX] = {
- [BLE_GATT_OP_MTU] = ble_gatt_kick_mtu,
- [BLE_GATT_OP_FIND_INFO] = ble_gatt_kick_find_info,
- [BLE_GATT_OP_DISC_ALL_SERVICES] = ble_gatt_kick_disc_all_services,
+static const struct ble_gatt_dispatch_entry
+ ble_gatt_dispatch[BLE_GATT_OP_MAX] = {
+
+ [BLE_GATT_OP_MTU] = {
+ .kick_cb = ble_gatt_kick_mtu,
+ .rx_err_cb = NULL,
+ },
+ [BLE_GATT_OP_FIND_INFO] = {
+ .kick_cb = ble_gatt_kick_find_info,
+ .rx_err_cb = NULL,
+ },
+ [BLE_GATT_OP_DISC_ALL_SERVICES] = {
+ .kick_cb = ble_gatt_kick_disc_all_services,
+ .rx_err_cb = ble_gatt_rx_err_disc_all_services,
+ },
+ [BLE_GATT_OP_DISC_SERVICE_UUID] = {
+ .kick_cb = ble_gatt_kick_disc_service_uuid,
+ .rx_err_cb = ble_gatt_rx_err_disc_service_uuid,
+ },
};
#define BLE_GATT_ENTRY_F_PENDING 0x01
@@ -85,6 +124,13 @@ static struct os_mempool ble_gatt_entry_pool;
static STAILQ_HEAD(, ble_gatt_entry) ble_gatt_list;
+static const struct ble_gatt_dispatch_entry *
+ble_gatt_dispatch_get(uint8_t op)
+{
+ assert(op < BLE_GATT_OP_MAX);
+ return ble_gatt_dispatch + op;
+}
+
static struct ble_gatt_entry *
ble_gatt_entry_alloc(void)
{
@@ -294,9 +340,36 @@ ble_gatt_kick_disc_all_services(struct ble_gatt_entry *entry)
return 0;
}
+static int
+ble_gatt_kick_disc_service_uuid(struct ble_gatt_entry *entry)
+{
+ struct ble_att_find_type_value_req req;
+ struct ble_hs_conn *conn;
+ int rc;
+
+ conn = ble_hs_conn_find(entry->conn_handle);
+ if (conn == NULL) {
+ return ENOTCONN;
+ }
+
+ req.bhavq_start_handle = entry->disc_service_uuid.prev_handle + 1;
+ req.bhavq_end_handle = 0xffff;
+ req.bhavq_attr_type = BLE_ATT_UUID_PRIMARY_SERVICE;
+
+ rc = ble_att_clt_tx_find_type_value(conn, &req,
+ entry->disc_service_uuid.service_uuid,
+ 16);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
void
ble_gatt_wakeup(void)
{
+ const struct ble_gatt_dispatch_entry *dispatch;
struct ble_gatt_entry *entry;
struct ble_gatt_entry *prev;
struct ble_gatt_entry *next;
@@ -311,9 +384,8 @@ ble_gatt_wakeup(void)
next = STAILQ_NEXT(entry, next);
if (entry->flags & BLE_GATT_ENTRY_F_PENDING) {
- assert(entry->op < BLE_GATT_OP_MAX);
-
- rc = ble_gatt_kick_fns[entry->op](entry);
+ dispatch = ble_gatt_dispatch_get(entry->op);
+ rc = dispatch->kick_cb(entry);
if (rc == 0) {
ble_gatt_entry_set_expecting(entry, prev);
} else {
@@ -326,9 +398,52 @@ ble_gatt_wakeup(void)
}
}
+static int
+ble_gatt_rx_err_disc_all_services(struct ble_gatt_entry *entry,
+ struct ble_hs_conn *conn,
+ struct ble_att_error_rsp *rsp)
+{
+ uint8_t status;
+
+ if (rsp->bhaep_error_code == BLE_ATT_ERR_ATTR_NOT_FOUND) {
+ /* Discovery is complete. */
+ status = 0;
+ } else {
+ /* Discovery failure. */
+ status = rsp->bhaep_error_code;
+ }
+
+ entry->disc_all_services.cb(conn->bhc_handle, status, NULL,
+ entry->disc_all_services.cb_arg);
+
+ return 0;
+}
+
+static int
+ble_gatt_rx_err_disc_service_uuid(struct ble_gatt_entry *entry,
+ struct ble_hs_conn *conn,
+ struct ble_att_error_rsp *rsp)
+{
+ uint8_t status;
+
+ if (rsp->bhaep_error_code == BLE_ATT_ERR_ATTR_NOT_FOUND) {
+ /* Discovery is complete. */
+ status = 0;
+ } else {
+ /* Discovery failure. */
+ status = rsp->bhaep_error_code;
+ }
+
+ entry->disc_service_uuid.cb(conn->bhc_handle, status, NULL,
+ entry->disc_service_uuid.cb_arg);
+
+ return 0;
+}
+
void
-ble_gatt_rx_error(struct ble_hs_conn *conn, struct ble_att_error_rsp *rsp)
+ble_gatt_rx_err(struct ble_hs_conn *conn, struct ble_att_error_rsp *rsp)
{
+ const struct ble_gatt_dispatch_entry *dispatch;
struct ble_gatt_entry *entry;
struct ble_gatt_entry *prev;
@@ -338,19 +453,10 @@ ble_gatt_rx_error(struct ble_hs_conn *conn, struct ble_att_error_rsp *rsp)
return;
}
- switch (entry->op) {
- case BLE_GATT_OP_NONE:
- case BLE_GATT_OP_MTU:
- break;
-
- case BLE_GATT_OP_FIND_INFO:
- /* XXX: Branch on error status. */
- break;
+ dispatch = ble_gatt_dispatch_get(entry->op);
+ dispatch->rx_err_cb(entry, conn, rsp);
- default:
- assert(0);
- break;
- }
+ ble_gatt_entry_remove_free(entry, prev);
}
int
@@ -508,6 +614,57 @@ ble_gatt_rx_read_group_type_complete(struct ble_hs_conn *conn, int rc)
}
}
+void
+ble_gatt_rx_find_type_value_hinfo(struct ble_hs_conn *conn,
+ struct ble_att_clt_adata *adata)
+{
+ struct ble_gatt_service service;
+ struct ble_gatt_entry *entry;
+ struct ble_gatt_entry *prev;
+ int rc;
+
+ entry = ble_gatt_find(conn->bhc_handle, BLE_GATT_OP_DISC_SERVICE_UUID, 1,
+ &prev);
+ if (entry == NULL) {
+ /* Not expecting a response from this device. */
+ return;
+ }
+
+ service.start_handle = adata->att_handle;
+ service.end_handle = adata->end_group_handle;
+ memcpy(service.uuid128, entry->disc_service_uuid.service_uuid, 16);
+
+ rc = entry->disc_service_uuid.cb(conn->bhc_handle, 0, &service,
+ entry->disc_service_uuid.cb_arg);
+ if (rc != 0) {
+ ble_gatt_entry_remove_free(entry, prev);
+ }
+}
+
+void
+ble_gatt_rx_find_type_value_complete(struct ble_hs_conn *conn, int rc)
+{
+ struct ble_gatt_entry *entry;
+ struct ble_gatt_entry *prev;
+
+ entry = ble_gatt_find(conn->bhc_handle, BLE_GATT_OP_DISC_SERVICE_UUID, 1,
+ &prev);
+ if (entry == NULL) {
+ /* Not expecting a response from this device. */
+ return;
+ }
+
+ if (rc != 0 || entry->disc_service_uuid.prev_handle == 0xffff) {
+ /* Error or all services discovered. */
+ entry->disc_service_uuid.cb(conn->bhc_handle, rc, NULL,
+ entry->disc_service_uuid.cb_arg);
+ ble_gatt_entry_remove_free(entry, prev);
+ } else {
+ /* Send follow-up request. */
+ ble_gatt_entry_set_pending(entry);
+ }
+}
+
int
ble_gatt_disc_all_services(uint16_t conn_handle, ble_gatt_disc_service_fn *cb,
void *cb_arg)
@@ -527,6 +684,25 @@ ble_gatt_disc_all_services(uint16_t conn_handle, ble_gatt_disc_service_fn *cb,
return 0;
}
+int
+ble_gatt_disc_service_by_uuid(uint16_t conn_handle, void *service_uuid128,
+ ble_gatt_disc_service_fn *cb, void *cb_arg)
+{
+ struct ble_gatt_entry *entry;
+ int rc;
+
+ rc = ble_gatt_new_entry(conn_handle, &entry);
+ if (rc != 0) {
+ return rc;
+ }
+ entry->op = BLE_GATT_OP_DISC_SERVICE_UUID;
+ memcpy(entry->disc_service_uuid.service_uuid, service_uuid128, 16);
+ entry->disc_service_uuid.prev_handle = 0x0000;
+ entry->disc_service_uuid.cb = cb;
+ entry->disc_service_uuid.cb_arg = cb_arg;
+
+ return 0;
+}
int
ble_gatt_init(void)
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/941319ca/net/nimble/host/src/test/ble_gatt_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatt_test.c b/net/nimble/host/src/test/ble_gatt_test.c
index f4d23aa..ad9b4d0 100644
--- a/net/nimble/host/src/test/ble_gatt_test.c
+++ b/net/nimble/host/src/test/ble_gatt_test.c
@@ -36,8 +36,17 @@ struct ble_gatt_test_service {
static struct ble_gatt_service
ble_gatt_test_services[BLE_GATT_TEST_MAX_SERVICES];
static int ble_gatt_test_num_services;
+static int ble_gatt_test_rx_complete;
-int
+static void
+ble_gatt_test_init(void)
+{
+ ble_hs_test_util_init();
+ ble_gatt_test_num_services = 0;
+ ble_gatt_test_rx_complete = 0;
+}
+
+static int
ble_gatt_test_misc_service_length(struct ble_gatt_test_service *service)
{
if (service->uuid16 != 0) {
@@ -47,6 +56,32 @@ ble_gatt_test_misc_service_length(struct ble_gatt_test_service *service)
}
}
+static void
+ble_gatt_test_misc_rx_err_rsp(struct ble_hs_conn *conn, uint8_t req_op,
+ uint8_t error_code)
+{
+ struct ble_att_error_rsp rsp;
+ struct ble_l2cap_chan *chan;
+ uint8_t buf[BLE_ATT_ERROR_RSP_SZ];
+ int rc;
+
+ /* Send the pending ATT Request. */
+ ble_gatt_wakeup();
+
+ rsp.bhaep_req_op = req_op;
+ rsp.bhaep_handle = conn->bhc_handle;
+ rsp.bhaep_error_code = error_code;
+
+ rc = ble_att_error_rsp_write(buf, sizeof buf, &rsp);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
+ TEST_ASSERT_FATAL(chan != NULL);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, sizeof buf);
+ TEST_ASSERT(rc == 0);
+}
+
static int
ble_gatt_test_misc_rx_disc_services_rsp_once(
struct ble_hs_conn *conn, struct ble_gatt_test_service *services)
@@ -116,6 +151,67 @@ ble_gatt_test_misc_rx_disc_services_rsp(struct ble_hs_conn *conn,
services + idx);
idx += count;
}
+
+ if (services[idx - 1].start_handle != 0xffff) {
+ ble_gatt_test_misc_rx_err_rsp(conn, BLE_ATT_OP_READ_GROUP_TYPE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND);
+ }
+}
+
+static int
+ble_gatt_test_misc_rx_disc_uuid_rsp_once(
+ struct ble_hs_conn *conn, struct ble_gatt_test_service *services)
+{
+ struct ble_l2cap_chan *chan;
+ uint8_t buf[1024];
+ int off;
+ int rc;
+ int i;
+
+ /* Send the pending ATT Find By Type Value Request. */
+ ble_gatt_wakeup();
+
+ buf[0] = BLE_ATT_OP_FIND_TYPE_VALUE_RSP;
+ off = BLE_ATT_FIND_TYPE_VALUE_RSP_BASE_SZ;
+ for (i = 0; ; i++) {
+ if (services[i].start_handle == 0) {
+ /* No more services. */
+ break;
+ }
+
+ htole16(buf + off, services[i].start_handle);
+ off += 2;
+
+ htole16(buf + off, services[i].end_handle);
+ off += 2;
+ }
+
+ chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
+ TEST_ASSERT_FATAL(chan != NULL);
+
+ rc = ble_hs_test_util_l2cap_rx_payload_flat(conn, chan, buf, off);
+ TEST_ASSERT(rc == 0);
+
+ return i;
+}
+
+static void
+ble_gatt_test_misc_rx_disc_uuid_rsp(struct ble_hs_conn *conn,
+ struct ble_gatt_test_service *services)
+{
+ int count;
+ int idx;
+
+ idx = 0;
+ while (services[idx].start_handle != 0) {
+ count = ble_gatt_test_misc_rx_disc_uuid_rsp_once(conn, services + idx);
+ idx += count;
+ }
+
+ if (services[idx - 1].start_handle != 0xffff) {
+ ble_gatt_test_misc_rx_err_rsp(conn, BLE_ATT_OP_FIND_TYPE_VALUE_REQ,
+ BLE_ATT_ERR_ATTR_NOT_FOUND);
+ }
}
static void
@@ -141,16 +237,21 @@ ble_gatt_test_misc_verify_services(struct ble_gatt_test_service *services)
}
TEST_ASSERT(i == ble_gatt_test_num_services);
+ TEST_ASSERT(ble_gatt_test_rx_complete);
}
static int
ble_gatt_test_misc_disc_cb(uint16_t conn_handle, int status,
struct ble_gatt_service *service, void *arg)
{
- TEST_ASSERT_FATAL(ble_gatt_test_num_services < BLE_GATT_TEST_MAX_SERVICES);
TEST_ASSERT(status == 0);
+ TEST_ASSERT(!ble_gatt_test_rx_complete);
- if (status == 0) {
+ if (service == NULL) {
+ ble_gatt_test_rx_complete = 1;
+ } else {
+ TEST_ASSERT_FATAL(ble_gatt_test_num_services <
+ BLE_GATT_TEST_MAX_SERVICES);
ble_gatt_test_services[ble_gatt_test_num_services++] = *service;
}
@@ -163,8 +264,7 @@ ble_gatt_test_misc_good_disc_services(struct ble_gatt_test_service *services)
struct ble_hs_conn *conn;
int rc;
- ble_hs_test_util_init();
- ble_gatt_test_num_services = 0;
+ ble_gatt_test_init();
conn = ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}));
@@ -175,7 +275,29 @@ ble_gatt_test_misc_good_disc_services(struct ble_gatt_test_service *services)
ble_gatt_test_misc_verify_services(services);
}
-TEST_CASE(ble_gatt_test_1)
+static void
+ble_gatt_test_misc_good_disc_uuid(struct ble_gatt_test_service *services)
+{
+ struct ble_hs_conn *conn;
+ int rc;
+
+ ble_gatt_test_init();
+
+ conn = ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}));
+
+ if (services[0].uuid16 != 0) {
+ rc = ble_hs_uuid_from_16bit(services[0].uuid16, services[0].uuid128);
+ TEST_ASSERT_FATAL(rc == 0);
+ }
+ rc = ble_gatt_disc_service_by_uuid(2, services[0].uuid128,
+ ble_gatt_test_misc_disc_cb, NULL);
+ TEST_ASSERT(rc == 0);
+
+ ble_gatt_test_misc_rx_disc_uuid_rsp(conn, services);
+ ble_gatt_test_misc_verify_services(services);
+}
+
+TEST_CASE(ble_gatt_test_disc_all_services)
{
/*** One 128-bit service. */
ble_gatt_test_misc_good_disc_services((struct ble_gatt_test_service[]) {
@@ -207,13 +329,80 @@ TEST_CASE(ble_gatt_test_1)
{ 0 }
});
- /* XXX: Test multiple responses. */
- /* XXX: Test 16-bit UUIDs. */
+ /*** End with handle 0xffff. */
+ ble_gatt_test_misc_good_disc_services((struct ble_gatt_test_service[]) {
+ { 1, 5, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, },
+ { 7, 0xffff, 0, {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }, },
+ });
+}
+
+TEST_CASE(ble_gatt_test_disc_service_uuid)
+{
+ /*** 128-bit service; one entry. */
+ ble_gatt_test_misc_good_disc_uuid((struct ble_gatt_test_service[]) {
+ { 1, 5, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, },
+ { 0 }
+ });
+
+ /*** 128-bit service; two entries. */
+ ble_gatt_test_misc_good_disc_uuid((struct ble_gatt_test_service[]) {
+ { 1, 5, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, },
+ { 8, 43, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, },
+ { 0 }
+ });
+
+ /*** 128-bit service; five entries. */
+ ble_gatt_test_misc_good_disc_uuid((struct ble_gatt_test_service[]) {
+ { 1, 5, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, },
+ { 8, 43, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, },
+ { 67, 100, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, },
+ { 102, 103, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, },
+ { 262, 900, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, },
+ { 0 }
+ });
+
+ /*** 128-bit service; end with handle 0xffff. */
+ ble_gatt_test_misc_good_disc_uuid((struct ble_gatt_test_service[]) {
+ { 1, 5, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, },
+ { 7, 0xffff, 0, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, },
+ { 0 }
+ });
+
+ /*** 16-bit service; one entry. */
+ ble_gatt_test_misc_good_disc_uuid((struct ble_gatt_test_service[]) {
+ { 1, 5, 0x1234 },
+ { 0 }
+ });
+
+ /*** 16-bit service; two entries. */
+ ble_gatt_test_misc_good_disc_uuid((struct ble_gatt_test_service[]) {
+ { 1, 5, 0x1234 },
+ { 85, 243, 0x1234 },
+ { 0 }
+ });
+
+ /*** 16-bit service; five entries. */
+ ble_gatt_test_misc_good_disc_uuid((struct ble_gatt_test_service[]) {
+ { 1, 5, 0x1234 },
+ { 85, 243, 0x1234 },
+ { 382, 383, 0x1234 },
+ { 562, 898, 0x1234 },
+ { 902, 984, 0x1234 },
+ { 0 }
+ });
+
+ /*** 16-bit service; end with handle 0xffff. */
+ ble_gatt_test_misc_good_disc_uuid((struct ble_gatt_test_service[]) {
+ { 1, 5, 0x1234 },
+ { 9, 0xffff, 0x1234 },
+ { 0 }
+ });
}
TEST_SUITE(ble_gatt_suite)
{
- ble_gatt_test_1();
+ ble_gatt_test_disc_all_services();
+ ble_gatt_test_disc_service_uuid();
}
int
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/941319ca/net/nimble/host/src/test/ble_hs_att_svr_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_att_svr_test.c b/net/nimble/host/src/test/ble_hs_att_svr_test.c
index 37f3f11..0b1d928 100644
--- a/net/nimble/host/src/test/ble_hs_att_svr_test.c
+++ b/net/nimble/host/src/test/ble_hs_att_svr_test.c
@@ -622,7 +622,7 @@ TEST_CASE(ble_att_svr_test_find_type_value)
struct ble_att_find_type_value_req req;
struct ble_l2cap_chan *chan;
struct ble_hs_conn *conn;
- uint8_t buf[BLE_ATT_FIND_TYPE_VALUE_REQ_MIN_SZ + 2];
+ uint8_t buf[BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ + 2];
uint16_t handle1;
uint16_t handle2;
uint16_t handle3;
@@ -649,7 +649,7 @@ TEST_CASE(ble_att_svr_test_find_type_value)
/* One-time write of the attribute value at the end of the request. */
ble_att_svr_test_attr_r_1 = (uint8_t[]){0x99, 0x99};
ble_att_svr_test_attr_r_1_len = 2;
- memcpy(buf + BLE_ATT_FIND_TYPE_VALUE_REQ_MIN_SZ,
+ memcpy(buf + BLE_ATT_FIND_TYPE_VALUE_REQ_BASE_SZ,
ble_att_svr_test_attr_r_1,
ble_att_svr_test_attr_r_1_len);