うおーるぼっとをWiiリモコンでコントロールする新しいプログラムです。 以前のものより、Wiiリモコンが早く繋がる様になりました。 It is a program which controls A with the Wii remote. ※ A Bluetooth dongle and a Wii remote control are needed.

Dependencies:   USBHost mbed FATFileSystem mbed-rtos

Committer:
jksoft
Date:
Mon Jun 10 16:01:50 2013 +0000
Revision:
0:fccb789424fc
1.0

Who changed what in which revision?

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