mbed base bard check program for BlueTooth USB dongle module (3 switches, 6 leds, I2C LCD, A/D)

Dependencies:   USBHost mbed

Fork of BTstack by Norimasa Okamoto

Committer:
tamaki
Date:
Mon Oct 17 00:25:18 2016 +0000
Revision:
3:7b7d1273e2d5
Parent:
0:1ed23ab1345f
mbed base bard check program
; for BlueTooth USB dongle module
; (3 switches, 6 leds, I2C LCD, A/D)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:1ed23ab1345f 1 /*
va009039 0:1ed23ab1345f 2 * Copyright (C) 2009-2012 by Matthias Ringwald
va009039 0:1ed23ab1345f 3 *
va009039 0:1ed23ab1345f 4 * Redistribution and use in source and binary forms, with or without
va009039 0:1ed23ab1345f 5 * modification, are permitted provided that the following conditions
va009039 0:1ed23ab1345f 6 * are met:
va009039 0:1ed23ab1345f 7 *
va009039 0:1ed23ab1345f 8 * 1. Redistributions of source code must retain the above copyright
va009039 0:1ed23ab1345f 9 * notice, this list of conditions and the following disclaimer.
va009039 0:1ed23ab1345f 10 * 2. Redistributions in binary form must reproduce the above copyright
va009039 0:1ed23ab1345f 11 * notice, this list of conditions and the following disclaimer in the
va009039 0:1ed23ab1345f 12 * documentation and/or other materials provided with the distribution.
va009039 0:1ed23ab1345f 13 * 3. Neither the name of the copyright holders nor the names of
va009039 0:1ed23ab1345f 14 * contributors may be used to endorse or promote products derived
va009039 0:1ed23ab1345f 15 * from this software without specific prior written permission.
va009039 0:1ed23ab1345f 16 * 4. Any redistribution, use, or modification is done solely for
va009039 0:1ed23ab1345f 17 * personal benefit and not for any commercial purpose or for
va009039 0:1ed23ab1345f 18 * monetary gain.
va009039 0:1ed23ab1345f 19 *
va009039 0:1ed23ab1345f 20 * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS
va009039 0:1ed23ab1345f 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
va009039 0:1ed23ab1345f 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
va009039 0:1ed23ab1345f 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
va009039 0:1ed23ab1345f 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
va009039 0:1ed23ab1345f 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
va009039 0:1ed23ab1345f 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
va009039 0:1ed23ab1345f 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
va009039 0:1ed23ab1345f 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
va009039 0:1ed23ab1345f 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
va009039 0:1ed23ab1345f 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
va009039 0:1ed23ab1345f 31 * SUCH DAMAGE.
va009039 0:1ed23ab1345f 32 *
va009039 0:1ed23ab1345f 33 * Please inquire about commercial licensing options at btstack@ringwald.ch
va009039 0:1ed23ab1345f 34 *
va009039 0:1ed23ab1345f 35 */
va009039 0:1ed23ab1345f 36
va009039 0:1ed23ab1345f 37 /*
va009039 0:1ed23ab1345f 38 * sdp_util.c
va009039 0:1ed23ab1345f 39 */
va009039 0:1ed23ab1345f 40
va009039 0:1ed23ab1345f 41 #include <btstack/sdp_util.h>
va009039 0:1ed23ab1345f 42 #include <btstack/utils.h>
va009039 0:1ed23ab1345f 43
va009039 0:1ed23ab1345f 44 #include <stdio.h>
va009039 0:1ed23ab1345f 45 #include <stdlib.h>
va009039 0:1ed23ab1345f 46 #include <string.h>
va009039 0:1ed23ab1345f 47 #include <stdint.h>
va009039 0:1ed23ab1345f 48 #include <inttypes.h> // PRIx32
va009039 0:1ed23ab1345f 49
va009039 0:1ed23ab1345f 50 // workaround for missing PRIx32 on mspgcc (16-bit MCU)
va009039 0:1ed23ab1345f 51 #ifndef PRIx32
va009039 0:1ed23ab1345f 52 #warning Using own: #define PRIx32 "lx"
va009039 0:1ed23ab1345f 53 #define PRIx32 "lx"
va009039 0:1ed23ab1345f 54 #endif
va009039 0:1ed23ab1345f 55
va009039 0:1ed23ab1345f 56 // date element type names
va009039 0:1ed23ab1345f 57 const char * const type_names[] = { "NIL", "UINT", "INT", "UUID", "STRING", "BOOL", "DES", "DEA", "URL"};
va009039 0:1ed23ab1345f 58
va009039 0:1ed23ab1345f 59 // Bluetooth Base UUID: 00000000-0000-1000-8000- 00805F9B34FB
va009039 0:1ed23ab1345f 60 const uint8_t sdp_bluetooth_base_uuid[] = { 0x00, 0x00, 0x00, 0x00, /* - */ 0x00, 0x00, /* - */ 0x10, 0x00, /* - */
va009039 0:1ed23ab1345f 61 0x80, 0x00, /* - */ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
va009039 0:1ed23ab1345f 62
va009039 0:1ed23ab1345f 63 void sdp_normalize_uuid(uint8_t *uuid, uint32_t shortUUID){
va009039 0:1ed23ab1345f 64 memcpy(uuid, sdp_bluetooth_base_uuid, 16);
va009039 0:1ed23ab1345f 65 net_store_32(uuid, 0, shortUUID);
va009039 0:1ed23ab1345f 66 }
va009039 0:1ed23ab1345f 67
va009039 0:1ed23ab1345f 68 // MARK: DataElement getter
va009039 0:1ed23ab1345f 69 de_size_t de_get_size_type(uint8_t *header){
va009039 0:1ed23ab1345f 70 return (de_size_t) (header[0] & 7);
va009039 0:1ed23ab1345f 71 }
va009039 0:1ed23ab1345f 72
va009039 0:1ed23ab1345f 73 de_type_t de_get_element_type(uint8_t *header){
va009039 0:1ed23ab1345f 74 return (de_type_t) (header[0] >> 3);
va009039 0:1ed23ab1345f 75 }
va009039 0:1ed23ab1345f 76
va009039 0:1ed23ab1345f 77 int de_get_header_size(uint8_t * header){
va009039 0:1ed23ab1345f 78 de_size_t de_size = de_get_size_type(header);
va009039 0:1ed23ab1345f 79 if (de_size <= DE_SIZE_128) {
va009039 0:1ed23ab1345f 80 return 1;
va009039 0:1ed23ab1345f 81 }
va009039 0:1ed23ab1345f 82 return 1 + (1 << (de_size-DE_SIZE_VAR_8));
va009039 0:1ed23ab1345f 83 }
va009039 0:1ed23ab1345f 84
va009039 0:1ed23ab1345f 85 int de_get_data_size(uint8_t * header){
va009039 0:1ed23ab1345f 86 uint32_t result = 0;
va009039 0:1ed23ab1345f 87 de_type_t de_type = de_get_element_type(header);
va009039 0:1ed23ab1345f 88 de_size_t de_size = de_get_size_type(header);
va009039 0:1ed23ab1345f 89 switch (de_size){
va009039 0:1ed23ab1345f 90 case DE_SIZE_VAR_8:
va009039 0:1ed23ab1345f 91 result = header[1];
va009039 0:1ed23ab1345f 92 break;
va009039 0:1ed23ab1345f 93 case DE_SIZE_VAR_16:
va009039 0:1ed23ab1345f 94 result = READ_NET_16(header,1);
va009039 0:1ed23ab1345f 95 break;
va009039 0:1ed23ab1345f 96 case DE_SIZE_VAR_32:
va009039 0:1ed23ab1345f 97 result = READ_NET_32(header,1);
va009039 0:1ed23ab1345f 98 break;
va009039 0:1ed23ab1345f 99 default:
va009039 0:1ed23ab1345f 100 // case DE_SIZE_8:
va009039 0:1ed23ab1345f 101 // case DE_SIZE_16:
va009039 0:1ed23ab1345f 102 // case DE_SIZE_32:
va009039 0:1ed23ab1345f 103 // case DE_SIZE_64:
va009039 0:1ed23ab1345f 104 // case DE_SIZE_128:
va009039 0:1ed23ab1345f 105 if (de_type == DE_NIL) return 0;
va009039 0:1ed23ab1345f 106 return 1 << de_size;
va009039 0:1ed23ab1345f 107 }
va009039 0:1ed23ab1345f 108 return result;
va009039 0:1ed23ab1345f 109 }
va009039 0:1ed23ab1345f 110
va009039 0:1ed23ab1345f 111 int de_get_len(uint8_t *header){
va009039 0:1ed23ab1345f 112 return de_get_header_size(header) + de_get_data_size(header);
va009039 0:1ed23ab1345f 113 }
va009039 0:1ed23ab1345f 114
va009039 0:1ed23ab1345f 115 // @returns: element is valid UUID
va009039 0:1ed23ab1345f 116 int de_get_normalized_uuid(uint8_t *uuid128, uint8_t *element){
va009039 0:1ed23ab1345f 117 de_type_t uuidType = de_get_element_type(element);
va009039 0:1ed23ab1345f 118 de_size_t uuidSize = de_get_size_type(element);
va009039 0:1ed23ab1345f 119 if (uuidType != DE_UUID) return 0;
va009039 0:1ed23ab1345f 120 uint32_t shortUUID;
va009039 0:1ed23ab1345f 121 switch (uuidSize){
va009039 0:1ed23ab1345f 122 case DE_SIZE_16:
va009039 0:1ed23ab1345f 123 shortUUID = READ_NET_16(element, 1);
va009039 0:1ed23ab1345f 124 break;
va009039 0:1ed23ab1345f 125 case DE_SIZE_32:
va009039 0:1ed23ab1345f 126 shortUUID = READ_NET_32(element, 1);
va009039 0:1ed23ab1345f 127 break;
va009039 0:1ed23ab1345f 128 case DE_SIZE_128:
va009039 0:1ed23ab1345f 129 memcpy(uuid128, element+1, 16);
va009039 0:1ed23ab1345f 130 return 1;
va009039 0:1ed23ab1345f 131 default:
va009039 0:1ed23ab1345f 132 return 0;
va009039 0:1ed23ab1345f 133 }
va009039 0:1ed23ab1345f 134 sdp_normalize_uuid(uuid128, shortUUID);
va009039 0:1ed23ab1345f 135 return 1;
va009039 0:1ed23ab1345f 136 }
va009039 0:1ed23ab1345f 137
va009039 0:1ed23ab1345f 138 // functions to create record
va009039 0:1ed23ab1345f 139 static void de_store_descriptor(uint8_t * header, de_type_t type, de_size_t size){
va009039 0:1ed23ab1345f 140 header[0] = (type << 3) | size;
va009039 0:1ed23ab1345f 141 }
va009039 0:1ed23ab1345f 142
va009039 0:1ed23ab1345f 143 void de_store_descriptor_with_len(uint8_t * header, de_type_t type, de_size_t size, uint32_t len){
va009039 0:1ed23ab1345f 144 header[0] = (type << 3) | size;
va009039 0:1ed23ab1345f 145 switch (size){
va009039 0:1ed23ab1345f 146 case DE_SIZE_VAR_8:
va009039 0:1ed23ab1345f 147 header[1] = len;
va009039 0:1ed23ab1345f 148 break;
va009039 0:1ed23ab1345f 149 case DE_SIZE_VAR_16:
va009039 0:1ed23ab1345f 150 net_store_16(header, 1, len);
va009039 0:1ed23ab1345f 151 break;
va009039 0:1ed23ab1345f 152 case DE_SIZE_VAR_32:
va009039 0:1ed23ab1345f 153 net_store_32(header, 1, len);
va009039 0:1ed23ab1345f 154 break;
va009039 0:1ed23ab1345f 155 default:
va009039 0:1ed23ab1345f 156 break;
va009039 0:1ed23ab1345f 157 }
va009039 0:1ed23ab1345f 158 }
va009039 0:1ed23ab1345f 159
va009039 0:1ed23ab1345f 160 // MARK: DataElement creation
va009039 0:1ed23ab1345f 161
va009039 0:1ed23ab1345f 162 /* starts a new sequence in empty buffer - first call */
va009039 0:1ed23ab1345f 163 void de_create_sequence(uint8_t *header){
va009039 0:1ed23ab1345f 164 de_store_descriptor_with_len( header, DE_DES, DE_SIZE_VAR_16, 0); // DES, 2 Byte Length
va009039 0:1ed23ab1345f 165 };
va009039 0:1ed23ab1345f 166
va009039 0:1ed23ab1345f 167 /* starts a sub-sequence, @returns handle for sub-sequence */
va009039 0:1ed23ab1345f 168 uint8_t * de_push_sequence(uint8_t *header){
va009039 0:1ed23ab1345f 169 int element_len = de_get_len(header);
va009039 0:1ed23ab1345f 170 de_store_descriptor_with_len(header+element_len, DE_DES, DE_SIZE_VAR_16, 0); // DES, 2 Byte Length
va009039 0:1ed23ab1345f 171 return header + element_len;
va009039 0:1ed23ab1345f 172 }
va009039 0:1ed23ab1345f 173
va009039 0:1ed23ab1345f 174 /* closes the current sequence and updates the parent sequence */
va009039 0:1ed23ab1345f 175 void de_pop_sequence(uint8_t * parent, uint8_t * child){
va009039 0:1ed23ab1345f 176 int child_len = de_get_len(child);
va009039 0:1ed23ab1345f 177 int data_size_parent = READ_NET_16(parent,1);
va009039 0:1ed23ab1345f 178 net_store_16(parent, 1, data_size_parent + child_len);
va009039 0:1ed23ab1345f 179 }
va009039 0:1ed23ab1345f 180
va009039 0:1ed23ab1345f 181 /* adds a single number value and 16+32 bit UUID to the sequence */
va009039 0:1ed23ab1345f 182 void de_add_number(uint8_t *seq, de_type_t type, de_size_t size, uint32_t value){
va009039 0:1ed23ab1345f 183 int data_size = READ_NET_16(seq,1);
va009039 0:1ed23ab1345f 184 int element_size = 1; // e.g. for DE_TYPE_NIL
va009039 0:1ed23ab1345f 185 de_store_descriptor(seq+3+data_size, type, size);
va009039 0:1ed23ab1345f 186 switch (size){
va009039 0:1ed23ab1345f 187 case DE_SIZE_8:
va009039 0:1ed23ab1345f 188 if (type != DE_NIL){
va009039 0:1ed23ab1345f 189 seq[4+data_size] = value;
va009039 0:1ed23ab1345f 190 element_size = 2;
va009039 0:1ed23ab1345f 191 }
va009039 0:1ed23ab1345f 192 break;
va009039 0:1ed23ab1345f 193 case DE_SIZE_16:
va009039 0:1ed23ab1345f 194 net_store_16(seq, 4+data_size, value);
va009039 0:1ed23ab1345f 195 element_size = 3;
va009039 0:1ed23ab1345f 196 break;
va009039 0:1ed23ab1345f 197 case DE_SIZE_32:
va009039 0:1ed23ab1345f 198 net_store_32(seq, 4+data_size, value);
va009039 0:1ed23ab1345f 199 element_size = 5;
va009039 0:1ed23ab1345f 200 break;
va009039 0:1ed23ab1345f 201 default:
va009039 0:1ed23ab1345f 202 break;
va009039 0:1ed23ab1345f 203 }
va009039 0:1ed23ab1345f 204 net_store_16(seq, 1, data_size+element_size);
va009039 0:1ed23ab1345f 205 }
va009039 0:1ed23ab1345f 206
va009039 0:1ed23ab1345f 207 /* add a single block of data, e.g. as DE_STRING, DE_URL */
va009039 0:1ed23ab1345f 208 void de_add_data( uint8_t *seq, de_type_t type, uint16_t size, uint8_t *data){
va009039 0:1ed23ab1345f 209 int data_size = READ_NET_16(seq,1);
va009039 0:1ed23ab1345f 210 if (size > 0xff) {
va009039 0:1ed23ab1345f 211 // use 16-bit lengh information (3 byte header)
va009039 0:1ed23ab1345f 212 de_store_descriptor_with_len(seq+3+data_size, type, DE_SIZE_VAR_16, size);
va009039 0:1ed23ab1345f 213 data_size += 3;
va009039 0:1ed23ab1345f 214 } else {
va009039 0:1ed23ab1345f 215 // use 8-bit lengh information (2 byte header)
va009039 0:1ed23ab1345f 216 de_store_descriptor_with_len(seq+3+data_size, type, DE_SIZE_VAR_8, size);
va009039 0:1ed23ab1345f 217 data_size += 2;
va009039 0:1ed23ab1345f 218 }
va009039 0:1ed23ab1345f 219 memcpy( seq + 3 + data_size, data, size);
va009039 0:1ed23ab1345f 220 data_size += size;
va009039 0:1ed23ab1345f 221 net_store_16(seq, 1, data_size);
va009039 0:1ed23ab1345f 222 }
va009039 0:1ed23ab1345f 223
va009039 0:1ed23ab1345f 224 void de_add_uuid128(uint8_t * seq, uint8_t * uuid){
va009039 0:1ed23ab1345f 225 int data_size = READ_NET_16(seq,1);
va009039 0:1ed23ab1345f 226 de_store_descriptor(seq+3+data_size, DE_UUID, DE_SIZE_128);
va009039 0:1ed23ab1345f 227 memcpy( seq + 4 + data_size, uuid, 16);
va009039 0:1ed23ab1345f 228 net_store_16(seq, 1, data_size+1+16);
va009039 0:1ed23ab1345f 229 }
va009039 0:1ed23ab1345f 230
va009039 0:1ed23ab1345f 231 void sdp_add_attribute(uint8_t *seq, uint16_t attributeID, uint8_t attributeValue){
va009039 0:1ed23ab1345f 232 }
va009039 0:1ed23ab1345f 233
va009039 0:1ed23ab1345f 234 // MARK: DataElementSequence traversal
va009039 0:1ed23ab1345f 235 typedef int (*de_traversal_callback_t)(uint8_t * element, de_type_t type, de_size_t size, void *context);
va009039 0:1ed23ab1345f 236 static void de_traverse_sequence(uint8_t * element, de_traversal_callback_t handler, void *context){
va009039 0:1ed23ab1345f 237 de_type_t type = de_get_element_type(element);
va009039 0:1ed23ab1345f 238 if (type != DE_DES) return;
va009039 0:1ed23ab1345f 239 int pos = de_get_header_size(element);
va009039 0:1ed23ab1345f 240 int end_pos = de_get_len(element);
va009039 0:1ed23ab1345f 241 while (pos < end_pos){
va009039 0:1ed23ab1345f 242 de_type_t elemType = de_get_element_type(element + pos);
va009039 0:1ed23ab1345f 243 de_size_t elemSize = de_get_size_type(element + pos);
va009039 0:1ed23ab1345f 244 uint8_t done = (*handler)(element + pos, elemType, elemSize, context);
va009039 0:1ed23ab1345f 245 if (done) break;
va009039 0:1ed23ab1345f 246 pos += de_get_len(element + pos);
va009039 0:1ed23ab1345f 247 }
va009039 0:1ed23ab1345f 248 }
va009039 0:1ed23ab1345f 249
va009039 0:1ed23ab1345f 250 // MARK: AttributeList traversal
va009039 0:1ed23ab1345f 251 typedef int (*sdp_attribute_list_traversal_callback_t)(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *context);
va009039 0:1ed23ab1345f 252 static void sdp_attribute_list_traverse_sequence(uint8_t * element, sdp_attribute_list_traversal_callback_t handler, void *context){
va009039 0:1ed23ab1345f 253 de_type_t type = de_get_element_type(element);
va009039 0:1ed23ab1345f 254 if (type != DE_DES) return;
va009039 0:1ed23ab1345f 255 int pos = de_get_header_size(element);
va009039 0:1ed23ab1345f 256 int end_pos = de_get_len(element);
va009039 0:1ed23ab1345f 257 while (pos < end_pos){
va009039 0:1ed23ab1345f 258 de_type_t idType = de_get_element_type(element + pos);
va009039 0:1ed23ab1345f 259 de_size_t idSize = de_get_size_type(element + pos);
va009039 0:1ed23ab1345f 260 if (idType != DE_UINT || idSize != DE_SIZE_16) break; // wrong type
va009039 0:1ed23ab1345f 261 uint16_t attribute_id = READ_NET_16(element, pos + 1);
va009039 0:1ed23ab1345f 262 pos += 3;
va009039 0:1ed23ab1345f 263 if (pos >= end_pos) break; // array out of bounds
va009039 0:1ed23ab1345f 264 de_type_t valueType = de_get_element_type(element + pos);
va009039 0:1ed23ab1345f 265 de_size_t valueSize = de_get_size_type(element + pos);
va009039 0:1ed23ab1345f 266 uint8_t done = (*handler)(attribute_id, element + pos, valueType, valueSize, context);
va009039 0:1ed23ab1345f 267 if (done) break;
va009039 0:1ed23ab1345f 268 pos += de_get_len(element + pos);
va009039 0:1ed23ab1345f 269 }
va009039 0:1ed23ab1345f 270 }
va009039 0:1ed23ab1345f 271
va009039 0:1ed23ab1345f 272 // MARK: AttributeID in AttributeIDList
va009039 0:1ed23ab1345f 273 // attribute ID in AttributeIDList
va009039 0:1ed23ab1345f 274 // context { result, attributeID }
va009039 0:1ed23ab1345f 275 struct sdp_context_attributeID_search {
va009039 0:1ed23ab1345f 276 int result;
va009039 0:1ed23ab1345f 277 uint16_t attributeID;
va009039 0:1ed23ab1345f 278 };
va009039 0:1ed23ab1345f 279 static int sdp_traversal_attributeID_search(uint8_t * element, de_type_t type, de_size_t size, void *my_context){
va009039 0:1ed23ab1345f 280 struct sdp_context_attributeID_search * context = (struct sdp_context_attributeID_search *) my_context;
va009039 0:1ed23ab1345f 281 if (type != DE_UINT) return 0;
va009039 0:1ed23ab1345f 282 switch (size) {
va009039 0:1ed23ab1345f 283 case DE_SIZE_16:
va009039 0:1ed23ab1345f 284 if (READ_NET_16(element, 1) == context->attributeID) {
va009039 0:1ed23ab1345f 285 context->result = 1;
va009039 0:1ed23ab1345f 286 return 1;
va009039 0:1ed23ab1345f 287 }
va009039 0:1ed23ab1345f 288 break;
va009039 0:1ed23ab1345f 289 case DE_SIZE_32:
va009039 0:1ed23ab1345f 290 if (READ_NET_16(element, 1) <= context->attributeID
va009039 0:1ed23ab1345f 291 && context->attributeID <= READ_NET_16(element, 3)) {
va009039 0:1ed23ab1345f 292 context->result = 1;
va009039 0:1ed23ab1345f 293 return 1;
va009039 0:1ed23ab1345f 294 }
va009039 0:1ed23ab1345f 295 break;
va009039 0:1ed23ab1345f 296 default:
va009039 0:1ed23ab1345f 297 break;
va009039 0:1ed23ab1345f 298 }
va009039 0:1ed23ab1345f 299 return 0;
va009039 0:1ed23ab1345f 300 }
va009039 0:1ed23ab1345f 301 int sdp_attribute_list_constains_id(uint8_t *attributeIDList, uint16_t attributeID){
va009039 0:1ed23ab1345f 302 struct sdp_context_attributeID_search attributeID_search;
va009039 0:1ed23ab1345f 303 attributeID_search.result = 0;
va009039 0:1ed23ab1345f 304 attributeID_search.attributeID = attributeID;
va009039 0:1ed23ab1345f 305 de_traverse_sequence(attributeIDList, sdp_traversal_attributeID_search, &attributeID_search);
va009039 0:1ed23ab1345f 306 return attributeID_search.result;
va009039 0:1ed23ab1345f 307 }
va009039 0:1ed23ab1345f 308
va009039 0:1ed23ab1345f 309 // MARK: Append Attributes for AttributeIDList
va009039 0:1ed23ab1345f 310 // pre: buffer contains DES with 2 byte length field
va009039 0:1ed23ab1345f 311 struct sdp_context_append_attributes {
va009039 0:1ed23ab1345f 312 uint8_t * buffer;
va009039 0:1ed23ab1345f 313 uint16_t startOffset; // offset of when to start copying
va009039 0:1ed23ab1345f 314 uint16_t maxBytes;
va009039 0:1ed23ab1345f 315 uint16_t usedBytes;
va009039 0:1ed23ab1345f 316 uint8_t *attributeIDList;
va009039 0:1ed23ab1345f 317 };
va009039 0:1ed23ab1345f 318
va009039 0:1ed23ab1345f 319 static int sdp_traversal_append_attributes(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *my_context){
va009039 0:1ed23ab1345f 320 struct sdp_context_append_attributes * context = (struct sdp_context_append_attributes *) my_context;
va009039 0:1ed23ab1345f 321 if (sdp_attribute_list_constains_id(context->attributeIDList, attributeID)) {
va009039 0:1ed23ab1345f 322 // DES_HEADER(3) + DES_DATA + (UINT16(3) + attribute)
va009039 0:1ed23ab1345f 323 uint16_t data_size = READ_NET_16(context->buffer, 1);
va009039 0:1ed23ab1345f 324 int attribute_len = de_get_len(attributeValue);
va009039 0:1ed23ab1345f 325 if (3 + data_size + (3 + attribute_len) <= context->maxBytes) {
va009039 0:1ed23ab1345f 326 // copy Attribute
va009039 0:1ed23ab1345f 327 de_add_number(context->buffer, DE_UINT, DE_SIZE_16, attributeID);
va009039 0:1ed23ab1345f 328 data_size += 3; // 3 bytes
va009039 0:1ed23ab1345f 329 memcpy(context->buffer + 3 + data_size, attributeValue, attribute_len);
va009039 0:1ed23ab1345f 330 net_store_16(context->buffer,1,data_size+attribute_len);
va009039 0:1ed23ab1345f 331 } else {
va009039 0:1ed23ab1345f 332 // not enought space left -> continue with previous element
va009039 0:1ed23ab1345f 333 return 1;
va009039 0:1ed23ab1345f 334 }
va009039 0:1ed23ab1345f 335 }
va009039 0:1ed23ab1345f 336 return 0;
va009039 0:1ed23ab1345f 337 }
va009039 0:1ed23ab1345f 338
va009039 0:1ed23ab1345f 339 // maxBytes: maximal size of data element sequence
va009039 0:1ed23ab1345f 340 uint16_t sdp_append_attributes_in_attributeIDList(uint8_t *record, uint8_t *attributeIDList, uint16_t startOffset, uint16_t maxBytes, uint8_t *buffer){
va009039 0:1ed23ab1345f 341 struct sdp_context_append_attributes context;
va009039 0:1ed23ab1345f 342 context.buffer = buffer;
va009039 0:1ed23ab1345f 343 context.maxBytes = maxBytes;
va009039 0:1ed23ab1345f 344 context.usedBytes = 0;
va009039 0:1ed23ab1345f 345 context.startOffset = startOffset;
va009039 0:1ed23ab1345f 346 context.attributeIDList = attributeIDList;
va009039 0:1ed23ab1345f 347 sdp_attribute_list_traverse_sequence(record, sdp_traversal_append_attributes, &context);
va009039 0:1ed23ab1345f 348 return context.usedBytes;
va009039 0:1ed23ab1345f 349 }
va009039 0:1ed23ab1345f 350
va009039 0:1ed23ab1345f 351 // MARK: Filter attributes that match attribute list from startOffset and a max nr bytes
va009039 0:1ed23ab1345f 352 struct sdp_context_filter_attributes {
va009039 0:1ed23ab1345f 353 uint8_t * buffer;
va009039 0:1ed23ab1345f 354 uint16_t startOffset; // offset of when to start copying
va009039 0:1ed23ab1345f 355 uint16_t maxBytes;
va009039 0:1ed23ab1345f 356 uint16_t usedBytes;
va009039 0:1ed23ab1345f 357 uint8_t *attributeIDList;
va009039 0:1ed23ab1345f 358 int complete;
va009039 0:1ed23ab1345f 359 };
va009039 0:1ed23ab1345f 360
va009039 0:1ed23ab1345f 361 // copy data with given start offset and max bytes, returns OK if all data has been copied
va009039 0:1ed23ab1345f 362 static int spd_append_range(struct sdp_context_filter_attributes* context, uint16_t len, uint8_t *data){
va009039 0:1ed23ab1345f 363 int ok = 1;
va009039 0:1ed23ab1345f 364 uint16_t remainder_len = len - context->startOffset;
va009039 0:1ed23ab1345f 365 if (context->maxBytes < remainder_len){
va009039 0:1ed23ab1345f 366 remainder_len = context->maxBytes;
va009039 0:1ed23ab1345f 367 ok = 0;
va009039 0:1ed23ab1345f 368 }
va009039 0:1ed23ab1345f 369 memcpy(context->buffer, &data[context->startOffset], remainder_len);
va009039 0:1ed23ab1345f 370 context->usedBytes += remainder_len;
va009039 0:1ed23ab1345f 371 context->buffer += remainder_len;
va009039 0:1ed23ab1345f 372 context->maxBytes -= remainder_len;
va009039 0:1ed23ab1345f 373 context->startOffset = 0;
va009039 0:1ed23ab1345f 374 return ok;
va009039 0:1ed23ab1345f 375 }
va009039 0:1ed23ab1345f 376
va009039 0:1ed23ab1345f 377 static int sdp_traversal_filter_attributes(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *my_context){
va009039 0:1ed23ab1345f 378 struct sdp_context_filter_attributes * context = (struct sdp_context_filter_attributes *) my_context;
va009039 0:1ed23ab1345f 379
va009039 0:1ed23ab1345f 380 if (!sdp_attribute_list_constains_id(context->attributeIDList, attributeID)) return 0;
va009039 0:1ed23ab1345f 381
va009039 0:1ed23ab1345f 382 // { Attribute ID (Descriptor, big endian 16-bit ID), AttributeValue (data)}
va009039 0:1ed23ab1345f 383
va009039 0:1ed23ab1345f 384 // handle Attribute ID
va009039 0:1ed23ab1345f 385 if (context->startOffset >= 3){
va009039 0:1ed23ab1345f 386 context->startOffset -= 3;
va009039 0:1ed23ab1345f 387 } else {
va009039 0:1ed23ab1345f 388 uint8_t idBuffer[3];
va009039 0:1ed23ab1345f 389 de_store_descriptor(idBuffer, DE_UINT, DE_SIZE_16);
va009039 0:1ed23ab1345f 390 net_store_16(idBuffer,1,attributeID);
va009039 0:1ed23ab1345f 391
va009039 0:1ed23ab1345f 392 int ok = spd_append_range(context, 3, idBuffer);
va009039 0:1ed23ab1345f 393 if (!ok) {
va009039 0:1ed23ab1345f 394 context->complete = 0;
va009039 0:1ed23ab1345f 395 return 1;
va009039 0:1ed23ab1345f 396 }
va009039 0:1ed23ab1345f 397 }
va009039 0:1ed23ab1345f 398
va009039 0:1ed23ab1345f 399 // handle Attribute Value
va009039 0:1ed23ab1345f 400 int attribute_len = de_get_len(attributeValue);
va009039 0:1ed23ab1345f 401 if (context->startOffset >= attribute_len) {
va009039 0:1ed23ab1345f 402 context->startOffset -= attribute_len;
va009039 0:1ed23ab1345f 403 return 0;
va009039 0:1ed23ab1345f 404 }
va009039 0:1ed23ab1345f 405
va009039 0:1ed23ab1345f 406 int ok = spd_append_range(context, attribute_len, attributeValue);
va009039 0:1ed23ab1345f 407 if (!ok) {
va009039 0:1ed23ab1345f 408 context->complete = 0;
va009039 0:1ed23ab1345f 409 return 1;
va009039 0:1ed23ab1345f 410 }
va009039 0:1ed23ab1345f 411 return 0;
va009039 0:1ed23ab1345f 412 }
va009039 0:1ed23ab1345f 413
va009039 0:1ed23ab1345f 414 int sdp_filter_attributes_in_attributeIDList(uint8_t *record, uint8_t *attributeIDList, uint16_t startOffset, uint16_t maxBytes, uint16_t *usedBytes, uint8_t *buffer){
va009039 0:1ed23ab1345f 415
va009039 0:1ed23ab1345f 416 struct sdp_context_filter_attributes context;
va009039 0:1ed23ab1345f 417 context.buffer = buffer;
va009039 0:1ed23ab1345f 418 context.maxBytes = maxBytes;
va009039 0:1ed23ab1345f 419 context.usedBytes = 0;
va009039 0:1ed23ab1345f 420 context.startOffset = startOffset;
va009039 0:1ed23ab1345f 421 context.attributeIDList = attributeIDList;
va009039 0:1ed23ab1345f 422 context.complete = 1;
va009039 0:1ed23ab1345f 423
va009039 0:1ed23ab1345f 424 sdp_attribute_list_traverse_sequence(record, sdp_traversal_filter_attributes, &context);
va009039 0:1ed23ab1345f 425
va009039 0:1ed23ab1345f 426 *usedBytes = context.usedBytes;
va009039 0:1ed23ab1345f 427 return context.complete;
va009039 0:1ed23ab1345f 428 }
va009039 0:1ed23ab1345f 429
va009039 0:1ed23ab1345f 430 // MARK: Get sum of attributes matching attribute list
va009039 0:1ed23ab1345f 431 struct sdp_context_get_filtered_size {
va009039 0:1ed23ab1345f 432 uint8_t *attributeIDList;
va009039 0:1ed23ab1345f 433 uint16_t size;
va009039 0:1ed23ab1345f 434 };
va009039 0:1ed23ab1345f 435
va009039 0:1ed23ab1345f 436 static int sdp_traversal_get_filtered_size(uint16_t attributeID, uint8_t * attributeValue, de_type_t type, de_size_t size, void *my_context){
va009039 0:1ed23ab1345f 437 struct sdp_context_get_filtered_size * context = (struct sdp_context_get_filtered_size *) my_context;
va009039 0:1ed23ab1345f 438 if (sdp_attribute_list_constains_id(context->attributeIDList, attributeID)) {
va009039 0:1ed23ab1345f 439 context->size += 3 + de_get_len(attributeValue);
va009039 0:1ed23ab1345f 440 }
va009039 0:1ed23ab1345f 441 return 0;
va009039 0:1ed23ab1345f 442 }
va009039 0:1ed23ab1345f 443
va009039 0:1ed23ab1345f 444 int spd_get_filtered_size(uint8_t *record, uint8_t *attributeIDList){
va009039 0:1ed23ab1345f 445 struct sdp_context_get_filtered_size context;
va009039 0:1ed23ab1345f 446 context.size = 0;
va009039 0:1ed23ab1345f 447 context.attributeIDList = attributeIDList;
va009039 0:1ed23ab1345f 448 sdp_attribute_list_traverse_sequence(record, sdp_traversal_get_filtered_size, &context);
va009039 0:1ed23ab1345f 449 return context.size;
va009039 0:1ed23ab1345f 450 }
va009039 0:1ed23ab1345f 451
va009039 0:1ed23ab1345f 452 // MARK: Get AttributeValue for AttributeID
va009039 0:1ed23ab1345f 453 // find attribute (ELEMENT) by ID
va009039 0:1ed23ab1345f 454 struct sdp_context_attribute_by_id {
va009039 0:1ed23ab1345f 455 uint16_t attributeID;
va009039 0:1ed23ab1345f 456 uint8_t * attributeValue;
va009039 0:1ed23ab1345f 457 };
va009039 0:1ed23ab1345f 458 static int sdp_traversal_attribute_by_id(uint16_t attributeID, uint8_t * attributeValue, de_type_t attributeType, de_size_t size, void *my_context){
va009039 0:1ed23ab1345f 459 struct sdp_context_attribute_by_id * context = (struct sdp_context_attribute_by_id *) my_context;
va009039 0:1ed23ab1345f 460 if (attributeID == context->attributeID) {
va009039 0:1ed23ab1345f 461 context->attributeValue = attributeValue;
va009039 0:1ed23ab1345f 462 return 1;
va009039 0:1ed23ab1345f 463 }
va009039 0:1ed23ab1345f 464 return 0;
va009039 0:1ed23ab1345f 465 }
va009039 0:1ed23ab1345f 466
va009039 0:1ed23ab1345f 467 uint8_t * sdp_get_attribute_value_for_attribute_id(uint8_t * record, uint16_t attributeID){
va009039 0:1ed23ab1345f 468 struct sdp_context_attribute_by_id context;
va009039 0:1ed23ab1345f 469 context.attributeValue = NULL;
va009039 0:1ed23ab1345f 470 context.attributeID = attributeID;
va009039 0:1ed23ab1345f 471 sdp_attribute_list_traverse_sequence(record, sdp_traversal_attribute_by_id, &context);
va009039 0:1ed23ab1345f 472 return context.attributeValue;
va009039 0:1ed23ab1345f 473 }
va009039 0:1ed23ab1345f 474
va009039 0:1ed23ab1345f 475 // MARK: Set AttributeValue for AttributeID
va009039 0:1ed23ab1345f 476 struct sdp_context_set_attribute_for_id {
va009039 0:1ed23ab1345f 477 uint16_t attributeID;
va009039 0:1ed23ab1345f 478 uint32_t attributeValue;
va009039 0:1ed23ab1345f 479 uint8_t attributeFound;
va009039 0:1ed23ab1345f 480 };
va009039 0:1ed23ab1345f 481 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){
va009039 0:1ed23ab1345f 482 struct sdp_context_set_attribute_for_id * context = (struct sdp_context_set_attribute_for_id *) my_context;
va009039 0:1ed23ab1345f 483 if (attributeID == context->attributeID) {
va009039 0:1ed23ab1345f 484 context->attributeFound = 1;
va009039 0:1ed23ab1345f 485 switch (size){
va009039 0:1ed23ab1345f 486 case DE_SIZE_8:
va009039 0:1ed23ab1345f 487 if (attributeType != DE_NIL){
va009039 0:1ed23ab1345f 488 attributeValue[1] = context->attributeValue;
va009039 0:1ed23ab1345f 489 }
va009039 0:1ed23ab1345f 490 break;
va009039 0:1ed23ab1345f 491 case DE_SIZE_16:
va009039 0:1ed23ab1345f 492 net_store_16(attributeValue, 1, context->attributeValue);
va009039 0:1ed23ab1345f 493 break;
va009039 0:1ed23ab1345f 494 case DE_SIZE_32:
va009039 0:1ed23ab1345f 495 net_store_32(attributeValue, 1, context->attributeValue);
va009039 0:1ed23ab1345f 496 break;
va009039 0:1ed23ab1345f 497 // Might want to support STRINGS to, copy upto original length
va009039 0:1ed23ab1345f 498 default:
va009039 0:1ed23ab1345f 499 break;
va009039 0:1ed23ab1345f 500 }
va009039 0:1ed23ab1345f 501 return 1;
va009039 0:1ed23ab1345f 502 }
va009039 0:1ed23ab1345f 503 return 0;
va009039 0:1ed23ab1345f 504 }
va009039 0:1ed23ab1345f 505 uint8_t sdp_set_attribute_value_for_attribute_id(uint8_t * record, uint16_t attributeID, uint32_t value){
va009039 0:1ed23ab1345f 506 struct sdp_context_set_attribute_for_id context;
va009039 0:1ed23ab1345f 507 context.attributeID = attributeID;
va009039 0:1ed23ab1345f 508 context.attributeValue = value;
va009039 0:1ed23ab1345f 509 context.attributeFound = 0;
va009039 0:1ed23ab1345f 510 sdp_attribute_list_traverse_sequence(record, sdp_traversal_set_attribute_for_id, &context);
va009039 0:1ed23ab1345f 511 return context.attributeFound;
va009039 0:1ed23ab1345f 512 }
va009039 0:1ed23ab1345f 513
va009039 0:1ed23ab1345f 514 // MARK: ServiceRecord contains UUID
va009039 0:1ed23ab1345f 515 // service record contains UUID
va009039 0:1ed23ab1345f 516 // context { normalizedUUID }
va009039 0:1ed23ab1345f 517 struct sdp_context_contains_uuid128 {
va009039 0:1ed23ab1345f 518 uint8_t * uuid128;
va009039 0:1ed23ab1345f 519 int result;
va009039 0:1ed23ab1345f 520 };
va009039 0:1ed23ab1345f 521 int sdp_record_contains_UUID128(uint8_t *record, uint8_t *uuid128);
va009039 0:1ed23ab1345f 522 static int sdp_traversal_contains_UUID128(uint8_t * element, de_type_t type, de_size_t size, void *my_context){
va009039 0:1ed23ab1345f 523 struct sdp_context_contains_uuid128 * context = (struct sdp_context_contains_uuid128 *) my_context;
va009039 0:1ed23ab1345f 524 uint8_t normalizedUUID[16];
va009039 0:1ed23ab1345f 525 if (type == DE_UUID){
va009039 0:1ed23ab1345f 526 uint8_t uuidOK = de_get_normalized_uuid(normalizedUUID, element);
va009039 0:1ed23ab1345f 527 context->result = uuidOK && memcmp(context->uuid128, normalizedUUID, 16) == 0;
va009039 0:1ed23ab1345f 528 }
va009039 0:1ed23ab1345f 529 if (type == DE_DES){
va009039 0:1ed23ab1345f 530 context->result = sdp_record_contains_UUID128(element, context->uuid128);
va009039 0:1ed23ab1345f 531 }
va009039 0:1ed23ab1345f 532 return context->result;
va009039 0:1ed23ab1345f 533 }
va009039 0:1ed23ab1345f 534 int sdp_record_contains_UUID128(uint8_t *record, uint8_t *uuid128){
va009039 0:1ed23ab1345f 535 struct sdp_context_contains_uuid128 context;
va009039 0:1ed23ab1345f 536 context.uuid128 = uuid128;
va009039 0:1ed23ab1345f 537 context.result = 0;
va009039 0:1ed23ab1345f 538 de_traverse_sequence(record, sdp_traversal_contains_UUID128, &context);
va009039 0:1ed23ab1345f 539 return context.result;
va009039 0:1ed23ab1345f 540 }
va009039 0:1ed23ab1345f 541
va009039 0:1ed23ab1345f 542 // MARK: ServiceRecord matches SearchServicePattern
va009039 0:1ed23ab1345f 543 // if UUID in searchServicePattern is not found in record => false
va009039 0:1ed23ab1345f 544 // context { result, record }
va009039 0:1ed23ab1345f 545 struct sdp_context_match_pattern {
va009039 0:1ed23ab1345f 546 uint8_t * record;
va009039 0:1ed23ab1345f 547 int result;
va009039 0:1ed23ab1345f 548 };
va009039 0:1ed23ab1345f 549 int sdp_traversal_match_pattern(uint8_t * element, de_type_t attributeType, de_size_t size, void *my_context){
va009039 0:1ed23ab1345f 550 struct sdp_context_match_pattern * context = (struct sdp_context_match_pattern *) my_context;
va009039 0:1ed23ab1345f 551 uint8_t normalizedUUID[16];
va009039 0:1ed23ab1345f 552 uint8_t uuidOK = de_get_normalized_uuid(normalizedUUID, element);
va009039 0:1ed23ab1345f 553 if (!uuidOK || !sdp_record_contains_UUID128(context->record, normalizedUUID)){
va009039 0:1ed23ab1345f 554 context->result = 0;
va009039 0:1ed23ab1345f 555 return 1;
va009039 0:1ed23ab1345f 556 }
va009039 0:1ed23ab1345f 557 return 0;
va009039 0:1ed23ab1345f 558 }
va009039 0:1ed23ab1345f 559 int sdp_record_matches_service_search_pattern(uint8_t *record, uint8_t *serviceSearchPattern){
va009039 0:1ed23ab1345f 560 struct sdp_context_match_pattern context;
va009039 0:1ed23ab1345f 561 context.record = record;
va009039 0:1ed23ab1345f 562 context.result = 1;
va009039 0:1ed23ab1345f 563 de_traverse_sequence(serviceSearchPattern, sdp_traversal_match_pattern, &context);
va009039 0:1ed23ab1345f 564 return context.result;
va009039 0:1ed23ab1345f 565 }
va009039 0:1ed23ab1345f 566
va009039 0:1ed23ab1345f 567 // MARK: Dump DataElement
va009039 0:1ed23ab1345f 568 // context { indent }
va009039 0:1ed23ab1345f 569 static int de_traversal_dump_data(uint8_t * element, de_type_t de_type, de_size_t de_size, void *my_context){
va009039 0:1ed23ab1345f 570 int indent = *(int*) my_context;
va009039 0:1ed23ab1345f 571 int i;
va009039 0:1ed23ab1345f 572 for (i=0; i<indent;i++) printf(" ");
va009039 0:1ed23ab1345f 573 int pos = de_get_header_size(element);
va009039 0:1ed23ab1345f 574 int end_pos = de_get_len(element);
va009039 0:1ed23ab1345f 575 printf("type %5s (%u), element len %2u ", type_names[de_type], de_type, end_pos);
va009039 0:1ed23ab1345f 576 if (de_type == DE_DES) {
va009039 0:1ed23ab1345f 577 printf("\n");
va009039 0:1ed23ab1345f 578 indent++;
va009039 0:1ed23ab1345f 579 de_traverse_sequence(element, de_traversal_dump_data, (void *)&indent);
va009039 0:1ed23ab1345f 580 } else if (de_type == DE_UUID && de_size == DE_SIZE_128) {
va009039 0:1ed23ab1345f 581 printf(", value: ");
va009039 0:1ed23ab1345f 582 printUUID(element+1);
va009039 0:1ed23ab1345f 583 printf("\n");
va009039 0:1ed23ab1345f 584 } else if (de_type == DE_STRING) {
va009039 0:1ed23ab1345f 585 int len = 0;
va009039 0:1ed23ab1345f 586 switch (de_size){
va009039 0:1ed23ab1345f 587 case DE_SIZE_VAR_8:
va009039 0:1ed23ab1345f 588 len = element[1];
va009039 0:1ed23ab1345f 589 break;
va009039 0:1ed23ab1345f 590 case DE_SIZE_VAR_16:
va009039 0:1ed23ab1345f 591 len = READ_NET_16(element, 1);
va009039 0:1ed23ab1345f 592 break;
va009039 0:1ed23ab1345f 593 default:
va009039 0:1ed23ab1345f 594 break;
va009039 0:1ed23ab1345f 595 }
va009039 0:1ed23ab1345f 596 printf("len %u (0x%02x)\n", len, len);
va009039 0:1ed23ab1345f 597 hexdump(&element[pos], len);
va009039 0:1ed23ab1345f 598 } else {
va009039 0:1ed23ab1345f 599 uint32_t value = 0;
va009039 0:1ed23ab1345f 600 switch (de_size) {
va009039 0:1ed23ab1345f 601 case DE_SIZE_8:
va009039 0:1ed23ab1345f 602 if (de_type != DE_NIL){
va009039 0:1ed23ab1345f 603 value = element[pos];
va009039 0:1ed23ab1345f 604 }
va009039 0:1ed23ab1345f 605 break;
va009039 0:1ed23ab1345f 606 case DE_SIZE_16:
va009039 0:1ed23ab1345f 607 value = READ_NET_16(element,pos);
va009039 0:1ed23ab1345f 608 break;
va009039 0:1ed23ab1345f 609 case DE_SIZE_32:
va009039 0:1ed23ab1345f 610 value = READ_NET_32(element,pos);
va009039 0:1ed23ab1345f 611 break;
va009039 0:1ed23ab1345f 612 default:
va009039 0:1ed23ab1345f 613 break;
va009039 0:1ed23ab1345f 614 }
va009039 0:1ed23ab1345f 615 printf(", value: 0x%08" PRIx32 "\n", value);
va009039 0:1ed23ab1345f 616 }
va009039 0:1ed23ab1345f 617 return 0;
va009039 0:1ed23ab1345f 618 }
va009039 0:1ed23ab1345f 619
va009039 0:1ed23ab1345f 620 void de_dump_data_element(uint8_t * record){
va009039 0:1ed23ab1345f 621 int indent = 0;
va009039 0:1ed23ab1345f 622 // hack to get root DES, too.
va009039 0:1ed23ab1345f 623 de_type_t type = de_get_element_type(record);
va009039 0:1ed23ab1345f 624 de_size_t size = de_get_size_type(record);
va009039 0:1ed23ab1345f 625 de_traversal_dump_data(record, type, size, (void*) &indent);
va009039 0:1ed23ab1345f 626 }
va009039 0:1ed23ab1345f 627
va009039 0:1ed23ab1345f 628 void sdp_create_spp_service(uint8_t *service, int service_id, const char *name){
va009039 0:1ed23ab1345f 629
va009039 0:1ed23ab1345f 630 uint8_t* attribute;
va009039 0:1ed23ab1345f 631 de_create_sequence(service);
va009039 0:1ed23ab1345f 632
va009039 0:1ed23ab1345f 633 // 0x0000 "Service Record Handle"
va009039 0:1ed23ab1345f 634 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceRecordHandle);
va009039 0:1ed23ab1345f 635 de_add_number(service, DE_UINT, DE_SIZE_32, 0x10001);
va009039 0:1ed23ab1345f 636
va009039 0:1ed23ab1345f 637 // 0x0001 "Service Class ID List"
va009039 0:1ed23ab1345f 638 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ServiceClassIDList);
va009039 0:1ed23ab1345f 639 attribute = de_push_sequence(service);
va009039 0:1ed23ab1345f 640 {
va009039 0:1ed23ab1345f 641 de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1101 );
va009039 0:1ed23ab1345f 642 }
va009039 0:1ed23ab1345f 643 de_pop_sequence(service, attribute);
va009039 0:1ed23ab1345f 644
va009039 0:1ed23ab1345f 645 // 0x0004 "Protocol Descriptor List"
va009039 0:1ed23ab1345f 646 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_ProtocolDescriptorList);
va009039 0:1ed23ab1345f 647 attribute = de_push_sequence(service);
va009039 0:1ed23ab1345f 648 {
va009039 0:1ed23ab1345f 649 uint8_t* l2cpProtocol = de_push_sequence(attribute);
va009039 0:1ed23ab1345f 650 {
va009039 0:1ed23ab1345f 651 de_add_number(l2cpProtocol, DE_UUID, DE_SIZE_16, 0x0100);
va009039 0:1ed23ab1345f 652 }
va009039 0:1ed23ab1345f 653 de_pop_sequence(attribute, l2cpProtocol);
va009039 0:1ed23ab1345f 654
va009039 0:1ed23ab1345f 655 uint8_t* rfcomm = de_push_sequence(attribute);
va009039 0:1ed23ab1345f 656 {
va009039 0:1ed23ab1345f 657 de_add_number(rfcomm, DE_UUID, DE_SIZE_16, 0x0003); // rfcomm_service
va009039 0:1ed23ab1345f 658 de_add_number(rfcomm, DE_UINT, DE_SIZE_8, service_id); // rfcomm channel
va009039 0:1ed23ab1345f 659 }
va009039 0:1ed23ab1345f 660 de_pop_sequence(attribute, rfcomm);
va009039 0:1ed23ab1345f 661 }
va009039 0:1ed23ab1345f 662 de_pop_sequence(service, attribute);
va009039 0:1ed23ab1345f 663
va009039 0:1ed23ab1345f 664 // 0x0005 "Public Browse Group"
va009039 0:1ed23ab1345f 665 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BrowseGroupList); // public browse group
va009039 0:1ed23ab1345f 666 attribute = de_push_sequence(service);
va009039 0:1ed23ab1345f 667 {
va009039 0:1ed23ab1345f 668 de_add_number(attribute, DE_UUID, DE_SIZE_16, 0x1002 );
va009039 0:1ed23ab1345f 669 }
va009039 0:1ed23ab1345f 670 de_pop_sequence(service, attribute);
va009039 0:1ed23ab1345f 671
va009039 0:1ed23ab1345f 672 // 0x0006
va009039 0:1ed23ab1345f 673 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_LanguageBaseAttributeIDList);
va009039 0:1ed23ab1345f 674 attribute = de_push_sequence(service);
va009039 0:1ed23ab1345f 675 {
va009039 0:1ed23ab1345f 676 de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x656e);
va009039 0:1ed23ab1345f 677 de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x006a);
va009039 0:1ed23ab1345f 678 de_add_number(attribute, DE_UINT, DE_SIZE_16, 0x0100);
va009039 0:1ed23ab1345f 679 }
va009039 0:1ed23ab1345f 680 de_pop_sequence(service, attribute);
va009039 0:1ed23ab1345f 681
va009039 0:1ed23ab1345f 682 // 0x0009 "Bluetooth Profile Descriptor List"
va009039 0:1ed23ab1345f 683 de_add_number(service, DE_UINT, DE_SIZE_16, SDP_BluetoothProfileDescriptorList);
va009039 0:1ed23ab1345f 684 attribute = de_push_sequence(service);
va009039 0:1ed23ab1345f 685 {
va009039 0:1ed23ab1345f 686 uint8_t *sppProfile = de_push_sequence(attribute);
va009039 0:1ed23ab1345f 687 {
va009039 0:1ed23ab1345f 688 de_add_number(sppProfile, DE_UUID, DE_SIZE_16, 0x1101);
va009039 0:1ed23ab1345f 689 de_add_number(sppProfile, DE_UINT, DE_SIZE_16, 0x0100);
va009039 0:1ed23ab1345f 690 }
va009039 0:1ed23ab1345f 691 de_pop_sequence(attribute, sppProfile);
va009039 0:1ed23ab1345f 692 }
va009039 0:1ed23ab1345f 693 de_pop_sequence(service, attribute);
va009039 0:1ed23ab1345f 694
va009039 0:1ed23ab1345f 695 // 0x0100 "ServiceName"
va009039 0:1ed23ab1345f 696 de_add_number(service, DE_UINT, DE_SIZE_16, 0x0100);
va009039 0:1ed23ab1345f 697 de_add_data(service, DE_STRING, strlen(name), (uint8_t *) name);
va009039 0:1ed23ab1345f 698 }