Annotation of src/lib/libbluetooth/sdp_data.3, Revision 1.7
1.7 ! plunky 1: .\" $NetBSD: sdp_data.3,v 1.6 2010/12/16 10:08:27 wiz Exp $
1.1 plunky 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: .\"
1.7 ! plunky 30: .Dd January 15, 2011
1.1 plunky 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
1.7 ! plunky 126: .Fn sdp_put_uint64 "sdp_data_t *data" "uint64_t value"
! 127: .Ft bool
1.1 plunky 128: .Fn sdp_put_int "sdp_data_t *data" "intmax_t value"
129: .Ft bool
130: .Fn sdp_put_int8 "sdp_data_t *data" "int8_t value"
131: .Ft bool
132: .Fn sdp_put_int16 "sdp_data_t *data" "int16_t value"
133: .Ft bool
134: .Fn sdp_put_int32 "sdp_data_t *data" "int32_t value"
135: .Ft bool
1.7 ! plunky 136: .Fn sdp_put_int64 "sdp_data_t *data" "int64_t value"
! 137: .Ft bool
1.1 plunky 138: .Fn sdp_put_seq "sdp_data_t *data" "ssize_t length"
139: .Ft bool
140: .Fn sdp_put_alt "sdp_data_t *data" "ssize_t length"
141: .Ft bool
142: .Fn sdp_put_str "sdp_data_t *data" "const char *str" "ssize_t length"
143: .Ft bool
144: .Fn sdp_put_url "sdp_data_t *data" "const char *url" "ssize_t length"
145: .Ft bool
146: .Fn sdp_set_bool "const sdp_data_t *data" "bool value"
147: .Ft bool
148: .Fn sdp_set_uint "const sdp_data_t *data" "uintmax_t value"
149: .Ft bool
150: .Fn sdp_set_int "const sdp_data_t *data" "intmax_t value"
151: .Ft bool
152: .Fn sdp_set_seq "const sdp_data_t *data" "ssize_t length"
153: .Ft ssize_t
154: .Fn sdp_data_size "const sdp_data_t *data"
155: .Ft int
156: .Fn sdp_data_type "const sdp_data_t *data"
157: .Ft bool
158: .Fn sdp_data_valid "const sdp_data_t *data"
159: .Ft void
160: .Fn sdp_data_print "const sdp_data_t *data" "int indent"
161: .Sh DESCRIPTION
162: These routines provide for the manipulation of Service Discovery
163: Protocol data buffers.
164: An SDP data buffer type is defined as:
165: .Bd -literal -offset indent
166: typedef struct {
167: uint8_t *next;
168: uint8_t *end;
169: } sdp_data_t;
170: .Ed
171: .Pp
172: Where
1.2 plunky 173: .Fa next
1.1 plunky 174: points to the next available byte, and
1.2 plunky 175: .Fa end
1.1 plunky 176: points to the first address past end of the data area, such that
177: .Qq end = next + length .
178: .Pp
179: The SDP data consists of byte streams describing data elements, where
180: a data element is a typed data representation consisting of a header
181: field and a data field.
182: The header field consists of type and size descriptors, and the data
183: field is a sequence of bytes whose length is specified in the size
184: descriptor and whose content is specified by the type descriptor.
185: For instance, the byte sequence
186: .Qq 0x09, 0x01, 0x00
187: describes an 16-bit unsigned integer element (type 0x09) with
188: value of 0x0100.
189: .Pp
190: Data element types including signed and unsigned integers, boolean,
191: string, sequence and alternative lists are defined in the
192: .In sdp.h
193: include file.
194: See the
195: .Qq Service Discovery Protocol
196: chapters of the
197: .Qq Bluetooth Core Specifications
198: for more information.
199: .Pp
200: To reduce the burden of storing and transferring 128-bit UUID values, a
201: range of UUID values has been pre-allocated for assignment to often-used,
1.3 wiz 202: registered purposes.
203: The first UUID in this pre-allocated range is known as the
1.1 plunky 204: .Qq Bluetooth Base UUID ,
205: defined in the
206: .Qq Bluetooth Assigned Numbers
207: document and declared in
208: .In sdp.h
209: as
210: .Vt const uuid_t BLUETOOTH_BASE_UUID ;
211: .Pp
212: The data manipulation routines are arranged into major groups
213: by function:
214: .Bl -hang
215: .It The Fn sdp_match_uuid16
216: routine examines the next data element in the data buffer for
217: an element of type UUID that matches the Bluetooth short alias
218: UUID with 16-bit value given.
219: If the UUID matches, the function will return
220: .Dv true
221: and the
1.2 plunky 222: .Fa next
1.1 plunky 223: field of the SDP data buffer will be advanced to the next element.
224: Otherwise
225: .Dv false
226: will be returned.
227: .It The Fn sdp_get_xxxx
228: routines examine the next data element in the data buffer for an
229: element of the given type.
230: If the type matches, the function will extract the typed value to
231: the address given and advance the
1.2 plunky 232: .Fa next
1.1 plunky 233: field of the SDP data buffer to the next element then return
234: .Dv true .
235: Otherwise
236: .Dv false
237: will be returned.
238: Note, these functions will not modify the
1.2 plunky 239: .Fa data
1.1 plunky 240: argument unless the correct type was found, and will update the
1.2 plunky 241: .Fa data
1.1 plunky 242: argument first to allow discarding in the case where a
243: .Dv sdp_data_t
244: was being returned.
245: .It The Fn sdp_put_xxxx
246: routines will attempt to write a data element of the given type
247: and value to the data buffer.
248: If the data buffer is too small to contain the encoded data element,
249: the function will return
250: .Dv false ,
251: otherwise
252: .Dv true
253: will be returned and the
1.2 plunky 254: .Fa next
1.1 plunky 255: field of the SDP data pointer will be advanced.
256: In the case of
257: .Fn sdp_put_seq
258: and
259: .Fn sdp_put_alt ,
260: the
1.2 plunky 261: .Fa length
1.1 plunky 262: argument may be -1, in which case the generated sequence header will
263: describe all the remaining buffer space.
264: For
265: .Fn sdp_put_str
266: and
267: .Fn sdp_put_url
268: the
1.2 plunky 269: .Fa length
1.1 plunky 270: argument may be -1 in which case the string pointer is treated as
271: nul terminated.
272: .It The Fn sdp_set_xxxx
273: routines examine the SDP data buffer for a data element of the given
274: type, and replace the content with the passed value.
275: If the next data element in the buffer is not of the appropriate
276: type, the function will return
277: .Dv false ,
278: otherwise
279: .Dv true
280: will be returned and the value updated.
281: In the case of
282: .Fn sdp_set_seq
283: and
284: .Fn sdp_set_alt ,
285: the
1.2 plunky 286: .Fa length
1.1 plunky 287: argument may be -1, in which case the sequence header will be
288: adjusted to describe the entire data space where possible.
289: .It The Fn sdp_data_xxxx
290: routines include various functions to provide information about
291: the data stream such as
292: .Fn sdp_data_size
293: to return the size of the next data element, and
294: .Fn sdp_data_type
295: to return the type of the next data element.
296: .Fn sdp_data_valid
297: can be used to ensure that the entire data buffer contains
298: valid SDP data elements and that all of the elements are contained
299: exactly within the data buffer.
300: Finally,
301: .Fn sdp_data_print
302: will print the data buffer in human readable format.
303: .El
304: .Sh EXAMPLES
305: To parse a ServiceAttribute response obtained from a remote server
306: using
307: .Xr sdp_service_attribute 3 ,
308: examining various attribute values:
309: .Bd -literal
310: sdp_data_t rsp, val;
311: uint16_t attr;
312: uintmax_t handle;
313:
314: /* rsp contains remote response */
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: .Ed
1.4 plunky 334: .Pp
1.1 plunky 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.
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
361: Note that although
362: .Dv SIZE
363: is assumed to be large enough to contain the entire sequence
364: in this case, the
365: .Fn sdp_put_xxxx
366: routines will not overflow the buffer area or write partial data.
367: .Pp
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
374: .Dv SIZE
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
377: buffer size.
378: .Fn sdp_seq_seq
379: will 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
387: The
388: .Qq Service Discovery Protocol
389: section of the Bluetooth Core specifications, available at
390: .Qq http://www.bluetooth.com/
391: .Sh HISTORY
392: These SDP data parsing and manipulation functions first appeared in
393: .Nx 6.0 .
CVSweb <webmaster@jp.NetBSD.org>