BTstack for Nucleo F401RE/FRDM-KL46Z example program
Dependencies: F401RE-USBHost mbed
sdp_util.c
00001 /* 00002 * Copyright (C) 2009-2012 by Matthias Ringwald 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holders nor the names of 00014 * contributors may be used to endorse or promote products derived 00015 * from this software without specific prior written permission. 00016 * 4. Any redistribution, use, or modification is done solely for 00017 * personal benefit and not for any commercial purpose or for 00018 * monetary gain. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS 00021 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00022 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00023 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 00024 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00025 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00026 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00027 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00028 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00029 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00030 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00031 * SUCH DAMAGE. 00032 * 00033 * Please inquire about commercial licensing options at btstack@ringwald.ch 00034 * 00035 */ 00036 00037 /* 00038 * sdp_util.c 00039 */ 00040 00041 #include <btstack/sdp_util.h> 00042 #include <btstack/utils.h> 00043 00044 #include <stdio.h> 00045 #include <stdlib.h> 00046 #include <string.h> 00047 #include <stdint.h> 00048 #include <inttypes.h> // PRIx32 00049 00050 // workaround for missing PRIx32 on mspgcc (16-bit MCU) 00051 #ifndef PRIx32 00052 #warning Using own: #define PRIx32 "lx" 00053 #define PRIx32 "lx" 00054 #endif 00055 00056 // date element type names 00057 const char * const type_names[] = { "NIL", "UINT", "INT", "UUID", "STRING", "BOOL", "DES", "DEA", "URL"}; 00058 00059 // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB 00060 const uint8_t sdp_bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */ 00061 0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; 00062 00063 void sdp_normalize_uuid(uint8_t *uuid, uint32_t shortUUID){ 00064 memcpy(uuid, sdp_bluetooth_base_uuid, 16); 00065 net_store_32(uuid, 0, shortUUID); 00066 } 00067 00068 // MARK: DataElement getter 00069 de_size_t de_get_size_type(uint8_t *header){ 00070 return (de_size_t) (header[0] & 7); 00071 } 00072 00073 de_type_t de_get_element_type(uint8_t *header){ 00074 return (de_type_t) (header[0] >> 3); 00075 } 00076 00077 int de_get_header_size(uint8_t * header){ 00078 de_size_t de_size = de_get_size_type(header); 00079 if (de_size <= DE_SIZE_128) { 00080 return 1; 00081 } 00082 return 1 + (1 << (de_size-DE_SIZE_VAR_8)); 00083 } 00084 00085 int de_get_data_size(uint8_t * header){ 00086 uint32_t result = 0; 00087 de_type_t de_type = de_get_element_type(header); 00088 de_size_t de_size = de_get_size_type(header); 00089 switch (de_size){ 00090 case DE_SIZE_VAR_8: 00091 result = header[1]; 00092 break; 00093 case DE_SIZE_VAR_16: 00094 result = READ_NET_16(header,1); 00095 break; 00096 case DE_SIZE_VAR_32: 00097 result = READ_NET_32(header,1); 00098 break; 00099 default: 00100 // case DE_SIZE_8: 00101 // case DE_SIZE_16: 00102 // case DE_SIZE_32: 00103 // case DE_SIZE_64: 00104 // case DE_SIZE_128: 00105 if (de_type == DE_NIL) return 0; 00106 return 1 << de_size; 00107 } 00108 return result; 00109 } 00110 00111 int de_get_len(uint8_t *header){ 00112 return de_get_header_size(header) + de_get_data_size(header); 00113 } 00114 00115 // @returns: element is valid UUID 00116 int de_get_normalized_uuid(uint8_t *uuid128, uint8_t *element){ 00117 de_type_t uuidType = de_get_element_type(element); 00118 de_size_t uuidSize = de_get_size_type(element); 00119 if (uuidType != DE_UUID) return 0; 00120 uint32_t shortUUID; 00121 switch (uuidSize){ 00122 case DE_SIZE_16: 00123 shortUUID = READ_NET_16(element, 1); 00124 break; 00125 case DE_SIZE_32: 00126 shortUUID = READ_NET_32(element, 1); 00127 break; 00128 case DE_SIZE_128: 00129 memcpy(uuid128, element+1, 16); 00130 return 1; 00131 default: 00132 return 0; 00133 } 00134 sdp_normalize_uuid(uuid128, shortUUID); 00135 return 1; 00136 } 00137 00138 // functions to create record 00139 static void de_store_descriptor(uint8_t * header, de_type_t type, de_size_t size){ 00140 header[0] = (type << 3) | size; 00141 } 00142 00143 void de_store_descriptor_with_len(uint8_t * header, de_type_t type, de_size_t size, uint32_t len){ 00144 header[0] = (type << 3) | size; 00145 switch (size){ 00146 case DE_SIZE_VAR_8: 00147 header[1] = len; 00148 break; 00149 case DE_SIZE_VAR_16: 00150 net_store_16(header, 1, len); 00151 break; 00152 case DE_SIZE_VAR_32: 00153 net_store_32(header, 1, len); 00154 break; 00155 default: 00156 break; 00157 } 00158 } 00159 00160 // MARK: DataElement creation 00161 00162 /* starts a new sequence in empty buffer - first call */ 00163 void de_create_sequence(uint8_t *header){ 00164 de_store_descriptor_with_len( header, DE_DES, DE_SIZE_VAR_16, 0); // DES, 2 Byte Length 00165 }; 00166 00167 /* starts a sub-sequence, @returns handle for sub-sequence */ 00168 uint8_t * de_push_sequence(uint8_t *header){ 00169 int element_len = de_get_len(header); 00170 de_store_descriptor_with_len(header+element_len, DE_DES, DE_SIZE_VAR_16, 0); // DES, 2 Byte Length 00171 return header + element_len; 00172 } 00173 00174 /* closes the current sequence and updates the parent sequence */ 00175 void de_pop_sequence(uint8_t * parent, uint8_t * child){ 00176 int child_len = de_get_len(child); 00177 int data_size_parent = READ_NET_16(parent,1); 00178 net_store_16(parent, 1, data_size_parent + child_len); 00179 } 00180 00181 /* adds a single number value and 16+32 bit UUID to the sequence */ 00182 void de_add_number(uint8_t *seq, de_type_t type, de_size_t size, uint32_t value){ 00183 int data_size = READ_NET_16(seq,1); 00184 int element_size = 1; // e.g. for DE_TYPE_NIL 00185 de_store_descriptor(seq+3+data_size, type, size); 00186 switch (size){ 00187 case DE_SIZE_8: 00188 if (type != DE_NIL){ 00189 seq[4+data_size] = value; 00190 element_size = 2; 00191 } 00192 break; 00193 case DE_SIZE_16: 00194 net_store_16(seq, 4+data_size, value); 00195 element_size = 3; 00196 break; 00197 case DE_SIZE_32: 00198 net_store_32(seq, 4+data_size, value); 00199 element_size = 5; 00200 break; 00201 default: 00202 break; 00203 } 00204 net_store_16(seq, 1, data_size+element_size); 00205 } 00206 00207 /* add a single block of data, e.g. as DE_STRING, DE_URL */ 00208 void de_add_data( uint8_t *seq, de_type_t type, uint16_t size, uint8_t *data){ 00209 int data_size = READ_NET_16(seq,1); 00210 if (size > 0xff) { 00211 // use 16-bit lengh information (3 byte header) 00212 de_store_descriptor_with_len(seq+3+data_size, type, DE_SIZE_VAR_16, size); 00213 data_size += 3; 00214 } else { 00215 // use 8-bit lengh information (2 byte header) 00216 de_store_descriptor_with_len(seq+3+data_size, type, DE_SIZE_VAR_8, size); 00217 data_size += 2; 00218 } 00219 memcpy( seq + 3 + data_size, data, size); 00220 data_size += size; 00221 net_store_16(seq, 1, data_size); 00222 } 00223 00224 void de_add_uuid128(uint8_t * seq, uint8_t * uuid){ 00225 int data_size = READ_NET_16(seq,1); 00226 de_store_descriptor(seq+3+data_size, DE_UUID, DE_SIZE_128); 00227 memcpy( seq + 4 + data_size, uuid, 16); 00228 net_store_16(seq, 1, data_size+1+16); 00229 } 00230 00231 void sdp_add_attribute(uint8_t *seq, uint16_t attributeID, uint8_t attributeValue){ 00232 } 00233 00234 // MARK: DataElementSequence traversal 00235 typedef int (*de_traversal_callback_t)(uint8_t * element, de_type_t type, de_size_t size, void *context); 00236 static void de_traverse_sequence(uint8_t * element, de_traversal_callback_t handler, void *context){ 00237 de_type_t type = de_get_element_type(element); 00238 if (type != DE_DES) return; 00239 int pos = de_get_header_size(element); 00240 int end_pos = de_get_len(element); 00241 while (pos < end_pos){ 00242 de_type_t elemType = de_get_element_type(element + pos); 00243 de_size_t elemSize = de_get_size_type(element + pos); 00244 uint8_t done = (*handler)(element + pos, elemType, elemSize, context); 00245 if (done) break; 00246 pos += de_get_len(element + pos); 00247 } 00248 } 00249 00250 // MARK: AttributeList traversal 00251 typedef int (*sdp_attribute_list_traversal_callback_t)(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *context); 00252 static void sdp_attribute_list_traverse_sequence(uint8_t * element, sdp_attribute_list_traversal_callback_t handler, void *context){ 00253 de_type_t type = de_get_element_type(element); 00254 if (type != DE_DES) return; 00255 int pos = de_get_header_size(element); 00256 int end_pos = de_get_len(element); 00257 while (pos < end_pos){ 00258 de_type_t idType = de_get_element_type(element + pos); 00259 de_size_t idSize = de_get_size_type(element + pos); 00260 if (idType != DE_UINT || idSize != DE_SIZE_16) break; // wrong type 00261 uint16_t attribute_id = READ_NET_16(element, pos + 1); 00262 pos += 3; 00263 if (pos >= end_pos) break; // array out of bounds 00264 de_type_t valueType = de_get_element_type(element + pos); 00265 de_size_t valueSize = de_get_size_type(element + pos); 00266 uint8_t done = (*handler)(attribute_id, element + pos, valueType, valueSize, context); 00267 if (done) break; 00268 pos += de_get_len(element + pos); 00269 } 00270 } 00271 00272 // MARK: AttributeID in AttributeIDList 00273 // attribute ID in AttributeIDList 00274 // context { result, attributeID } 00275 struct sdp_context_attributeID_search { 00276 int result; 00277 uint16_t attributeID; 00278 }; 00279 static int sdp_traversal_attributeID_search(uint8_t * element, de_type_t type, de_size_t size, void *my_context){ 00280 struct sdp_context_attributeID_search * context = (struct sdp_context_attributeID_search *) my_context; 00281 if (type != DE_UINT) return 0; 00282 switch (size) { 00283 case DE_SIZE_16: 00284 if (READ_NET_16(element, 1) == context->attributeID) { 00285 context->result = 1; 00286 return 1; 00287 } 00288 break; 00289 case DE_SIZE_32: 00290 if (READ_NET_16(element, 1) <= context->attributeID 00291 && context->attributeID <= READ_NET_16(element, 3)) { 00292 context->result = 1; 00293 return 1; 00294 } 00295 break; 00296 default: 00297 break; 00298 } 00299 return 0; 00300 } 00301 int sdp_attribute_list_constains_id(uint8_t *attributeIDList, uint16_t attributeID){ 00302 struct sdp_context_attributeID_search attributeID_search; 00303 attributeID_search.result = 0; 00304 attributeID_search.attributeID = attributeID; 00305 de_traverse_sequence(attributeIDList, sdp_traversal_attributeID_search, &attributeID_search); 00306 return attributeID_search.result; 00307 } 00308 00309 // MARK: Append Attributes for AttributeIDList 00310 // pre: buffer contains DES with 2 byte length field 00311 struct sdp_context_append_attributes { 00312 uint8_t * buffer; 00313 uint16_t startOffset; // offset of when to start copying 00314 uint16_t maxBytes; 00315 uint16_t usedBytes; 00316 uint8_t *attributeIDList; 00317 }; 00318 00319 static int sdp_traversal_append_attributes(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *my_context){ 00320 struct sdp_context_append_attributes * context = (struct sdp_context_append_attributes *) my_context; 00321 if (sdp_attribute_list_constains_id(context->attributeIDList, attributeID)) { 00322 // DES_HEADER(3) + DES_DATA + (UINT16(3) + attribute) 00323 uint16_t data_size = READ_NET_16(context->buffer, 1); 00324 int attribute_len = de_get_len(attributeValue); 00325 if (3 + data_size + (3 + attribute_len) <= context->maxBytes) { 00326 // copy Attribute 00327 de_add_number(context->buffer, DE_UINT, DE_SIZE_16, attributeID); 00328 data_size += 3; // 3 bytes 00329 memcpy(context->buffer + 3 + data_size, attributeValue, attribute_len); 00330 net_store_16(context->buffer,1,data_size+attribute_len); 00331 } else { 00332 // not enought space left -> continue with previous element 00333 return 1; 00334 } 00335 } 00336 return 0; 00337 } 00338 00339 // maxBytes: maximal size of data element sequence 00340 uint16_t sdp_append_attributes_in_attributeIDList(uint8_t *record, uint8_t *attributeIDList, uint16_t startOffset, uint16_t maxBytes, uint8_t *buffer){ 00341 struct sdp_context_append_attributes context; 00342 context.buffer = buffer; 00343 context.maxBytes = maxBytes; 00344 context.usedBytes = 0; 00345 context.startOffset = startOffset; 00346 context.attributeIDList = attributeIDList; 00347 sdp_attribute_list_traverse_sequence(record, sdp_traversal_append_attributes, &context); 00348 return context.usedBytes; 00349 } 00350 00351 // MARK: Filter attributes that match attribute list from startOffset and a max nr bytes 00352 struct sdp_context_filter_attributes { 00353 uint8_t * buffer; 00354 uint16_t startOffset; // offset of when to start copying 00355 uint16_t maxBytes; 00356 uint16_t usedBytes; 00357 uint8_t *attributeIDList; 00358 int complete; 00359 }; 00360 00361 // copy data with given start offset and max bytes, returns OK if all data has been copied 00362 static int spd_append_range(struct sdp_context_filter_attributes* context, uint16_t len, uint8_t *data){ 00363 int ok = 1; 00364 uint16_t remainder_len = len - context->startOffset; 00365 if (context->maxBytes < remainder_len){ 00366 remainder_len = context->maxBytes; 00367 ok = 0; 00368 } 00369 memcpy(context->buffer, &data[context->startOffset], remainder_len); 00370 context->usedBytes += remainder_len; 00371 context->buffer += remainder_len; 00372 context->maxBytes -= remainder_len; 00373 context->startOffset = 0; 00374 return ok; 00375 } 00376 00377 static int sdp_traversal_filter_attributes(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *my_context){ 00378 struct sdp_context_filter_attributes * context = (struct sdp_context_filter_attributes *) my_context; 00379 00380 if (!sdp_attribute_list_constains_id(context->attributeIDList, attributeID)) return 0; 00381 00382 // { Attribute ID (Descriptor, big endian 16-bit ID), AttributeValue (data)} 00383 00384 // handle Attribute ID 00385 if (context->startOffset >= 3){ 00386 context->startOffset -= 3; 00387 } else { 00388 uint8_t idBuffer[3]; 00389 de_store_descriptor(idBuffer, DE_UINT, DE_SIZE_16); 00390 net_store_16(idBuffer,1,attributeID); 00391 00392 int ok = spd_append_range(context, 3, idBuffer); 00393 if (!ok) { 00394 context->complete = 0; 00395 return 1; 00396 } 00397 } 00398 00399 // handle Attribute Value 00400 int attribute_len = de_get_len(attributeValue); 00401 if (context->startOffset >= attribute_len) { 00402 context->startOffset -= attribute_len; 00403 return 0; 00404 } 00405 00406 int ok = spd_append_range(context, attribute_len, attributeValue); 00407 if (!ok) { 00408 context->complete = 0; 00409 return 1; 00410 } 00411 return 0; 00412 } 00413 00414 int sdp_filter_attributes_in_attributeIDList(uint8_t *record, uint8_t *attributeIDList, uint16_t startOffset, uint16_t maxBytes, uint16_t *usedBytes, uint8_t *buffer){ 00415 00416 struct sdp_context_filter_attributes context; 00417 context.buffer = buffer; 00418 context.maxBytes = maxBytes; 00419 context.usedBytes = 0; 00420 context.startOffset = startOffset; 00421 context.attributeIDList = attributeIDList; 00422 context.complete = 1; 00423 00424 sdp_attribute_list_traverse_sequence(record, sdp_traversal_filter_attributes, &context); 00425 00426 *usedBytes = context.usedBytes; 00427 return context.complete; 00428 } 00429 00430 // MARK: Get sum of attributes matching attribute list 00431 struct sdp_context_get_filtered_size { 00432 uint8_t *attributeIDList; 00433 uint16_t size; 00434 }; 00435 00436 static int sdp_traversal_get_filtered_size(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *my_context){ 00437 struct sdp_context_get_filtered_size * context = (struct sdp_context_get_filtered_size *) my_context; 00438 if (sdp_attribute_list_constains_id(context->attributeIDList, attributeID)) { 00439 context->size += 3 + de_get_len(attributeValue); 00440 } 00441 return 0; 00442 } 00443 00444 int spd_get_filtered_size(uint8_t *record, uint8_t *attributeIDList){ 00445 struct sdp_context_get_filtered_size context; 00446 context.size = 0; 00447 context.attributeIDList = attributeIDList; 00448 sdp_attribute_list_traverse_sequence(record, sdp_traversal_get_filtered_size, &context); 00449 return context.size; 00450 } 00451 00452 // MARK: Get AttributeValue for AttributeID 00453 // find attribute (ELEMENT) by ID 00454 struct sdp_context_attribute_by_id { 00455 uint16_t attributeID; 00456 uint8_t * attributeValue; 00457 }; 00458 static int sdp_traversal_attribute_by_id(uint16_t attributeID, uint8_t * attributeValue, de_type_t attributeType, de_size_t size, void *my_context){ 00459 struct sdp_context_attribute_by_id * context = (struct sdp_context_attribute_by_id *) my_context; 00460 if (attributeID == context->attributeID) { 00461 context->attributeValue = attributeValue; 00462 return 1; 00463 } 00464 return 0; 00465 } 00466 00467 uint8_t * sdp_get_attribute_value_for_attribute_id(uint8_t * record, uint16_t attributeID){ 00468 struct sdp_context_attribute_by_id context; 00469 context.attributeValue = NULL; 00470 context.attributeID = attributeID; 00471 sdp_attribute_list_traverse_sequence(record, sdp_traversal_attribute_by_id, &context); 00472 return context.attributeValue; 00473 } 00474 00475 // MARK: Set AttributeValue for AttributeID 00476 struct sdp_context_set_attribute_for_id { 00477 uint16_t attributeID; 00478 uint32_t attributeValue; 00479 uint8_t attributeFound; 00480 }; 00481 static int sdp_traversal_set_attribute_for_id(uint16_t attributeID, uint8_t * attributeValue, de_type_t attributeType, de_size_t size, void *my_context){ 00482 struct sdp_context_set_attribute_for_id * context = (struct sdp_context_set_attribute_for_id *) my_context; 00483 if (attributeID == context->attributeID) { 00484 context->attributeFound = 1; 00485 switch (size){ 00486 case DE_SIZE_8: 00487 if (attributeType != DE_NIL){ 00488 attributeValue[1] = context->attributeValue; 00489 } 00490 break; 00491 case DE_SIZE_16: 00492 net_store_16(attributeValue, 1, context->attributeValue); 00493 break; 00494 case DE_SIZE_32: 00495 net_store_32(attributeValue, 1, context->attributeValue); 00496 break; 00497 // Might want to support STRINGS to, copy upto original length 00498 default: 00499 break; 00500 } 00501 return 1; 00502 } 00503 return 0; 00504 } 00505 uint8_t sdp_set_attribute_value_for_attribute_id(uint8_t * record, uint16_t attributeID, uint32_t value){ 00506 struct sdp_context_set_attribute_for_id context; 00507 context.attributeID = attributeID; 00508 context.attributeValue = value; 00509 context.attributeFound = 0; 00510 sdp_attribute_list_traverse_sequence(record, sdp_traversal_set_attribute_for_id, &context); 00511 return context.attributeFound; 00512 } 00513 00514 // MARK: ServiceRecord contains UUID 00515 // service record contains UUID 00516 // context { normalizedUUID } 00517 struct sdp_context_contains_uuid128 { 00518 uint8_t * uuid128; 00519 int result; 00520 }; 00521 int sdp_record_contains_UUID128(uint8_t *record, uint8_t *uuid128); 00522 static int sdp_traversal_contains_UUID128(uint8_t * element, de_type_t type, de_size_t size, void *my_context){ 00523 struct sdp_context_contains_uuid128 * context = (struct sdp_context_contains_uuid128 *) my_context; 00524 uint8_t normalizedUUID[16]; 00525 if (type == DE_UUID){ 00526 uint8_t uuidOK = de_get_normalized_uuid(normalizedUUID, element); 00527 context->result = uuidOK && memcmp(context->uuid128, normalizedUUID, 16) == 0; 00528 } 00529 if (type == DE_DES){ 00530 context->result = sdp_record_contains_UUID128(element, context->uuid128); 00531 } 00532 return context->result; 00533 } 00534 int sdp_record_contains_UUID128(uint8_t *record, uint8_t *uuid128){ 00535 struct sdp_context_contains_uuid128 context; 00536 context.uuid128 = uuid128; 00537 context.result = 0; 00538 de_traverse_sequence(record, sdp_traversal_contains_UUID128, &context); 00539 return context.result; 00540 } 00541 00542 // MARK: ServiceRecord matches SearchServicePattern 00543 // if UUID in searchServicePattern is not found in record => false 00544 // context { result, record } 00545 struct sdp_context_match_pattern { 00546 uint8_t * record; 00547 int result; 00548 }; 00549 int sdp_traversal_match_pattern(uint8_t * element, de_type_t attributeType, de_size_t size, void *my_context){ 00550 struct sdp_context_match_pattern * context = (struct sdp_context_match_pattern *) my_context; 00551 uint8_t normalizedUUID[16]; 00552 uint8_t uuidOK = de_get_normalized_uuid(normalizedUUID, element); 00553 if (!uuidOK || !sdp_record_contains_UUID128(context->record, normalizedUUID)){ 00554 context->result = 0; 00555 return 1; 00556 } 00557 return 0; 00558 } 00559 int sdp_record_matches_service_search_pattern(uint8_t *record, uint8_t *serviceSearchPattern){ 00560 struct sdp_context_match_pattern context; 00561 context.record = record; 00562 context.result = 1; 00563 de_traverse_sequence(serviceSearchPattern, sdp_traversal_match_pattern, &context); 00564 return context.result; 00565 } 00566 00567 // MARK: Dump DataElement 00568 // context { indent } 00569 static int de_traversal_dump_data(uint8_t * element, de_type_t de_type, de_size_t de_size, void *my_context){ 00570 int indent = *(int*) my_context; 00571 int i; 00572 for (i=0; i<indent;i++) printf(" "); 00573 int pos = de_get_header_size(element); 00574 int end_pos = de_get_len(element); 00575 printf("type %5s (%u), element len %2u ", type_names[de_type], de_type, end_pos); 00576 if (de_type == DE_DES) { 00577 printf("\n"); 00578 indent++; 00579 de_traverse_sequence(element, de_traversal_dump_data, (void *)&indent); 00580 } else if (de_type == DE_UUID && de_size == DE_SIZE_128) { 00581 printf(", value: "); 00582 printUUID(element+1); 00583 printf("\n"); 00584 } else if (de_type == DE_STRING) { 00585 int len = 0; 00586 switch (de_size){ 00587 case DE_SIZE_VAR_8: 00588 len = element[1]; 00589 break; 00590 case DE_SIZE_VAR_16: 00591 len = READ_NET_16(element, 1); 00592 break; 00593 default: 00594 break; 00595 } 00596 printf("len %u (0x%02x)\n", len, len); 00597 hexdump(&element[pos], len); 00598 } else { 00599 uint32_t value = 0; 00600 switch (de_size) { 00601 case DE_SIZE_8: 00602 if (de_type != DE_NIL){ 00603 value = element[pos]; 00604 } 00605 break; 00606 case DE_SIZE_16: 00607 value = READ_NET_16(element,pos); 00608 break; 00609 case DE_SIZE_32: 00610 value = READ_NET_32(element,pos); 00611 break; 00612 default: 00613 break; 00614 } 00615 printf(", value: 0x%08" PRIx32 "\n", value); 00616 } 00617 return 0; 00618 } 00619 00620 void de_dump_data_element(uint8_t * record){ 00621 int indent = 0; 00622 // hack to get root DES, too. 00623 de_type_t type = de_get_element_type(record); 00624 de_size_t size = de_get_size_type(record); 00625 de_traversal_dump_data(record, type, size, (void*) &indent); 00626 } 00627 00628 void sdp_create_spp_service(uint8_t *service, int service_id, const char *name){ 00629 00630 uint8_t* attribute; 00631 de_create_sequence(service); 00632 00633 // 0x0000 "Service Record Handle" 00634 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceRecordHandle); 00635 de_add_number(service, DE_UINT, DE_SIZE_32, 0x10001); 00636 00637 // 0x0001 "Service Class ID List" 00638 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList); 00639 attribute = de_push_sequence(service); 00640 { 00641 de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1101 ); 00642 } 00643 de_pop_sequence(service, attribute); 00644 00645 // 0x0004 "Protocol Descriptor List" 00646 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ProtocolDescriptorList); 00647 attribute = de_push_sequence(service); 00648 { 00649 uint8_t* l2cpProtocol = de_push_sequence(attribute); 00650 { 00651 de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, 0x0100); 00652 } 00653 de_pop_sequence(attribute, l2cpProtocol); 00654 00655 uint8_t* rfcomm = de_push_sequence(attribute); 00656 { 00657 de_add_number(rfcomm, DE_UUID, DE_SIZE_16, 0x0003); // rfcomm_service 00658 de_add_number(rfcomm, DE_UINT, DE_SIZE_8, service_id); // rfcomm channel 00659 } 00660 de_pop_sequence(attribute, rfcomm); 00661 } 00662 de_pop_sequence(service, attribute); 00663 00664 // 0x0005 "Public Browse Group" 00665 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList); // public browse group 00666 attribute = de_push_sequence(service); 00667 { 00668 de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1002 ); 00669 } 00670 de_pop_sequence(service, attribute); 00671 00672 // 0x0006 00673 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_LanguageBaseAttributeIDList); 00674 attribute = de_push_sequence(service); 00675 { 00676 de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x656e); 00677 de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x006a); 00678 de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0100); 00679 } 00680 de_pop_sequence(service, attribute); 00681 00682 // 0x0009 "Bluetooth Profile Descriptor List" 00683 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BluetoothProfileDescriptorList); 00684 attribute = de_push_sequence(service); 00685 { 00686 uint8_t *sppProfile = de_push_sequence(attribute); 00687 { 00688 de_add_number(sppProfile, DE_UUID, DE_SIZE_16, 0x1101); 00689 de_add_number(sppProfile, DE_UINT, DE_SIZE_16, 0x0100); 00690 } 00691 de_pop_sequence(attribute, sppProfile); 00692 } 00693 de_pop_sequence(service, attribute); 00694 00695 // 0x0100 "ServiceName" 00696 de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100); 00697 de_add_data(service, DE_STRING, strlen(name), (uint8_t *) name); 00698 }
Generated on Thu Jul 14 2022 08:49:57 by 1.7.2