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