xref: /netbsd-src/lib/libbluetooth/sdp_data.3 (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
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