Bluetooth: SDP: Server: Find the attributes in the record

Retrieves the record specified by the record handle, go over each
attribute in the record and check whether the attribute is there
in the list provided in the request.

Change-Id: I8f09e0fbb7811a20bb25dc0029cd7c79a9345c88
Signed-off-by: Kaustav Dey Biswas <kaustav.d.biswas@intel.com>
Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com>
This commit is contained in:
Kaustav Dey Biswas 2017-03-02 21:38:46 +05:30 committed by Johan Hedberg
commit 61706ca021

View file

@ -24,6 +24,8 @@
#define SDP_CHAN(_ch) CONTAINER_OF(_ch, struct bt_sdp, chan.chan)
#define IN_RANGE(val, min, max) (val >= min && val <= max)
#define SDP_DATA_MTU 200
#define SDP_MTU (SDP_DATA_MTU + sizeof(struct bt_sdp_hdr))
@ -81,6 +83,27 @@ enum {
BT_SDP_ITER_CONTINUE,
};
struct select_attrs_data {
struct bt_sdp_record *rec;
struct bt_sdp *sdp;
uint32_t *filter;
uint16_t max_att_len;
uint8_t num_filters;
};
/* @typedef bt_sdp_attr_func_t
* @brief SDP attribute iterator callback.
*
* @param attr Attribute found.
* @param att_idx Index of the found attribute in the attribute database.
* @param user_data Data given.
*
* @return BT_SDP_ITER_CONTINUE if should continue to the next attribute
* or BT_SDP_ITER_STOP to stop.
*/
typedef uint8_t (*bt_sdp_attr_func_t)(struct bt_sdp_attribute *attr,
uint8_t att_idx, void *user_data);
/* @typedef bt_sdp_svc_func_t
* @brief SDP service record iterator callback.
*
@ -645,7 +668,108 @@ static uint16_t sdp_svc_search_req(struct bt_sdp *sdp, struct net_buf *buf,
return 0;
}
/* @brief Extracts the attribute search list from a net_buf
/* @brief SDP attribute iterator.
*
* Iterate over attributes of a service record from a starting index.
*
* @param record Service record whose attributes are to be iterated over.
* @param idx Index in the attribute list from where to start.
* @param func Callback function.
* @param user_data Data to pass to the callback.
*
* @return Index of the attribute where the iterator stopped
*/
static uint8_t bt_sdp_foreach_attr(struct bt_sdp_record *record, uint8_t idx,
bt_sdp_attr_func_t func, void *user_data)
{
for (; idx < record->attr_count; idx++) {
if (func(&record->attrs[idx], idx, user_data) ==
BT_SDP_ITER_STOP) {
break;
}
}
return idx;
}
/* @brief Check if an attribute matches a range, and include it in the response
*
* Checks if an attribute matches a given attribute ID or range, and if so,
* includes it in the response packet
*
* @param attr The current attribute
* @param att_idx Index of the current attribute in the database
* @param user_data Pointer to the structure containing response packet, byte
* count, states, etc
*
* @return BT_SDP_ITER_CONTINUE if should continue to the next attribute
* or BT_SDP_ITER_STOP to stop.
*/
static uint8_t select_attrs(struct bt_sdp_attribute *attr, uint8_t att_idx,
void *user_data)
{
struct select_attrs_data *sad = user_data;
uint16_t att_id_lower, att_id_upper, att_id_cur;
uint8_t idx_filter;
for (idx_filter = 0; idx_filter < sad->num_filters; idx_filter++) {
att_id_lower = (sad->filter[idx_filter] >> 16);
att_id_upper = (sad->filter[idx_filter]);
att_id_cur = attr->id;
/* Check for range values */
if (att_id_lower != 0xffff &&
(!IN_RANGE(att_id_cur, att_id_lower, att_id_upper))) {
continue;
}
/* Check for match values */
if (att_id_lower == 0xffff && att_id_cur != att_id_upper) {
continue;
}
/* Attribute ID matches */
/* TODO: Add the attribute value to the packet */
break;
}
return BT_SDP_ITER_CONTINUE;
}
/* @brief Creates a response containing list(s) of attributes
*
* Creates a response containing the attributes of a service record. To be used
* for responding to Service Attribute and Service Search Attribute requests
*
* @param sdp Pointer to the SDP structure
* @param record Service record whose attributes are to be included in the
* response
* @param filter Attribute values/ranges to be used as a filter
* @param num_filters Number of elements in the attribute filter
* @param max_att_len Maximum size of attributes to be included in the response
* @param next_att Starting position of the search in the service's attr list
*
* @return None
*/
static void create_attr_resp(struct bt_sdp *sdp, struct bt_sdp_record *record,
uint32_t *filter, uint8_t num_filters,
uint16_t max_att_len, uint8_t next_att)
{
struct select_attrs_data sad;
uint8_t idx_att;
sad.num_filters = num_filters;
sad.rec = record;
sad.sdp = sdp;
sad.max_att_len = max_att_len;
sad.filter = filter;
idx_att = bt_sdp_foreach_attr(sad.rec, next_att, select_attrs, &sad);
}
/* @brief Extracts the attribute search list from a buffer
*
* Parses a buffer to extract the attribute search list (list of attribute IDs
* and ranges) which are to be used to filter attributes.
@ -708,6 +832,27 @@ static uint16_t get_att_search_list(struct net_buf *buf, uint32_t *filter,
return 0;
}
/* @brief Check if a given handle matches that of the current service
*
* Checks if a given handle matches that of the current service
*
* @param rec The current service record
* @param user_data Pointer to the service record handle to be matched
*
* @return BT_SDP_ITER_CONTINUE if should continue to the next record
* or BT_SDP_ITER_STOP to stop.
*/
static uint8_t find_handle(struct bt_sdp_record *rec, void *user_data)
{
uint32_t *svc_rec_hdl = user_data;
if (rec->handle == *svc_rec_hdl) {
return BT_SDP_ITER_STOP;
}
return BT_SDP_ITER_CONTINUE;
}
/* @brief Handler for Service Attribute Request
*
* Parses, processes and responds to a Service Attribute Request
@ -722,6 +867,7 @@ static uint16_t sdp_svc_att_req(struct bt_sdp *sdp, struct net_buf *buf,
uint16_t tid)
{
uint32_t filter[MAX_NUM_ATT_ID_FILTER];
struct bt_sdp_record *record;
uint32_t svc_rec_hdl;
uint16_t max_att_len, res;
uint8_t num_filters, cont_state_size, next_att = 0;
@ -768,7 +914,18 @@ static uint16_t sdp_svc_att_req(struct bt_sdp *sdp, struct net_buf *buf,
BT_DBG("svc_rec_hdl %u, max_att_len 0x%04x, cont_state %u", svc_rec_hdl,
max_att_len, next_att);
/* TODO: Find the attributes in the record and send it */
/* Find the service */
record = bt_sdp_foreach_svc(find_handle, &svc_rec_hdl);
if (!record) {
BT_WARN("Handle %u not found", svc_rec_hdl);
return BT_SDP_INVALID_RECORD_HANDLE;
}
create_attr_resp(sdp, record, filter, num_filters, max_att_len,
next_att);
/* TODO: Form the resp packet and send */
return 0;
}