1 .\" $NetBSD: sdp_data.3,v 1.2 2009/05/20 17:22:56 plunky Exp $
3 .\" Copyright (c) 2009 The NetBSD Foundation, Inc.
4 .\" All rights reserved.
6 .\" This code is derived from software contributed to The NetBSD Foundation
9 .\" Redistribution and use in source and binary forms, with or without
10 .\" modification, are permitted provided that the following conditions
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.
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
75 .Nd Service Discovery Protocol data manipulation routines
80 .Vt extern const uuid_t BLUETOOTH_BASE_UUID ;
82 .Fn sdp_match_uuid16 "sdp_data_t *data" "uint16_t uuid"
84 .Fn sdp_get_data "sdp_data_t *data" "sdp_data_t *value"
86 .Fn sdp_get_attr "sdp_data_t *data" "uint16_t *attr" "sdp_data_t *value"
88 .Fn sdp_get_uuid "sdp_data_t *data" "uuid_t *uuid"
90 .Fn sdp_get_bool "sdp_data_t *data" "bool *value"
92 .Fn sdp_get_seq "sdp_data_t *data" "sdp_data_t *seq"
94 .Fn sdp_get_alt "sdp_data_t *data" "sdp_data_t *alt"
96 .Fn sdp_get_uint "sdp_data_t *data" "uintmax_t *value"
98 .Fn sdp_get_int "sdp_data_t *data" "intmax_t *value"
100 .Fn sdp_get_str "sdp_data_t *data" "char **str" "size_t *length"
102 .Fn sdp_get_url "sdp_data_t *data" "char **url" "size_t *length"
104 .Fn sdp_put_data "sdp_data_t *data" "sdp_data_t *value"
106 .Fn sdp_put_attr "sdp_data_t *data" "uint16_t attr" "sdp_data_t *value"
108 .Fn sdp_put_uuid "sdp_data_t *data" "const uuid_t *value"
110 .Fn sdp_put_uuid16 "sdp_data_t *data" "uint16_t value"
112 .Fn sdp_put_uuid32 "sdp_data_t *data" "uint32_t value"
114 .Fn sdp_put_uuid128 "sdp_data_t *data" "const uuid_t *value"
116 .Fn sdp_put_bool "sdp_data_t *data" "bool value"
118 .Fn sdp_put_uint "sdp_data_t *data" "uintmax_t value"
120 .Fn sdp_put_uint8 "sdp_data_t *data" "uint8_t value"
122 .Fn sdp_put_uint16 "sdp_data_t *data" "uint16_t value"
124 .Fn sdp_put_uint32 "sdp_data_t *data" "uint32_t value"
126 .Fn sdp_put_int "sdp_data_t *data" "intmax_t value"
128 .Fn sdp_put_int8 "sdp_data_t *data" "int8_t value"
130 .Fn sdp_put_int16 "sdp_data_t *data" "int16_t value"
132 .Fn sdp_put_int32 "sdp_data_t *data" "int32_t value"
134 .Fn sdp_put_seq "sdp_data_t *data" "ssize_t length"
136 .Fn sdp_put_alt "sdp_data_t *data" "ssize_t length"
138 .Fn sdp_put_str "sdp_data_t *data" "const char *str" "ssize_t length"
140 .Fn sdp_put_url "sdp_data_t *data" "const char *url" "ssize_t length"
142 .Fn sdp_set_bool "const sdp_data_t *data" "bool value"
144 .Fn sdp_set_uint "const sdp_data_t *data" "uintmax_t value"
146 .Fn sdp_set_int "const sdp_data_t *data" "intmax_t value"
148 .Fn sdp_set_seq "const sdp_data_t *data" "ssize_t length"
150 .Fn sdp_data_size "const sdp_data_t *data"
152 .Fn sdp_data_type "const sdp_data_t *data"
154 .Fn sdp_data_valid "const sdp_data_t *data"
156 .Fn sdp_data_print "const sdp_data_t *data" "int indent"
158 These routines provide for the manipulation of Service Discovery
159 Protocol data buffers.
160 An SDP data buffer type is defined as:
161 .Bd -literal -offset indent
170 points to the next available byte, and
172 points to the first address past end of the data area, such that
173 .Qq end = next + length .
175 The SDP data consists of byte streams describing data elements, where
176 a data element is a typed data representation consisting of a header
177 field and a data field.
178 The header field consists of type and size descriptors, and the data
179 field is a sequence of bytes whose length is specified in the size
180 descriptor and whose content is specified by the type descriptor.
181 For instance, the byte sequence
183 describes an 16-bit unsigned integer element (type 0x09) with
186 Data element types including signed and unsigned integers, boolean,
187 string, sequence and alternative lists are defined in the
191 .Qq Service Discovery Protocol
193 .Qq Bluetooth Core Specifications
194 for more information.
196 To reduce the burden of storing and transferring 128-bit UUID values, a
197 range of UUID values has been pre-allocated for assignment to often-used,
199 The first UUID in this pre-allocated range is known as the
200 .Qq Bluetooth Base UUID ,
202 .Qq Bluetooth Assigned Numbers
203 document and declared in
206 .Vt const uuid_t BLUETOOTH_BASE_UUID ;
208 The data manipulation routines are arranged into major groups
211 .It The Fn sdp_match_uuid16
212 routine examines the next data element in the data buffer for
213 an element of type UUID that matches the Bluetooth short alias
214 UUID with 16-bit value given.
215 If the UUID matches, the function will return
219 field of the SDP data buffer will be advanced to the next element.
223 .It The Fn sdp_get_xxxx
224 routines examine the next data element in the data buffer for an
225 element of the given type.
226 If the type matches, the function will extract the typed value to
227 the address given and advance the
229 field of the SDP data buffer to the next element then return
234 Note, these functions will not modify the
236 argument unless the correct type was found, and will update the
238 argument first to allow discarding in the case where a
241 .It The Fn sdp_put_xxxx
242 routines will attempt to write a data element of the given type
243 and value to the data buffer.
244 If the data buffer is too small to contain the encoded data element,
245 the function will return
249 will be returned and the
251 field of the SDP data pointer will be advanced.
258 argument may be -1, in which case the generated sequence header will
259 describe all the remaining buffer space.
266 argument may be -1 in which case the string pointer is treated as
268 .It The Fn sdp_set_xxxx
269 routines examine the SDP data buffer for a data element of the given
270 type, and replace the content with the passed value.
271 If the next data element in the buffer is not of the appropriate
272 type, the function will return
276 will be returned and the value updated.
283 argument may be -1, in which case the sequence header will be
284 adjusted to describe the entire data space where possible.
285 .It The Fn sdp_data_xxxx
286 routines include various functions to provide information about
287 the data stream such as
289 to return the size of the next data element, and
291 to return the type of the next data element.
293 can be used to ensure that the entire data buffer contains
294 valid SDP data elements and that all of the elements are contained
295 exactly within the data buffer.
298 will print the data buffer in human readable format.
301 To parse a ServiceAttribute response obtained from a remote server
303 .Xr sdp_service_attribute 3 ,
304 examining various attribute values:
310 /* rsp contains remote response */
312 /* discard sequence header */
313 if (!sdp_get_seq(\*[Am]rsp, \*[Am]rsp))
314 err(EXIT_FAILURE, "response is not a sequence");
316 while (sdp_get_attr(\*[Am]rsp, \*[Am]attr, \*[Am]val)) {
318 case SDP_ATTR_SERVICE_RECORD_HANDLE:
319 sdp_get_uint(\*[Am]val, \*[Am]handle);
320 printf("ServiceRecordHandle: 0x%08x\\n", handle);
323 case SDP_ATTR_PROFILE_DESCRIPTOR_LIST:
324 printf("ProfileDescriptorList:\\n");
325 sdp_data_print(\*[Am]val, 0);
329 printf("uninteresting attribute 0x%04x\\n", attr);
335 The following code creates a ProtocolDataList attribute value for a service
336 using the L2CAP and RFCOMM protocols and illustrates how to construct sequences
337 of known and unknown length.
345 seq.end = buf + sizeof(buf);
346 sdp_put_seq(\*[Am]seq, -1);
348 sdp_put_seq(\*[Am]seq, 6);
349 sdp_put_uuid16(\*[Am]seq, SDP_UUID_PROTOCOL_L2CAP);
350 sdp_put_uint16(\*[Am]seq, psm);
352 sdp_put_seq(\*[Am]seq, 5);
353 sdp_put_uuid16(\*[Am]seq, SDP_UUID_PROTOCOL_RFCOMM);
354 sdp_put_uint8(\*[Am]seq, channel);
358 sdp_set_seq(\*[Am]seq, -1);
363 is assumed to be large enough to contain the entire sequence
366 routines will not overflow the buffer area or write partial data.
368 The encoded data stream will be stored in a space efficient
369 manner where possible.
370 In the above example, it is known that the data element sequence
371 containing the L2CAP UUID will be 8 bytes long overall since the
372 container length of 6 can be stored in a single byte.
373 But, because the value of
375 is unknown, the overall length of the ProtocolDataList may vary
376 depending if 8, 16 or 32 bits were needed to represent the original
379 will only modify the content, not the size of the header.
388 .Qq Service Discovery Protocol
389 section of the Bluetooth Core specifications, available at
390 .Qq http://www.bluetooth.com/
392 These SDP data parsing and manipulation functions first appeared in