うおーるぼっとを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
btstack/sdp_util.c@0:fccb789424fc, 2013-06-10 (annotated)
- Committer:
- jksoft
- Date:
- Mon Jun 10 16:01:50 2013 +0000
- Revision:
- 0:fccb789424fc
1.0
Who changed what in which revision?
User | Revision | Line number | New 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 | } |