1.\" $NetBSD: sdp_data.3,v 1.3 2009/05/21 09:23:50 wiz Exp $ 2.\" 3.\" Copyright (c) 2009 The NetBSD Foundation, Inc. 4.\" All rights reserved. 5.\" 6.\" This code is derived from software contributed to The NetBSD Foundation 7.\" by Iain Hibbert. 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 18.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28.\" SUCH DAMAGE. 29.\" 30.Dd May 7, 2009 31.Dt SDP_DATA 3 32.Os 33.Sh NAME 34.Nm sdp_match_uuid16 35.Nm sdp_get_data 36.Nm sdp_get_attr 37.Nm sdp_get_uuid 38.Nm sdp_get_bool 39.Nm sdp_get_seq 40.Nm sdp_get_alt 41.Nm sdp_get_uint 42.Nm sdp_get_int 43.Nm sdp_get_str 44.Nm sdp_get_url 45.Nm sdp_put_data 46.Nm sdp_put_attr 47.Nm sdp_put_uuid 48.Nm sdp_put_uuid16 49.Nm sdp_put_uuid32 50.Nm sdp_put_uuid128 51.Nm sdp_put_bool 52.Nm sdp_put_uint 53.Nm sdp_put_uint8 54.Nm sdp_put_uint16 55.Nm sdp_put_uint32 56.Nm sdp_put_uint64 57.Nm sdp_put_int 58.Nm sdp_put_int8 59.Nm sdp_put_int16 60.Nm sdp_put_int32 61.Nm sdp_put_int64 62.Nm sdp_put_seq 63.Nm sdp_put_alt 64.Nm sdp_put_str 65.Nm sdp_put_url 66.Nm sdp_set_bool 67.Nm sdp_set_uint 68.Nm sdp_set_int 69.Nm sdp_set_seq 70.Nm sdp_set_alt 71.Nm sdp_data_size 72.Nm sdp_data_type 73.Nm sdp_data_valid 74.Nm sdp_data_print 75.Nd Service Discovery Protocol data manipulation routines 76.Sh LIBRARY 77.Lb libbluetooth 78.Sh SYNOPSIS 79.In sdp.h 80.Vt extern const uuid_t BLUETOOTH_BASE_UUID ; 81.Ft bool 82.Fn sdp_match_uuid16 "sdp_data_t *data" "uint16_t uuid" 83.Ft bool 84.Fn sdp_get_data "sdp_data_t *data" "sdp_data_t *value" 85.Ft bool 86.Fn sdp_get_attr "sdp_data_t *data" "uint16_t *attr" "sdp_data_t *value" 87.Ft bool 88.Fn sdp_get_uuid "sdp_data_t *data" "uuid_t *uuid" 89.Ft bool 90.Fn sdp_get_bool "sdp_data_t *data" "bool *value" 91.Ft bool 92.Fn sdp_get_seq "sdp_data_t *data" "sdp_data_t *seq" 93.Ft bool 94.Fn sdp_get_alt "sdp_data_t *data" "sdp_data_t *alt" 95.Ft bool 96.Fn sdp_get_uint "sdp_data_t *data" "uintmax_t *value" 97.Ft bool 98.Fn sdp_get_int "sdp_data_t *data" "intmax_t *value" 99.Ft bool 100.Fn sdp_get_str "sdp_data_t *data" "char **str" "size_t *length" 101.Ft bool 102.Fn sdp_get_url "sdp_data_t *data" "char **url" "size_t *length" 103.Ft bool 104.Fn sdp_put_data "sdp_data_t *data" "sdp_data_t *value" 105.Ft bool 106.Fn sdp_put_attr "sdp_data_t *data" "uint16_t attr" "sdp_data_t *value" 107.Ft bool 108.Fn sdp_put_uuid "sdp_data_t *data" "const uuid_t *value" 109.Ft bool 110.Fn sdp_put_uuid16 "sdp_data_t *data" "uint16_t value" 111.Ft bool 112.Fn sdp_put_uuid32 "sdp_data_t *data" "uint32_t value" 113.Ft bool 114.Fn sdp_put_uuid128 "sdp_data_t *data" "const uuid_t *value" 115.Ft bool 116.Fn sdp_put_bool "sdp_data_t *data" "bool value" 117.Ft bool 118.Fn sdp_put_uint "sdp_data_t *data" "uintmax_t value" 119.Ft bool 120.Fn sdp_put_uint8 "sdp_data_t *data" "uint8_t value" 121.Ft bool 122.Fn sdp_put_uint16 "sdp_data_t *data" "uint16_t value" 123.Ft bool 124.Fn sdp_put_uint32 "sdp_data_t *data" "uint32_t value" 125.Ft bool 126.Fn sdp_put_int "sdp_data_t *data" "intmax_t value" 127.Ft bool 128.Fn sdp_put_int8 "sdp_data_t *data" "int8_t value" 129.Ft bool 130.Fn sdp_put_int16 "sdp_data_t *data" "int16_t value" 131.Ft bool 132.Fn sdp_put_int32 "sdp_data_t *data" "int32_t value" 133.Ft bool 134.Fn sdp_put_seq "sdp_data_t *data" "ssize_t length" 135.Ft bool 136.Fn sdp_put_alt "sdp_data_t *data" "ssize_t length" 137.Ft bool 138.Fn sdp_put_str "sdp_data_t *data" "const char *str" "ssize_t length" 139.Ft bool 140.Fn sdp_put_url "sdp_data_t *data" "const char *url" "ssize_t length" 141.Ft bool 142.Fn sdp_set_bool "const sdp_data_t *data" "bool value" 143.Ft bool 144.Fn sdp_set_uint "const sdp_data_t *data" "uintmax_t value" 145.Ft bool 146.Fn sdp_set_int "const sdp_data_t *data" "intmax_t value" 147.Ft bool 148.Fn sdp_set_seq "const sdp_data_t *data" "ssize_t length" 149.Ft ssize_t 150.Fn sdp_data_size "const sdp_data_t *data" 151.Ft int 152.Fn sdp_data_type "const sdp_data_t *data" 153.Ft bool 154.Fn sdp_data_valid "const sdp_data_t *data" 155.Ft void 156.Fn sdp_data_print "const sdp_data_t *data" "int indent" 157.Sh DESCRIPTION 158These routines provide for the manipulation of Service Discovery 159Protocol data buffers. 160An SDP data buffer type is defined as: 161.Bd -literal -offset indent 162typedef struct { 163 uint8_t *next; 164 uint8_t *end; 165} sdp_data_t; 166.Ed 167.Pp 168Where 169.Fa next 170points to the next available byte, and 171.Fa end 172points to the first address past end of the data area, such that 173.Qq end = next + length . 174.Pp 175The SDP data consists of byte streams describing data elements, where 176a data element is a typed data representation consisting of a header 177field and a data field. 178The header field consists of type and size descriptors, and the data 179field is a sequence of bytes whose length is specified in the size 180descriptor and whose content is specified by the type descriptor. 181For instance, the byte sequence 182.Qq 0x09, 0x01, 0x00 183describes an 16-bit unsigned integer element (type 0x09) with 184value of 0x0100. 185.Pp 186Data element types including signed and unsigned integers, boolean, 187string, sequence and alternative lists are defined in the 188.In sdp.h 189include file. 190See the 191.Qq Service Discovery Protocol 192chapters of the 193.Qq Bluetooth Core Specifications 194for more information. 195.Pp 196To reduce the burden of storing and transferring 128-bit UUID values, a 197range of UUID values has been pre-allocated for assignment to often-used, 198registered purposes. 199The first UUID in this pre-allocated range is known as the 200.Qq Bluetooth Base UUID , 201defined in the 202.Qq Bluetooth Assigned Numbers 203document and declared in 204.In sdp.h 205as 206.Vt const uuid_t BLUETOOTH_BASE_UUID ; 207.Pp 208The data manipulation routines are arranged into major groups 209by function: 210.Bl -hang 211.It The Fn sdp_match_uuid16 212routine examines the next data element in the data buffer for 213an element of type UUID that matches the Bluetooth short alias 214UUID with 16-bit value given. 215If the UUID matches, the function will return 216.Dv true 217and the 218.Fa next 219field of the SDP data buffer will be advanced to the next element. 220Otherwise 221.Dv false 222will be returned. 223.It The Fn sdp_get_xxxx 224routines examine the next data element in the data buffer for an 225element of the given type. 226If the type matches, the function will extract the typed value to 227the address given and advance the 228.Fa next 229field of the SDP data buffer to the next element then return 230.Dv true . 231Otherwise 232.Dv false 233will be returned. 234Note, these functions will not modify the 235.Fa data 236argument unless the correct type was found, and will update the 237.Fa data 238argument first to allow discarding in the case where a 239.Dv sdp_data_t 240was being returned. 241.It The Fn sdp_put_xxxx 242routines will attempt to write a data element of the given type 243and value to the data buffer. 244If the data buffer is too small to contain the encoded data element, 245the function will return 246.Dv false , 247otherwise 248.Dv true 249will be returned and the 250.Fa next 251field of the SDP data pointer will be advanced. 252In the case of 253.Fn sdp_put_seq 254and 255.Fn sdp_put_alt , 256the 257.Fa length 258argument may be -1, in which case the generated sequence header will 259describe all the remaining buffer space. 260For 261.Fn sdp_put_str 262and 263.Fn sdp_put_url 264the 265.Fa length 266argument may be -1 in which case the string pointer is treated as 267nul terminated. 268.It The Fn sdp_set_xxxx 269routines examine the SDP data buffer for a data element of the given 270type, and replace the content with the passed value. 271If the next data element in the buffer is not of the appropriate 272type, the function will return 273.Dv false , 274otherwise 275.Dv true 276will be returned and the value updated. 277In the case of 278.Fn sdp_set_seq 279and 280.Fn sdp_set_alt , 281the 282.Fa length 283argument may be -1, in which case the sequence header will be 284adjusted to describe the entire data space where possible. 285.It The Fn sdp_data_xxxx 286routines include various functions to provide information about 287the data stream such as 288.Fn sdp_data_size 289to return the size of the next data element, and 290.Fn sdp_data_type 291to return the type of the next data element. 292.Fn sdp_data_valid 293can be used to ensure that the entire data buffer contains 294valid SDP data elements and that all of the elements are contained 295exactly within the data buffer. 296Finally, 297.Fn sdp_data_print 298will print the data buffer in human readable format. 299.El 300.Sh EXAMPLES 301To parse a ServiceAttribute response obtained from a remote server 302using 303.Xr sdp_service_attribute 3 , 304examining various attribute values: 305.Bd -literal 306 sdp_data_t rsp, val; 307 uint16_t attr; 308 uintmax_t handle; 309 310 /* rsp contains remote response */ 311 312 /* discard sequence header */ 313 if (!sdp_get_seq(\*[Am]rsp, \*[Am]rsp)) 314 err(EXIT_FAILURE, "response is not a sequence"); 315 316 while (sdp_get_attr(\*[Am]rsp, \*[Am]attr, \*[Am]val)) { 317 switch(attr) { 318 case SDP_ATTR_SERVICE_RECORD_HANDLE: 319 sdp_get_uint(\*[Am]val, \*[Am]handle); 320 printf("ServiceRecordHandle: 0x%08x\\n", handle); 321 break; 322 323 case SDP_ATTR_PROFILE_DESCRIPTOR_LIST: 324 printf("ProfileDescriptorList:\\n"); 325 sdp_data_print(\*[Am]val, 0); 326 break; 327 328 default: 329 printf("uninteresting attribute 0x%04x\\n", attr); 330 break; 331 } 332 } 333 334.Ed 335The following code creates a ProtocolDataList attribute value for a service 336using the L2CAP and RFCOMM protocols and illustrates how to construct sequences 337of known and unknown length. 338.Bd -literal 339 uint8_t buf[SIZE]; 340 sdp_data_t seq; 341 uint16_t psm; 342 uint8_t channel; 343 344 seq.next = buf; 345 seq.end = buf + sizeof(buf); 346 sdp_put_seq(\*[Am]seq, -1); 347 348 sdp_put_seq(\*[Am]seq, 6); 349 sdp_put_uuid16(\*[Am]seq, SDP_UUID_PROTOCOL_L2CAP); 350 sdp_put_uint16(\*[Am]seq, psm); 351 352 sdp_put_seq(\*[Am]seq, 5); 353 sdp_put_uuid16(\*[Am]seq, SDP_UUID_PROTOCOL_RFCOMM); 354 sdp_put_uint8(\*[Am]seq, channel); 355 356 seq.end = seq.next; 357 seq.next = buf; 358 sdp_set_seq(\*[Am]seq, -1); 359.Ed 360.Pp 361Note that although 362.Dv SIZE 363is assumed to be large enough to contain the entire sequence 364in this case, the 365.Fn sdp_put_xxxx 366routines will not overflow the buffer area or write partial data. 367.Pp 368The encoded data stream will be stored in a space efficient 369manner where possible. 370In the above example, it is known that the data element sequence 371containing the L2CAP UUID will be 8 bytes long overall since the 372container length of 6 can be stored in a single byte. 373But, because the value of 374.Dv SIZE 375is unknown, the overall length of the ProtocolDataList may vary 376depending if 8, 16 or 32 bits were needed to represent the original 377buffer size. 378.Fn sdp_seq_seq 379will only modify the content, not the size of the header. 380.Sh SEE ALSO 381.Xr sdpquery 1 , 382.Xr bluetooth 3 , 383.Xr sdp 3 , 384.Xr uuid 3 , 385.Xr sdpd 8 386.Pp 387The 388.Qq Service Discovery Protocol 389section of the Bluetooth Core specifications, available at 390.Qq http://www.bluetooth.com/ 391.Sh HISTORY 392These SDP data parsing and manipulation functions first appeared in 393.Nx 6.0 . 394