BTstack for Nucleo F401RE/FRDM-KL46Z example program

Dependencies:   F401RE-USBHost mbed

The usage is the same as KL46Z-BTstack_example.
使い方はKL46Z-BTstack_exampleと同じです。
/media/uploads/va009039/f401re-btstack.jpg

Committer:
va009039
Date:
Mon Jun 09 09:03:25 2014 +0000
Revision:
0:a05a07cd6fdf
first commit

Who changed what in which revision?

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