Bluetooth: GATT: Add bt_gatt_discover_descriptor
This adds bt_gatt_discover_descriptors which can used to discover all descriptors in the given range. Change-Id: Idf93852ef9d8ba3bfce20dc0b95f4e11aa0dc73d Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
b672324c16
commit
e0792a1ba2
2 changed files with 139 additions and 6 deletions
|
@ -692,6 +692,23 @@ int bt_gatt_discover(struct bt_conn *conn,
|
||||||
int bt_gatt_discover_characteristic(struct bt_conn *conn,
|
int bt_gatt_discover_characteristic(struct bt_conn *conn,
|
||||||
struct bt_gatt_discover_params *params);
|
struct bt_gatt_discover_params *params);
|
||||||
|
|
||||||
|
/** @brief Discover Descriptor
|
||||||
|
*
|
||||||
|
* This procedure is used by a client to discover descriptors on a server.
|
||||||
|
* Note: In case the UUID is set in the parameter it will be matched against
|
||||||
|
* the attributes found before calling the function callback.
|
||||||
|
*
|
||||||
|
* For each attribute found the callback is called which can then decide
|
||||||
|
* whether to continue discovering or stop.
|
||||||
|
*
|
||||||
|
* @param conn Connection object.
|
||||||
|
* @param params Discover parameters.
|
||||||
|
*
|
||||||
|
* @return 0 in case of success or negative value in case of error.
|
||||||
|
*/
|
||||||
|
int bt_gatt_discover_descriptor(struct bt_conn *conn,
|
||||||
|
struct bt_gatt_discover_params *params);
|
||||||
|
|
||||||
/** @brief Cancel GATT pending request
|
/** @brief Cancel GATT pending request
|
||||||
*
|
*
|
||||||
* @param conn Connection object.
|
* @param conn Connection object.
|
||||||
|
|
|
@ -680,12 +680,6 @@ static void att_read_type_rsp(struct bt_conn *conn, uint8_t err,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next characteristic shall be after current value handle */
|
|
||||||
params->start_handle = handle;
|
|
||||||
if (params->start_handle < UINT16_MAX) {
|
|
||||||
params->start_handle++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stop if over the requested range */
|
/* Stop if over the requested range */
|
||||||
if (params->start_handle >= params->end_handle) {
|
if (params->start_handle >= params->end_handle) {
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -734,6 +728,128 @@ int bt_gatt_discover_characteristic(struct bt_conn *conn,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void att_find_info_rsp(struct bt_conn *conn, uint8_t err,
|
||||||
|
const void *pdu, uint16_t length,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
const struct bt_att_find_info_rsp *rsp = pdu;
|
||||||
|
struct bt_gatt_discover_params *params = user_data;
|
||||||
|
struct bt_uuid uuid;
|
||||||
|
uint16_t handle = 0;
|
||||||
|
uint8_t len;
|
||||||
|
union {
|
||||||
|
const struct bt_att_info_16 *i16;
|
||||||
|
const struct bt_att_info_128 *i128;
|
||||||
|
} info;
|
||||||
|
|
||||||
|
BT_DBG("err 0x%02x\n", err);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Data can be either in UUID16 or UUID128 */
|
||||||
|
switch (rsp->format) {
|
||||||
|
case BT_ATT_INFO_16:
|
||||||
|
uuid.type = BT_UUID_16;
|
||||||
|
len = sizeof(info.i16);
|
||||||
|
break;
|
||||||
|
case BT_ATT_INFO_128:
|
||||||
|
uuid.type = BT_UUID_128;
|
||||||
|
len = sizeof(info.i128);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BT_ERR("Invalid format %u\n", rsp->format);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse descriptors found */
|
||||||
|
for (length--, pdu = rsp->info; length >= len;
|
||||||
|
length -= len, pdu += len) {
|
||||||
|
const struct bt_gatt_attr *attr;
|
||||||
|
|
||||||
|
info.i16 = pdu;
|
||||||
|
handle = sys_le16_to_cpu(info.i16->handle);
|
||||||
|
|
||||||
|
switch (uuid.type) {
|
||||||
|
case BT_UUID_16:
|
||||||
|
uuid.u16 = sys_le16_to_cpu(info.i16->uuid);
|
||||||
|
break;
|
||||||
|
case BT_UUID_128:
|
||||||
|
memcpy(uuid.u128, info.i128->uuid, sizeof(uuid.u128));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BT_DBG("handle 0x%04x\n", handle);
|
||||||
|
|
||||||
|
/* Skip if UUID is set but doesn't match */
|
||||||
|
if (params->uuid && bt_uuid_cmp(&uuid, params->uuid)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr = (&(struct bt_gatt_attr)
|
||||||
|
BT_GATT_DESCRIPTOR(handle, &uuid, 0, NULL, NULL, NULL));
|
||||||
|
|
||||||
|
if (params->func(attr, params) == BT_GATT_ITER_STOP) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop if could not parse the whole PDU */
|
||||||
|
if (length > 0) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next characteristic shall be after current value handle */
|
||||||
|
params->start_handle = handle;
|
||||||
|
if (params->start_handle < UINT16_MAX) {
|
||||||
|
params->start_handle++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop if over the requested range */
|
||||||
|
if (params->start_handle >= params->end_handle) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Continue to the next range */
|
||||||
|
if (!bt_gatt_discover_descriptor(conn, params)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (params->destroy) {
|
||||||
|
params->destroy(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int bt_gatt_discover_descriptor(struct bt_conn *conn,
|
||||||
|
struct bt_gatt_discover_params *params)
|
||||||
|
{
|
||||||
|
struct bt_buf *buf;
|
||||||
|
struct bt_att_find_info_req *req;
|
||||||
|
|
||||||
|
if (!conn || !params->func || !params->start_handle ||
|
||||||
|
!params->end_handle) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = bt_att_create_pdu(conn, BT_ATT_OP_FIND_INFO_REQ, sizeof(*req));
|
||||||
|
if (!buf) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
req = bt_buf_add(buf, sizeof(*req));
|
||||||
|
req->start_handle = sys_cpu_to_le16(params->start_handle);
|
||||||
|
req->end_handle = sys_cpu_to_le16(params->end_handle);
|
||||||
|
|
||||||
|
BT_DBG("start_handle 0x%04x end_handle 0x%04x\n", params->start_handle,
|
||||||
|
params->end_handle);
|
||||||
|
|
||||||
|
bt_att_send(conn, buf, att_find_info_rsp, params, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void bt_gatt_cancel(struct bt_conn *conn)
|
void bt_gatt_cancel(struct bt_conn *conn)
|
||||||
{
|
{
|
||||||
bt_att_cancel(conn);
|
bt_att_cancel(conn);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue