void register_device_id(const uint16_t vendor, const uint16_t product, const uint16_t version) { const uint16_t spec = 0x0102, source = 0x0002; const uint8_t primary = 1; sdp_list_t *class_list, *group_list, *profile_list; uuid_t class_uuid, group_uuid; sdp_data_t *sdp_data, *primary_data, *source_data; sdp_data_t *spec_data, *vendor_data, *product_data, *version_data; sdp_profile_desc_t profile; sdp_record_t *record = sdp_record_alloc(); info("Adding device id record for %04x:%04x", vendor, product); btd_manager_set_did(vendor, product, version); record->handle = sdp_next_handle(); sdp_record_add(BDADDR_ANY, record); sdp_data = sdp_data_alloc(SDP_UINT32, &record->handle); sdp_attr_add(record, SDP_ATTR_RECORD_HANDLE, sdp_data); sdp_uuid16_create(&class_uuid, PNP_INFO_SVCLASS_ID); class_list = sdp_list_append(0, &class_uuid); sdp_set_service_classes(record, class_list); sdp_list_free(class_list, NULL); sdp_uuid16_create(&group_uuid, PUBLIC_BROWSE_GROUP); group_list = sdp_list_append(NULL, &group_uuid); sdp_set_browse_groups(record, group_list); sdp_list_free(group_list, NULL); sdp_uuid16_create(&profile.uuid, PNP_INFO_PROFILE_ID); profile.version = spec; profile_list = sdp_list_append(NULL, &profile); sdp_set_profile_descs(record, profile_list); sdp_list_free(profile_list, NULL); spec_data = sdp_data_alloc(SDP_UINT16, &spec); sdp_attr_add(record, 0x0200, spec_data); vendor_data = sdp_data_alloc(SDP_UINT16, &vendor); sdp_attr_add(record, 0x0201, vendor_data); product_data = sdp_data_alloc(SDP_UINT16, &product); sdp_attr_add(record, 0x0202, product_data); version_data = sdp_data_alloc(SDP_UINT16, &version); sdp_attr_add(record, 0x0203, version_data); primary_data = sdp_data_alloc(SDP_BOOL, &primary); sdp_attr_add(record, 0x0204, primary_data); source_data = sdp_data_alloc(SDP_UINT16, &source); sdp_attr_add(record, 0x0205, source_data); update_db_timestamp(); }
static sdp_record_t *create_rfcomm_record(uint8_t chan, uuid_t *uuid, const char *svc_name, bool has_obex) { sdp_list_t *svclass_id; sdp_list_t *seq, *proto_seq, *pbg_seq; sdp_list_t *proto[3]; uuid_t l2cap_uuid, rfcomm_uuid, obex_uuid, pbg_uuid; sdp_data_t *channel; sdp_record_t *record; record = sdp_record_alloc(); if (!record) return NULL; record->handle = sdp_next_handle(); svclass_id = sdp_list_append(NULL, uuid); sdp_set_service_classes(record, svclass_id); sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); proto[0] = sdp_list_append(NULL, &l2cap_uuid); seq = sdp_list_append(NULL, proto[0]); sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); proto[1] = sdp_list_append(NULL, &rfcomm_uuid); channel = sdp_data_alloc(SDP_UINT8, &chan); proto[1] = sdp_list_append(proto[1], channel); seq = sdp_list_append(seq, proto[1]); if (has_obex) { sdp_uuid16_create(&obex_uuid, OBEX_UUID); proto[2] = sdp_list_append(NULL, &obex_uuid); seq = sdp_list_append(seq, proto[2]); } proto_seq = sdp_list_append(NULL, seq); sdp_set_access_protos(record, proto_seq); sdp_uuid16_create(&pbg_uuid, PUBLIC_BROWSE_GROUP); pbg_seq = sdp_list_append(NULL, &pbg_uuid); sdp_set_browse_groups(record, pbg_seq); if (svc_name) sdp_set_info_attr(record, svc_name, NULL, NULL); sdp_data_free(channel); sdp_list_free(proto[0], NULL); sdp_list_free(proto[1], NULL); if (has_obex) sdp_list_free(proto[2], NULL); sdp_list_free(seq, NULL); sdp_list_free(proto_seq, NULL); sdp_list_free(pbg_seq, NULL); sdp_list_free(svclass_id, NULL); return record; }
int add_record_to_server(const bdaddr_t *src, sdp_record_t *rec) { sdp_data_t *data; sdp_list_t *pattern; if (rec->handle == 0xffffffff) { rec->handle = sdp_next_handle(); if (rec->handle < 0x10000) return -ENOSPC; } else { if (sdp_record_find(rec->handle)) return -EEXIST; } DBG("Adding record with handle 0x%05x", rec->handle); sdp_record_add(src, rec); data = sdp_data_alloc(SDP_UINT32, &rec->handle); sdp_attr_replace(rec, SDP_ATTR_RECORD_HANDLE, data); if (sdp_data_get(rec, SDP_ATTR_BROWSE_GRP_LIST) == NULL) { uuid_t uuid; sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP); sdp_pattern_add_uuid(rec, &uuid); } for (pattern = rec->pattern; pattern; pattern = pattern->next) { char uuid[32]; if (pattern->data == NULL) continue; sdp_uuid2strn((uuid_t *) pattern->data, uuid, sizeof(uuid)); DBG("Record pattern UUID %s", uuid); } update_db_timestamp(); return 0; }
/* * Add the newly created service record to the service repository */ int service_register_req(sdp_req_t *req, sdp_buf_t *rsp) { int scanned = 0; sdp_data_t *handle; uint8_t *p = req->buf + sizeof(sdp_pdu_hdr_t); int bufsize = req->len - sizeof(sdp_pdu_hdr_t); sdp_record_t *rec; req->flags = *p++; if (req->flags & SDP_DEVICE_RECORD) { bacpy(&req->device, (bdaddr_t *) p); p += sizeof(bdaddr_t); bufsize -= sizeof(bdaddr_t); } /* save image of PDU: we need it when clients request this attribute */ rec = extract_pdu_server(&req->device, p, bufsize, 0xffffffff, &scanned); if (!rec) goto invalid; if (rec->handle == 0xffffffff) { rec->handle = sdp_next_handle(); if (rec->handle < 0x10000) { sdp_record_free(rec); goto invalid; } } else { if (sdp_record_find(rec->handle)) { /* extract_pdu_server will add the record handle * if it is missing. So instead of failing, skip * the record adding to avoid duplication. */ goto success; } } sdp_record_add(&req->device, rec); if (!(req->flags & SDP_RECORD_PERSIST)) sdp_svcdb_set_collectable(rec, req->sock); handle = sdp_data_alloc(SDP_UINT32, &rec->handle); sdp_attr_replace(rec, SDP_ATTR_RECORD_HANDLE, handle); success: /* if the browse group descriptor is NULL, * ensure that the record belongs to the ROOT group */ if (sdp_data_get(rec, SDP_ATTR_BROWSE_GRP_LIST) == NULL) { uuid_t uuid; sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP); sdp_pattern_add_uuid(rec, &uuid); } update_db_timestamp(); /* Build a rsp buffer */ bt_put_be32(rec->handle, rsp->data); rsp->data_size = sizeof(uint32_t); return 0; invalid: bt_put_be16(SDP_INVALID_SYNTAX, rsp->data); rsp->data_size = sizeof(uint16_t); return -1; }