📄 sdp.c
字号:
pds = sdp_list_append(pds, curr->val.dataseq); ap = sdp_list_append(ap, pds); } *pap = ap; return 0;}int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **pap){ sdp_data_t *pdlist, *curr; sdp_list_t *ap = 0; pdlist = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST); if (pdlist == NULL) { errno = ENODATA; return -1; } SDPDBG("AP type : 0%x\n", pdlist->dtd); pdlist = pdlist->val.dataseq; for (; pdlist; pdlist = pdlist->next) { sdp_list_t *pds = 0; for (curr = pdlist->val.dataseq; curr; curr = curr->next) pds = sdp_list_append(pds, curr->val.dataseq); ap = sdp_list_append(ap, pds); } *pap = ap; return 0;}int sdp_get_uuidseq_attr(const sdp_record_t *rec, uint16_t attr, sdp_list_t **seqp){ sdp_data_t *sdpdata = sdp_data_get(rec, attr); *seqp = NULL; if (sdpdata && sdpdata->dtd >= SDP_SEQ8 && sdpdata->dtd <= SDP_SEQ32) { sdp_data_t *d; for (d = sdpdata->val.dataseq; d; d = d->next) { uuid_t *u; if (d->dtd < SDP_UUID16 || d->dtd > SDP_UUID128) goto fail; u = malloc(sizeof(uuid_t)); memset(u, 0, sizeof(uuid_t)); *u = d->val.uuid; *seqp = sdp_list_append(*seqp, u); } return 0; }fail: sdp_list_free(*seqp, free); errno = EINVAL; return -1;}int sdp_set_uuidseq_attr(sdp_record_t *rec, uint16_t aid, sdp_list_t *seq){ int status = 0, i, len; void **dtds, **values; uint8_t uuid16 = SDP_UUID16; uint8_t uuid32 = SDP_UUID32; uint8_t uuid128 = SDP_UUID128; sdp_list_t *p; len = sdp_list_len(seq); if (!seq || len == 0) return -1; dtds = (void **)malloc(len * sizeof(void *)); values = (void **)malloc(len * sizeof(void *)); for (p = seq, i = 0; i < len; i++, p = p->next) { uuid_t *uuid = (uuid_t *)p->data; if (uuid) switch (uuid->type) { case SDP_UUID16: dtds[i] = &uuid16; values[i] = &uuid->value.uuid16; break; case SDP_UUID32: dtds[i] = &uuid32; values[i] = &uuid->value.uuid32; break; case SDP_UUID128: dtds[i] = &uuid128; values[i] = &uuid->value.uuid128; break; default: status = -1; break; } else { status = -1; break; } } if (status == 0) { sdp_data_t *data = sdp_seq_alloc(dtds, values, len); sdp_attr_replace(rec, aid, data); sdp_pattern_add_uuidseq(rec, seq); } free(dtds); free(values); return status;}int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq){ sdp_lang_attr_t *lang; sdp_data_t *sdpdata, *curr_data; *langSeq = NULL; sdpdata = sdp_data_get(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST); if (sdpdata == NULL) { errno = ENODATA; return -1; } curr_data = sdpdata->val.dataseq; while (curr_data) { sdp_data_t *pCode = curr_data; sdp_data_t *pEncoding = pCode->next; sdp_data_t *pOffset = pEncoding->next; if (pCode && pEncoding && pOffset) { lang = malloc(sizeof(sdp_lang_attr_t)); lang->code_ISO639 = pCode->val.uint16; lang->encoding = pEncoding->val.uint16; lang->base_offset = pOffset->val.uint16; SDPDBG("code_ISO639 : 0x%02x\n", lang->code_ISO639); SDPDBG("encoding : 0x%02x\n", lang->encoding); SDPDBG("base_offfset : 0x%02x\n", lang->base_offset); *langSeq = sdp_list_append(*langSeq, lang); } curr_data = pOffset->next; } return 0;}int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq){ sdp_profile_desc_t *profDesc; sdp_data_t *sdpdata, *seq; *profDescSeq = NULL; sdpdata = sdp_data_get(rec, SDP_ATTR_PFILE_DESC_LIST); if (!sdpdata || !sdpdata->val.dataseq) { errno = ENODATA; return -1; } for (seq = sdpdata->val.dataseq; seq && seq->val.dataseq; seq = seq->next) { uuid_t *uuid = NULL; uint16_t version = 0x100; if (SDP_IS_UUID(seq->dtd)) { uuid = &seq->val.uuid; } else { sdp_data_t *puuid = seq->val.dataseq; sdp_data_t *pVnum = seq->val.dataseq->next; if (puuid && pVnum) { uuid = &puuid->val.uuid; version = pVnum->val.uint16; } } if (uuid != NULL) { profDesc = malloc(sizeof(sdp_profile_desc_t)); profDesc->uuid = *uuid; profDesc->version = version;#ifdef SDP_DEBUG sdp_uuid_print(&profDesc->uuid); SDPDBG("Vnum : 0x%04x\n", profDesc->version);#endif *profDescSeq = sdp_list_append(*profDescSeq, profDesc); } } return 0;}int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **u16){ sdp_data_t *d, *curr; *u16 = NULL; d = sdp_data_get(rec, SDP_ATTR_VERSION_NUM_LIST); if (d == NULL) { errno = ENODATA; return -1; } for (curr = d->val.dataseq; curr; curr = curr->next) *u16 = sdp_list_append(*u16, &curr->val.uint16); return 0;}/* flexible extraction of basic attributes - Jean II *//* How do we expect caller to extract predefined data sequences? */int sdp_get_int_attr(const sdp_record_t *rec, uint16_t attrid, int *value){ sdp_data_t *sdpdata = sdp_data_get(rec, attrid); if (sdpdata) /* Verify that it is what the caller expects */ if (sdpdata->dtd == SDP_BOOL || sdpdata->dtd == SDP_UINT8 || sdpdata->dtd == SDP_UINT16 || sdpdata->dtd == SDP_UINT32 || sdpdata->dtd == SDP_INT8 || sdpdata->dtd == SDP_INT16 || sdpdata->dtd == SDP_INT32) { *value = sdpdata->val.uint32; return 0; } errno = EINVAL; return -1;}int sdp_get_string_attr(const sdp_record_t *rec, uint16_t attrid, char *value, int valuelen){ sdp_data_t *sdpdata = sdp_data_get(rec, attrid); if (sdpdata) /* Verify that it is what the caller expects */ if (sdpdata->dtd == SDP_TEXT_STR8 || sdpdata->dtd == SDP_TEXT_STR16 || sdpdata->dtd == SDP_TEXT_STR32) if (strlen(sdpdata->val.str) < valuelen) { strcpy(value, sdpdata->val.str); return 0; } errno = EINVAL; return -1;}#define get_basic_attr(attrID, pAttrValue, fieldName) \ sdp_data_t *data = sdp_data_get(rec, attrID); \ if (data) { \ *pAttrValue = data->val.fieldName; \ return 0; \ } \ errno = EINVAL; \ return -1;int sdp_get_service_id(const sdp_record_t *rec, uuid_t *uuid){ get_basic_attr(SDP_ATTR_SERVICE_ID, uuid, uuid);}int sdp_get_group_id(const sdp_record_t *rec, uuid_t *uuid){ get_basic_attr(SDP_ATTR_GROUP_ID, uuid, uuid);}int sdp_get_record_state(const sdp_record_t *rec, uint32_t *svcRecState){ get_basic_attr(SDP_ATTR_RECORD_STATE, svcRecState, uint32);}int sdp_get_service_avail(const sdp_record_t *rec, uint8_t *svcAvail){ get_basic_attr(SDP_ATTR_SERVICE_AVAILABILITY, svcAvail, uint8);}int sdp_get_service_ttl(const sdp_record_t *rec, uint32_t *svcTTLInfo){ get_basic_attr(SDP_ATTR_SVCINFO_TTL, svcTTLInfo, uint32);}int sdp_get_database_state(const sdp_record_t *rec, uint32_t *svcDBState){ get_basic_attr(SDP_ATTR_SVCDB_STATE, svcDBState, uint32);}/* * NOTE that none of the setXXX() functions below will * actually update the SDP server, unless the * {register, update}sdp_record_t() function is invoked. */int sdp_attr_add_new(sdp_record_t *rec, uint16_t attr, uint8_t dtd, const void *value){ sdp_data_t *d = sdp_data_alloc(dtd, value); if (d) { sdp_attr_replace(rec, attr, d); return 0; } return -1;}/* * Set the information attributes of the service * pointed to by rec. The attributes are * service name, description and provider name */void sdp_set_info_attr(sdp_record_t *rec, const char *name, const char *prov, const char *desc){ if (name) sdp_attr_add_new(rec, SDP_ATTR_SVCNAME_PRIMARY, SDP_TEXT_STR8, (void *)name); if (prov) sdp_attr_add_new(rec, SDP_ATTR_PROVNAME_PRIMARY, SDP_TEXT_STR8, (void *)prov); if (desc) sdp_attr_add_new(rec, SDP_ATTR_SVCDESC_PRIMARY, SDP_TEXT_STR8, (void *)desc);}static sdp_data_t *access_proto_to_dataseq(sdp_record_t *rec, sdp_list_t *proto){ sdp_data_t *seq = NULL; void *dtds[10], *values[10]; void **seqDTDs, **seqs; int i, seqlen; sdp_list_t *p; seqlen = sdp_list_len(proto); seqDTDs = (void **)malloc(seqlen * sizeof(void *)); seqs = (void **)malloc(seqlen * sizeof(void *)); for (i = 0, p = proto; p; p = p->next, i++) { sdp_list_t *elt = (sdp_list_t *)p->data; sdp_data_t *s; int pslen = 0; for (; elt && pslen < sizeof(dtds); elt = elt->next, pslen++) { sdp_data_t *d = (sdp_data_t *)elt->data; dtds[pslen] = &d->dtd; switch (d->dtd) { case SDP_UUID16: values[pslen] = &((uuid_t *)d)->value.uuid16; break; case SDP_UUID32: values[pslen] = &((uuid_t *)d)->value.uuid32; break; case SDP_UUID128: values[pslen] = &((uuid_t *)d)->value.uuid128; break; case SDP_UINT8: values[pslen] = &d->val.uint8; break; case SDP_UINT16: values[pslen] = &d->val.uint16; break; case SDP_SEQ8: case SDP_SEQ16: case SDP_SEQ32: values[pslen] = d; break; // FIXME: more } } s = sdp_seq_alloc(dtds, values, pslen); if (s) { seqDTDs[i] = &s->dtd; seqs[i] = s; } } seq = sdp_seq_alloc(seqDTDs, seqs, seqlen); free(seqDTDs); free(seqs); return seq;}/* * sets the access protocols of the service specified * to the value specified in "access_proto" * * Note that if there are alternate mechanisms by * which the service is accessed, then they should * be specified as sequences * * Using a value of NULL for accessProtocols has * effect of removing this attribute (if previously set) * * This function replaces the existing sdp_access_proto_t * structure (if any) with the new one specified. * * returns 0 if successful or -1 if there is a failure. */int sdp_set_access_protos(sdp_record_t *rec, const sdp_list_t *ap){ const sdp_list_t *p; sdp_data_t *protos = NULL; for (p = ap; p; p = p->next) { sdp_data_t *seq = access_proto_to_dataseq(rec, (sdp_list_t *) p->data); protos = sdp_seq_append(protos, seq); } sdp_attr_add(rec, SDP_ATTR_PROTO_DESC_LIST, protos); return 0;}int sdp_set_add_access_protos(sdp_record_t *rec, const sdp_list_t *ap){ const sdp_list_t *p; sdp_data_t *protos = NULL; for (p = ap; p; p = p->next) { sdp_data_t *seq = access_proto_to_dataseq(rec, (sdp_list_t *) p->data); protos = sdp_seq_append(protos, seq); } sdp_attr_add(rec, SDP_ATTR_ADD_PROTO_DESC_LIST, protos ? sdp_data_alloc(SDP_SEQ8, protos) : NULL); return 0;}/* * set the "LanguageBase" attributes of the service record * record to the value specified in "langAttrList". * * "langAttrList" is a linked list of "sdp_lang_attr_t" * objects, one for each language in which user visible * attributes are present in the service record. * * Using a value of NULL for langAttrList has * effect of removing this attribute (if previously set) * * This function replaces the exisiting sdp_lang_attr_t * structure (if any) with the new one specified. * * returns 0 if successful or -1 if there is a failure. */int sdp_set_lang_attr(sdp_record_t *rec, const sdp_list_t *seq){ uint8_t uint16 = SDP_UINT16; int status = 0, i = 0, seqlen = sdp_list_len(seq); void **dtds = (void **)malloc(3 * seqlen * sizeof(void *)); void **values = (void **)malloc(3 * seqlen * sizeof(void *)); const sdp_list_t *p; for (p = seq; p; p = p->next) { sdp_lang_attr_t *lang = (sdp_lang_attr_t *)p->data; if (!lang) { status = -1; break; } dtds[i] = &uint16; values[i] = &lang->code_ISO639; i++; dtds[i] = &uint16; values[i] = &lang->encoding; i++; dtds[i] = &uint16; values[i] = &lang->base_offset; i++; } if (status == 0) { sdp_data_t *seq = sdp_seq_alloc(dtds, values, 3 * seqlen); sdp_attr_add(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST, seq); } free(dtds); free(values); return status;}/* * set the "ServiceID" attribute of the service. * * This is the UUID of the service. * * returns 0 if successful or -1 if there is a failure. */void sdp_set_service_id(sdp_record_t *rec, uuid_t uuid){ switch (uuid.type) { case SDP_UUID16: sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID16, &uuid.value.uuid16); break; case SDP_UUID32: sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID32, &uuid.value.uuid32); break; case SDP_UUID128: sdp_attr_add_new(rec, SDP_ATTR_SERVICE_ID, SDP_UUID128, &uuid.value.uuid128); break; } sdp_pattern_add_uuid(rec, &uuid);}/* * set the GroupID attribute of the service record defining a group. * * This is the UUID of the group. * * returns 0 if successful or -1 if there is a failure. */void sdp_set_group_id(sdp_record_t *rec, uuid_t uuid){ switch (uuid.type) { case SDP_UUID16: sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID16, &uuid.value.uuid16); break; case SDP_UUID32: sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID32, &uuid.value.uuid32); break; case SDP_UUID128: sdp_attr_add_new(rec, SDP_ATTR_GROUP_ID, SDP_UUID128, &uuid.value.uuid128); break; } sdp_pattern_add_uuid(rec, &uuid);}/* * set the ProfileDescriptorList attribute of the service record * pointed to by record to the value specified in "profileDesc". * * Each element in the list is an object of type * sdp_profile_desc_t which is a definition of the * Bluetooth profile that this service conforms to. * * Using a value of NULL for profileDesc has * effect of removing this attribute (if previously set) * * This function replaces the exisiting ProfileDescriptorList * structure (if any) with the new one specified. * * returns 0 if successful or -1 if there is a failure. */int sdp_set_profile_descs(sdp_record_t *rec, const sdp_list_t *profiles){ int status = 0; uint8_t uuid16 = SDP_UUID16; uint8_t uuid32 = SDP_UUID32; uint8_t uuid128 = SDP_UUID128; uint8_t uint16 = SDP_UINT16; int i = 0, seqlen = sdp_list_len(profiles); void **seqDTDs = (void **)malloc(seqlen * sizeof(void *)); void **seqs = (void **)malloc(seqlen * sizeof(void *)); const sdp_list_t *p; for (p = profiles; p; p = p->next) { sdp_data_t *seq; void *dtds[2], *values[2]; sdp_profile_desc_t *profile = (sdp_profile_desc_t *)p->data; if (!profile) { status = -1; break; } switch (profile->uuid.type) { case SDP_UUID16: dtds[0] = &uuid16; values[0] = &profile->uuid.value.uuid16; break; case SDP_UUID32: dtds[0] = &uuid32; values[0] = &profile->uuid.value.uuid32; break; case SDP_UUID128: dtds[0] = &uuid128; values[0] = &profile->uuid.value.uuid128; break; default: status = -1; break; } dtds[1] = &uint16; values[1] = &profile->version; seq = sdp_seq_alloc(dtds, values, 2); if (seq) { seqDTDs[i] = &seq->dtd; seqs[i] = seq; sdp_pattern_add_uuid(rec, &profile->uuid);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -