aboutsummaryrefslogtreecommitdiff
path: root/lib/libsdp
diff options
context:
space:
mode:
authorMaksim Yevmenkin <emax@FreeBSD.org>2003-10-12 22:04:24 +0000
committerMaksim Yevmenkin <emax@FreeBSD.org>2003-10-12 22:04:24 +0000
commit0986ab12e44caea472245845f9a89ced4f137d73 (patch)
tree0ae0c2be63f9f9161693789721b96beb9cabcc77 /lib/libsdp
parent907d8667501d77122c9b7016fc907f842f263bb7 (diff)
downloadsrc-0986ab12e44caea472245845f9a89ced4f137d73.tar.gz
src-0986ab12e44caea472245845f9a89ced4f137d73.zip
Update Bluetooth code.
Reviewed by: M. Warner Losh <imp@bsdimp.com>; John Hay <jhay@freebsd.org> Approved by: M. Warner Losh <imp@bsdimp.com> (mentor)
Notes
Notes: svn path=/head/; revision=121054
Diffstat (limited to 'lib/libsdp')
-rw-r--r--lib/libsdp/Makefile33
-rw-r--r--lib/libsdp/sdp-int.h65
-rw-r--r--lib/libsdp/sdp.3309
-rw-r--r--lib/libsdp/sdp.h477
-rw-r--r--lib/libsdp/search.c383
-rw-r--r--lib/libsdp/session.c174
-rw-r--r--lib/libsdp/util.c439
7 files changed, 1880 insertions, 0 deletions
diff --git a/lib/libsdp/Makefile b/lib/libsdp/Makefile
new file mode 100644
index 000000000000..4df747114eb6
--- /dev/null
+++ b/lib/libsdp/Makefile
@@ -0,0 +1,33 @@
+# $Id: Makefile,v 1.2 2003/09/07 20:34:19 max Exp $
+# $FreeBSD$
+
+LIB= sdp
+MAN= sdp.3
+
+WARNS?= 2
+CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../../sys
+
+SHLIB_MAJOR= 1
+
+SRCS= search.c session.c util.c
+INCS= sdp.h
+
+MLINKS+= sdp.3 SDP_GET8.3
+MLINKS+= sdp.3 SDP_GET16.3
+MLINKS+= sdp.3 SDP_GET32.3
+MLINKS+= sdp.3 SDP_GET64.3
+MLINKS+= sdp.3 SDP_GET128.3
+MLINKS+= sdp.3 SDP_PUT8.3
+MLINKS+= sdp.3 SDP_PUT16.3
+MLINKS+= sdp.3 SDP_PUT32.3
+MLINKS+= sdp.3 SDP_PUT64.3
+MLINKS+= sdp.3 SDP_PUT128.3
+MLINKS+= sdp.3 sdp_open.3
+MLINKS+= sdp.3 sdp_open_local.3
+MLINKS+= sdp.3 sdp_close.3
+MLINKS+= sdp.3 sdp_error.3
+MLINKS+= sdp.3 sdp_search.3
+MLINKS+= sdp.3 sdp_attr2desc.3
+MLINKS+= sdp.3 sdp_uuid2desc.3
+
+.include <bsd.lib.mk>
diff --git a/lib/libsdp/sdp-int.h b/lib/libsdp/sdp-int.h
new file mode 100644
index 000000000000..95aeb43e230c
--- /dev/null
+++ b/lib/libsdp/sdp-int.h
@@ -0,0 +1,65 @@
+/*
+ * sdp-int.h
+ *
+ * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: sdp-int.h,v 1.1 2003/09/01 23:01:07 max Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _SDP_INT_H_
+#define _SDP_INT_H_
+
+__BEGIN_DECLS
+
+#define SDP_UNSOCK_PATH "/var/run/sdp"
+#define SDP_UNSOCK_MTU 2048
+
+/*
+ * SDP session
+ */
+
+struct sdp_session {
+ u_int16_t flags;
+#define SDP_SESSION_LOCAL (1 << 0)
+ u_int16_t tid; /* current session transaction ID (tid) */
+ u_int16_t omtu; /* outgoing MTU (req buffer size) */
+ u_int16_t imtu; /* incoming MTU (rsp buffer size) */
+ u_int8_t *req; /* request buffer (start) */
+ u_int8_t *req_e; /* request buffer (end) */
+ u_int8_t *rsp; /* response buffer (start) */
+ u_int8_t *rsp_e; /* response buffer (end) */
+ u_int32_t cslen; /* continuation state length */
+ u_int8_t cs[16];/* continuation state */
+ int32_t s; /* L2CAP socket */
+ int32_t error; /* last error code */
+};
+typedef struct sdp_session sdp_session_t;
+typedef struct sdp_session * sdp_session_p;
+
+__END_DECLS
+
+#endif /* ndef _SDP_INT_H_ */
+
diff --git a/lib/libsdp/sdp.3 b/lib/libsdp/sdp.3
new file mode 100644
index 000000000000..94ef34e9d147
--- /dev/null
+++ b/lib/libsdp/sdp.3
@@ -0,0 +1,309 @@
+.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: sdp.3,v 1.1 2003/09/07 20:34:19 max Exp $
+.\" $FreeBSD$
+.\"
+.Dd September 7, 2003
+.Dt SDP 3
+.Os
+.Sh NAME
+.Nm SDP_GET8 ,
+.Nm SDP_GET16 ,
+.Nm SDP_GET32 ,
+.Nm SDP_GET64 ,
+.Nm SDP_GET128
+.Nd get SDP integer
+.Pp
+.Nm SDP_PUT8 ,
+.Nm SDP_PUT16 ,
+.Nm SDP_PUT32 ,
+.Nm SDP_PUT64 ,
+.Nm SDP_PUT128
+.Nd put SPD integer
+.Pp
+.Nm sdp_open ,
+.Nm sdp_open_local ,
+.Nm sdp_close
+.Nm sdp_error
+.Nd control SDP session
+.Pp
+.Nm sdp_search
+.Nd perform SDP query
+.Pp
+.Nm sdp_attr2desc ,
+.Nm sdp_uuid2desc
+.Nd convert numeric SDP attribute/UUID value into human readable description
+.Sh LIBRARY
+.Lb libsdp
+.Sh SYNOPSIS
+.In bluetooth.h
+.In sdp.h
+.Fn SDP_GET8 "b" "cp"
+.Fn SDP_GET16 "s" "cp"
+.Fn SDP_GET32 "l" "cp"
+.Fn SDP_GET64 "l" "cp"
+.Fn SDP_GET128 "l" "cp"
+.Fn SDP_PUT8 "b" "cp"
+.Fn SDP_PUT16 "s" "cp"
+.Fn SDP_PUT32 "l" "cp"
+.Fn SDP_PUT64 "l" "cp"
+.Fn SDP_PUT128 "l" "cp"
+.Ft void *
+.Fn sdp_open "bdaddr_t const *l" "bdaddr_t const *r"
+.Ft void *
+.Fn sdp_open_local "void"
+.Ft int32_t
+.Fn sdp_close "void *xs"
+.Ft int32_t
+.Fn sdp_error "void *xs"
+.Ft int32_t
+.Fn sdp_search "void *xs" "u_int32_t plen" "u_int16_t const *pp" "u_int32_t alen" "u_int32_t const *ap" "u_int32_t vlen" "sdp_attr_t *vp"
+.Ft char const * const
+.Fn sdp_attr2desc "u_int16_t attr"
+.Ft char const * const
+.Fn sdp_uuid2desc "u_int16_t uuid"
+.Sh DESCRIPTION
+The
+.Fn SDP_GET8 ,
+.Fn SDP_GET16 ,
+.Fn SDP_GET32 ,
+.Fn SDP_GET64
+and
+.Fn SDP_GET128
+macros are used to get byte, short, long, long long and 128-bit integer
+from the buffer pointed by
+.Vt cp
+pointer. The pointer is automatically advanced.
+.Pp
+The
+.Fn SDP_PUT8 ,
+.Fn SDP_PUT16 ,
+.Fn SDP_PUT32 ,
+.Fn SDP_PUT64
+and
+.Fn SDP_PUT128
+macros are used to put byte, short, long, long long and 128-bit integer
+into the buffer pointed by
+.Vt cp
+pointer. The pointer is automatically advanced.
+.Pp
+.Fn sdp_open
+and
+.Fn sdp_open_local
+functions each return a pointer to an opaque object describing SDP session.
+The
+.Vt l
+argument passed to
+.Fn sdp_open
+function should point to a source BD_ADDR.
+If source BD_ADDR is
+.Dv NULL
+then source address
+.Dv NG_HCI_BDADDR_ANY
+is used.
+The
+.Vt r
+argument passed to
+.Fn sdp_open
+function should point to a non
+.Dv NULL
+remote BD_ADDR.
+Remote BD_ADDR can not be
+.Dv NG_HCI_BDADDR_ANY .
+The
+.Fn sdp_open_local
+function takes no arguments and opens a connection to a local SDP server.
+.Pp
+The
+.Fn sdp_close
+function terminates active SDP session and deletes SDP session object.
+The
+.Vt xs
+parameter should point to a valid SDP session object created with
+.Fn sdp_open
+or
+.Fn sdp_open_local .
+.Pp
+The
+.Fn sdp_error
+function returns last error that is stored inside SDP session object.
+The
+.Vt xs
+parameter should point to a valid SDP session object created with
+.Fn sdp_open
+or
+.Fn sdp_open_local .
+The error value returned can be converted to a human readable message by
+calling
+.Xr strerror 3
+function.
+.Pp
+The
+.Fn sdp_search
+function is used to perform SDP Service Search Attribute Request.
+The
+.Vt xs
+parameter should point to a valid SDP session object created with
+.Fn sdp_open
+or
+.Fn sdp_open_local .
+The
+.Vt pp
+parameter is a Service Search Pattern - an array of one or more Service
+Class IDs.
+The maximum number of Service Class IDs in the array is 12.
+The
+.Vt plen
+parameter is the length of the Service Search pattern.
+The
+.Vt ap
+parameter is a Attribute ID Range List - an array of one or more SDP Attribute
+ID Range. Each attribute ID Range is encoded as a 32-bit unsigned integer data
+element, where the high order 16 bits are interpreted as the beginning
+attribute ID of the range and the low order 16 bits are interpreted as the
+ending attribute ID of the range.
+The attribute IDs contained in the Attribute ID Ranges List must be listed in
+ascending order without duplication of any attribute ID values.
+Note that all attributes may be requested by specifying a range of
+0x0000-0xFFFF.
+The
+.Vt alen
+parameter is the length of the Attribute ID Ranges List.
+The
+.Fn SDP_ATTR_RANGE "lo" "hi"
+macro can be used to prepare Attribute ID Range.
+The
+.Vt vp
+parameter should be an array of
+.Vt sdp_attr_t
+structures.
+Each
+.Vt sdp_attr_t
+structure describes single SDP attribute and defined as follows:
+.Bd -literal -offset indent
+struct sdp_attr {
+ u_int16_t flags;
+#define SDP_ATTR_OK (0 << 0)
+#define SDP_ATTR_INVALID (1 << 0)
+#define SDP_ATTR_TRUNCATED (1 << 1)
+ u_int16_t attr; /* SDP_ATTR_xxx */
+ u_int32_t vlen; /* length of the value[] in bytes */
+ u_int8_t *value; /* base pointer */
+};
+typedef struct sdp_attr sdp_attr_t;
+typedef struct sdp_attr * sdp_attr_p;
+.Ed
+.Pp
+The caller of the
+.Fn sdp_search
+function is expected to prepare the array of
+.Vt sdp_attr
+structures and for each element of the array both
+.Vt vlen
+and
+.Vt value
+must be set.
+The
+.Fn sdp_search
+function will fill each
+.Vt sdp_attr_t
+structure with attribute and value, i.e. it will set
+.Vt flags ,
+.Vt attr
+and
+.Vt vlen
+fields.
+The actual value of the attribute will be copied into
+.Vt value
+buffer.
+Note: attributes are returned in the order they appear in the Service Search
+Attribute Response.
+SDP server could return several attributes for the same record.
+In this case the order of the attributes will be: all attributes for the first
+records, then all attributes for the secord record etc.
+.Pp
+The
+.Fn sdp_attr2desc
+and
+.Fn sdp_uuid2desc
+functions each take a numeric attribute ID/UUID value and convert it to a
+human readable description.
+.Sh EXAMPLES
+The following example shows how to get
+.Dv SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
+attribute for the
+.Dv SDP_SERVICE_CLASS_SERIAL_PORT
+service from the remote device.
+.Bd -literal -offset indent
+bdaddr_t remote;
+u_int8_t buffer[1024];
+void *ss = NULL;
+u_int16_t serv = SDP_SERVICE_CLASS_SERIAL_PORT;
+u_int32_t attr = SDP_ATTR_RANGE(
+ SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
+ SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
+sdp_attr_t proto = { SDP_ATTR_INVALID,0,sizeof(buffer),buffer };
+
+/* Obtain/set remote BDADDR here */
+
+if ((ss = sdp_open(NG_HCI_BDADDR_ANY, remote)) == NULL)
+ /* exit ENOMEM */
+if (sdp_error(ss) != 0)
+ /* exit spd_error(ss) */
+
+if (sdp_search(ss, 1, &serv, 1, &attr, 1, &proto) != 0)
+ /* exit sdp_error(ss) */
+
+if (proto.flags != SDP_ATTR_OK)
+ /* exit see proto.flags for details */
+
+/* If we got here then we have attribute value in proto.value */
+.Ed
+.Sh DIAGNOSTICS
+Both
+.Fn sdp_open
+and
+.Fn sdp_open_local
+will return
+.Dv NULL
+if memory allocation for the new SDP session object fails.
+If the new SDP object was created then caller is still expected to call
+.Fn sdp_error
+to check if there was connection error.
+.Pp
+The
+.Fn sdp_search
+function returns non-zero value on error.
+The caller is expected to call
+.Fn sdp_error
+to find out more about error.
+.Sh SEE ALSO
+.Xr bluetooth 3 ,
+.Xr strerror 3
+.Sh BUGS
+This is client only library for now.
+Please report bugs if found.
+.Sh AUTHORS
+.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com
diff --git a/lib/libsdp/sdp.h b/lib/libsdp/sdp.h
new file mode 100644
index 000000000000..83f5977830ca
--- /dev/null
+++ b/lib/libsdp/sdp.h
@@ -0,0 +1,477 @@
+/*
+ * sdp.h
+ *
+ * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: sdp.h,v 1.3 2003/09/05 00:33:59 max Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _SDP_H_
+#define _SDP_H_
+
+__BEGIN_DECLS
+
+/*
+ * Data representation (page 349)
+ */
+
+/* Nil, the null type */
+#define SDP_DATA_NIL 0x00
+
+/* Unsigned integer */
+#define SDP_DATA_UINT8 0x08
+#define SDP_DATA_UINT16 0x09
+#define SDP_DATA_UINT32 0x0A
+#define SDP_DATA_UINT64 0x0B
+#define SDP_DATA_UINT128 0x0C
+
+/* Signed two's-complement integer */
+#define SDP_DATA_INT8 0x10
+#define SDP_DATA_INT16 0x11
+#define SDP_DATA_INT32 0x12
+#define SDP_DATA_INT64 0x13
+#define SDP_DATA_INT128 0x14
+
+/* UUID, a universally unique identifier */
+#define SDP_DATA_UUID16 0x19
+#define SDP_DATA_UUID32 0x1A
+#define SDP_DATA_UUID128 0x1C
+
+/* Text string */
+#define SDP_DATA_STR8 0x25
+#define SDP_DATA_STR16 0x26
+#define SDP_DATA_STR32 0x27
+
+/* Boolean */
+#define SDP_DATA_BOOL 0x28
+
+/*
+ * Data element sequence.
+ * A data element whose data field is a sequence of data elements
+ */
+#define SDP_DATA_SEQ8 0x35
+#define SDP_DATA_SEQ16 0x36
+#define SDP_DATA_SEQ32 0x37
+
+/*
+ * Data element alternative.
+ * A data element whose data field is a sequence of data elements from
+ * which one data element is to be selected.
+ */
+#define SDP_DATA_ALT8 0x3D
+#define SDP_DATA_ALT16 0x3E
+#define SDP_DATA_ALT32 0x3F
+
+/* URL, a uniform resource locator */
+#define SDP_DATA_URL8 0x45
+#define SDP_DATA_URL16 0x46
+#define SDP_DATA_URL32 0x47
+
+/*
+ * Protocols UUID (short) http://www.bluetoothsig.org/assigned-numbers/sdp.htm
+ * BASE UUID 00000000-0000-1000-8000-00805F9B34FB
+ */
+
+#define SDP_UUID_PROTOCOL_SDP 0x0001
+#define SDP_UUID_PROTOCOL_UDP 0x0002
+#define SDP_UUID_PROTOCOL_RFCOMM 0x0003
+#define SDP_UUID_PROTOCOL_TCP 0x0004
+#define SDP_UUID_PROTOCOL_TCS_BIN 0x0005
+#define SDP_UUID_PROTOCOL_TCS_AT 0x0006
+#define SDP_UUID_PROTOCOL_OBEX 0x0008
+#define SDP_UUID_PROTOCOL_IP 0x0009
+#define SDP_UUID_PROTOCOL_FTP 0x000A
+#define SDP_UUID_PROTOCOL_HTTP 0x000C
+#define SDP_UUID_PROTOCOL_WSP 0x000E
+#define SDP_UUID_PROTOCOL_BNEP 0x000F
+#define SDP_UUID_PROTOCOL_UPNP 0x0010
+#define SDP_UUID_PROTOCOL_HIDP 0x0011
+#define SDP_UUID_PROTOCOL_HARDCOPY_CONTROL_CHANNEL 0x0012
+#define SDP_UUID_PROTOCOL_HARDCOPY_DATA_CHANNEL 0x0014
+#define SDP_UUID_PROTOCOL_HARDCOPY_NOTIFICATION 0x0016
+#define SDP_UUID_PROTOCOL_AVCTP 0x0017
+#define SDP_UUID_PROTOCOL_AVDTP 0x0019
+#define SDP_UUID_PROTOCOL_CMPT 0x001B
+#define SDP_UUID_PROTOCOL_UDI_C_PLANE 0x001D
+#define SDP_UUID_PROTOCOL_L2CAP 0x0100
+
+/*
+ * Service class IDs http://www.bluetoothsig.org/assigned-numbers/sdp.htm
+ */
+
+#define SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER 0x1000
+#define SDP_SERVICE_CLASS_BROWSE_GROUP_DESCRIPTOR 0x1001
+#define SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP 0x1002
+#define SDP_SERVICE_CLASS_SERIAL_PORT 0x1101
+#define SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP 0x1102
+#define SDP_SERVICE_CLASS_DIALUP_NETWORKING 0x1103
+#define SDP_SERVICE_CLASS_IR_MC_SYNC 0x1104
+#define SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH 0x1105
+#define SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER 0x1106
+#define SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND 0x1107
+#define SDP_SERVICE_CLASS_HEADSET 0x1108
+#define SDP_SERVICE_CLASS_CORDLESS_TELEPHONY 0x1109
+#define SDP_SERVICE_CLASS_AUDIO_SOURCE 0x110A
+#define SDP_SERVICE_CLASS_AUDIO_SINK 0x110B
+#define SDP_SERVICE_CLASS_AV_REMOTE_CONTROL_TARGET 0x110C
+#define SDP_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION 0x110D
+#define SDP_SERVICE_CLASS_AV_REMOTE_CONTROL 0x110E
+#define SDP_SERVICE_CLASS_VIDEO_CONFERENCING 0x110F
+#define SDP_SERVICE_CLASS_INTERCOM 0x1110
+#define SDP_SERVICE_CLASS_FAX 0x1111
+#define SDP_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY 0x1112
+#define SDP_SERVICE_CLASS_WAP 0x1113
+#define SDP_SERVICE_CLASS_WAP_CLIENT 0x1114
+#define SDP_SERVICE_CLASS_PANU 0x1115
+#define SDP_SERVICE_CLASS_NAP 0x1116
+#define SDP_SERVICE_CLASS_GN 0x1117
+#define SDP_SERVICE_CLASS_DIRECT_PRINTING 0x1118
+#define SDP_SERVICE_CLASS_REFERENCE_PRINTING 0x1119
+#define SDP_SERVICE_CLASS_IMAGING 0x111A
+#define SDP_SERVICE_CLASS_IMAGING_RESPONDER 0x111B
+#define SDP_SERVICE_CLASS_IMAGING_AUTOMATIC_ARCHIVE 0x111C
+#define SDP_SERVICE_CLASS_IMAGING_REFERENCED_OBJECTS 0x111D
+#define SDP_SERVICE_CLASS_HANDSFREE 0x111E
+#define SDP_SERVICE_CLASS_HANDSFREE_AUDIO_GATEWAY 0x111F
+#define SDP_SERVICE_CLASS_DIRECT_PRINTING_REFERENCE_OBJECTS 0x1120
+#define SDP_SERVICE_CLASS_REFLECTED_UI 0x1121
+#define SDP_SERVICE_CLASS_BASIC_PRINTING 0x1122
+#define SDP_SERVICE_CLASS_PRINTING_STATUS 0x1123
+#define SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE 0x1124
+#define SDP_SERVICE_CLASS_HARDCOPY_CABLE_REPLACEMENT 0x1125
+#define SDP_SERVICE_CLASS_HCR_PRINT 0x1126
+#define SDP_SERVICE_CLASS_HCR_SCAN 0x1127
+#define SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS 0x1128
+#define SDP_SERVICE_CLASS_VIDEO_CONFERENCING_GW 0x1129
+#define SDP_SERVICE_CLASS_UDI_MT 0x112A
+#define SDP_SERVICE_CLASS_UDI_TA 0x112B
+#define SDP_SERVICE_CLASS_AUDIO_VIDEO 0x112C
+#define SDP_SERVICE_CLASS_SIM_ACCESS 0x112D
+#define SDP_SERVICE_CLASS_PNP_INFORMATION 0x1200
+#define SDP_SERVICE_CLASS_GENERIC_NETWORKING 0x1201
+#define SDP_SERVICE_CLASS_GENERIC_FILE_TRANSFER 0x1202
+#define SDP_SERVICE_CLASS_GENERIC_AUDIO 0x1203
+#define SDP_SERVICE_CLASS_GENERIC_TELEPHONY 0x1204
+#define SDP_SERVICE_CLASS_UPNP 0x1205
+#define SDP_SERVICE_CLASS_UPNP_IP 0x1206
+#define SDP_SERVICE_CLASS_ESDP_UPNP_IP_PAN 0x1300
+#define SDP_SERVICE_CLASS_ESDP_UPNP_IP_LAP 0x1301
+#define SDP_SERVICE_CLASS_ESDP_UPNP_L2CAP 0x1302
+
+/*
+ * Universal attribute definitions (page 366) and
+ * http://www.bluetoothsig.org/assigned-numbers/sdp.htm
+ */
+
+#define SDP_ATTR_RANGE(lo, hi) \
+ (u_int32_t)(((u_int16_t)(lo) << 16) | ((u_int16_t)(hi)))
+
+#define SDP_ATTR_SERVICE_RECORD_HANDLE 0x0000
+#define SDP_ATTR_SERVICE_CLASS_ID_LIST 0x0001
+#define SDP_ATTR_SERVICE_RECORD_STATE 0x0002
+#define SDP_ATTR_SERVICE_ID 0x0003
+#define SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST 0x0004
+#define SDP_ATTR_BROWSE_GROUP_LIST 0x0005
+#define SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST 0x0006
+#define SDP_ATTR_SERVICE_INFO_TIME_TO_LIVE 0x0007
+#define SDP_ATTR_SERVICE_AVAILABILITY 0x0008
+#define SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST 0x0009
+#define SDP_ATTR_DOCUMENTATION_URL 0x000A
+#define SDP_ATTR_CLIENT_EXECUTABLE_URL 0x000B
+#define SDP_ATTR_ICON_URL 0x000C
+#define SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS 0x000D
+#define SDP_ATTR_GROUP_ID 0x0200
+#define SDP_ATTR_IP_SUBNET 0x0200
+#define SDP_ATTR_VERSION_NUMBER_LIST 0x0200
+#define SDP_ATTR_SERVICE_DATABASE_STATE 0x0201
+#define SDP_ATTR_SERVICE_VERSION 0x0300
+#define SDP_ATTR_EXTERNAL_NETWORK 0x0301
+#define SDP_ATTR_NETWORK 0x0301
+#define SDP_ATTR_SUPPORTED_DATA_STORES_LIST 0x0301
+#define SDP_ATTR_FAX_CLASS1_SUPPORT 0x0302
+#define SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL 0x0302
+#define SDP_ATTR_FAX_CLASS20_SUPPORT 0x0303
+#define SDP_ATTR_SUPPORTED_FORMATS_LIST 0x0303
+#define SDP_ATTR_FAX_CLASS2_SUPPORT 0x0304
+#define SDP_ATTR_AUDIO_FEEDBACK_SUPPORT 0x0305
+#define SDP_ATTR_NETWORK_ADDRESS 0x0306
+#define SDP_ATTR_WAP_GATEWAY 0x0307
+#define SDP_ATTR_HOME_PAGE_URL 0x0308
+#define SDP_ATTR_WAP_STACK_TYPE 0x0309
+#define SDP_ATTR_SECURITY_DESCRIPTION 0x030A
+#define SDP_ATTR_NET_ACCESS_TYPE 0x030B
+#define SDP_ATTR_MAX_NET_ACCESS_RATE 0x030C
+#define SDP_ATTR_IPV4_SUBNET 0x030D
+#define SDP_ATTR_IPV6_SUBNET 0x030E
+#define SDP_ATTR_SUPPORTED_CAPABALITIES 0x0310
+#define SDP_ATTR_SUPPORTED_FEATURES 0x0311
+#define SDP_ATTR_SUPPORTED_FUNCTIONS 0x0312
+#define SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY 0x0313
+
+/*
+ * The offset must be added to the attribute ID base (contained in the
+ * LANGUAGE_BASE_ATTRIBUTE_ID_LIST attribute) in order to compute the
+ * attribute ID for these attributes.
+ */
+
+#define SDP_ATTR_SERVICE_NAME_OFFSET 0x0000
+#define SDP_ATTR_SERVICE_DESCRIPTION_OFFSET 0x0001
+#define SDP_ATTR_PROVIDER_NAME_OFFSET 0x0002
+
+/*
+ * Protocol data unit (PDU) format (page 352)
+ */
+
+#define SDP_PDU_ERROR_RESPONSE 0x01
+#define SDP_PDU_SERVICE_SEARCH_REQUEST 0x02
+#define SDP_PDU_SERVICE_SEARCH_RESPONSE 0x03
+#define SDP_PDU_SERVICE_ATTRIBUTE_REQUEST 0x04
+#define SDP_PDU_SERVICE_ATTRIBUTE_RESPONSE 0x05
+#define SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_REQUEST 0x06
+#define SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_RESPONSE 0x07
+
+struct sdp_pdu {
+ u_int8_t pid; /* PDU ID - SDP_PDU_xxx */
+ u_int16_t tid; /* transaction ID */
+ u_int16_t len; /* parameters length (in bytes) */
+} __attribute__ ((packed));
+typedef struct sdp_pdu sdp_pdu_t;
+typedef struct sdp_pdu * sdp_pdu_p;
+
+/*
+ * SDP int128/uint128 parameter
+ */
+
+struct int128 {
+ int8_t b[16];
+};
+typedef struct int128 int128_t;
+typedef struct int128 u_int128_t;
+
+/*
+ * SDP attribute
+ */
+
+struct sdp_attr {
+ u_int16_t flags;
+#define SDP_ATTR_OK (0 << 0)
+#define SDP_ATTR_INVALID (1 << 0)
+#define SDP_ATTR_TRUNCATED (1 << 1)
+ u_int16_t attr; /* SDP_ATTR_xxx */
+ u_int32_t vlen; /* length of the value[] in bytes */
+ u_int8_t *value; /* base pointer */
+};
+typedef struct sdp_attr sdp_attr_t;
+typedef struct sdp_attr * sdp_attr_p;
+
+/******************************************************************************
+ * User interface
+ *****************************************************************************/
+
+/* Inline versions of get/put byte/short/long. Pointer is advanced */
+#define SDP_GET8(b, cp) { \
+ register u_int8_t *t_cp = (u_int8_t *)(cp); \
+ (b) = *t_cp; \
+ (cp) ++; \
+}
+
+#define SDP_GET16(s, cp) { \
+ register u_int8_t *t_cp = (u_int8_t *)(cp); \
+ (s) = ((u_int16_t)t_cp[0] << 8) \
+ | ((u_int16_t)t_cp[1]) \
+ ; \
+ (cp) += 2; \
+}
+
+#define SDP_GET32(l, cp) { \
+ register u_int8_t *t_cp = (u_int8_t *)(cp); \
+ (l) = ((u_int32_t)t_cp[0] << 24) \
+ | ((u_int32_t)t_cp[1] << 16) \
+ | ((u_int32_t)t_cp[2] << 8) \
+ | ((u_int32_t)t_cp[3]) \
+ ; \
+ (cp) += 4; \
+}
+
+#define SDP_GET64(l, cp) { \
+ register u_int8_t *t_cp = (u_int8_t *)(cp); \
+ (l) = ((u_int64_t)t_cp[0] << 56) \
+ | ((u_int64_t)t_cp[1] << 48) \
+ | ((u_int64_t)t_cp[2] << 40) \
+ | ((u_int64_t)t_cp[3] << 32) \
+ | ((u_int64_t)t_cp[4] << 24) \
+ | ((u_int64_t)t_cp[5] << 16) \
+ | ((u_int64_t)t_cp[6] << 8) \
+ | ((u_int64_t)t_cp[7]) \
+ ; \
+ (cp) += 8; \
+}
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define SDP_GET128(l, cp) { \
+ register u_int8_t *t_cp = (u_int8_t *)(cp); \
+ (l)->b[15] = *t_cp++; \
+ (l)->b[14] = *t_cp++; \
+ (l)->b[13] = *t_cp++; \
+ (l)->b[12] = *t_cp++; \
+ (l)->b[11] = *t_cp++; \
+ (l)->b[10] = *t_cp++; \
+ (l)->b[9] = *t_cp++; \
+ (l)->b[8] = *t_cp++; \
+ (l)->b[7] = *t_cp++; \
+ (l)->b[6] = *t_cp++; \
+ (l)->b[5] = *t_cp++; \
+ (l)->b[4] = *t_cp++; \
+ (l)->b[3] = *t_cp++; \
+ (l)->b[2] = *t_cp++; \
+ (l)->b[1] = *t_cp++; \
+ (cp) += 16; \
+}
+#else /* BYTE_ORDER != LITTLE_ENDIAN */
+#define SDP_GET128(l, cp) { \
+ register u_int8_t *t_cp = (u_int8_t *)(cp); \
+ (l)->b[0] = *t_cp++; \
+ (l)->b[1] = *t_cp++; \
+ (l)->b[2] = *t_cp++; \
+ (l)->b[3] = *t_cp++; \
+ (l)->b[4] = *t_cp++; \
+ (l)->b[5] = *t_cp++; \
+ (l)->b[6] = *t_cp++; \
+ (l)->b[7] = *t_cp++; \
+ (l)->b[8] = *t_cp++; \
+ (l)->b[9] = *t_cp++; \
+ (l)->b[10] = *t_cp++; \
+ (l)->b[11] = *t_cp++; \
+ (l)->b[12] = *t_cp++; \
+ (l)->b[13] = *t_cp++; \
+ (l)->b[14] = *t_cp++; \
+ (l)->b[15] = *t_cp++; \
+ (cp) += 16; \
+}
+#endif /* BYTE_ORDER */
+
+#define SDP_PUT8(b, cp) { \
+ register u_int8_t t_b = (u_int8_t)(b); \
+ register u_int8_t *t_cp = (u_int8_t *)(cp); \
+ *t_cp = t_b; \
+ (cp) ++; \
+}
+
+#define SDP_PUT16(s, cp) { \
+ register u_int16_t t_s = (u_int16_t)(s); \
+ register u_int8_t *t_cp = (u_int8_t *)(cp); \
+ *t_cp++ = t_s >> 8; \
+ *t_cp = t_s; \
+ (cp) += 2; \
+}
+
+#define SDP_PUT32(l, cp) { \
+ register u_int32_t t_l = (u_int32_t)(l); \
+ register u_int8_t *t_cp = (u_int8_t *)(cp); \
+ *t_cp++ = t_l >> 24; \
+ *t_cp++ = t_l >> 16; \
+ *t_cp++ = t_l >> 8; \
+ *t_cp = t_l; \
+ (cp) += 4; \
+}
+
+#define SDP_PUT64(l, cp) { \
+ register u_int64_t t_l = (u_int64_t)(l); \
+ register u_int8_t *t_cp = (u_int8_t *)(cp); \
+ *t_cp++ = t_l >> 56; \
+ *t_cp++ = t_l >> 48; \
+ *t_cp++ = t_l >> 40; \
+ *t_cp++ = t_l >> 32; \
+ *t_cp++ = t_l >> 24; \
+ *t_cp++ = t_l >> 16; \
+ *t_cp++ = t_l >> 8; \
+ *t_cp = t_l; \
+ (cp) += 8; \
+}
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define SDP_PUT128(l, cp) { \
+ register u_int8_t *t_cp = (u_int8_t *)(cp); \
+ *t_cp++ = (l)->b[15]; \
+ *t_cp++ = (l)->b[14]; \
+ *t_cp++ = (l)->b[13]; \
+ *t_cp++ = (l)->b[12]; \
+ *t_cp++ = (l)->b[11]; \
+ *t_cp++ = (l)->b[10]; \
+ *t_cp++ = (l)->b[9]; \
+ *t_cp++ = (l)->b[8]; \
+ *t_cp++ = (l)->b[7]; \
+ *t_cp++ = (l)->b[6]; \
+ *t_cp++ = (l)->b[5]; \
+ *t_cp++ = (l)->b[4]; \
+ *t_cp++ = (l)->b[3]; \
+ *t_cp++ = (l)->b[2]; \
+ *t_cp++ = (l)->b[1]; \
+ *t_cp = (l)->b[0]; \
+ (cp) += 16; \
+}
+#else /* BYTE_ORDER != LITTLE_ENDIAN */
+#define SDP_PUT128(l, cp) { \
+ register u_int8_t *t_cp = (u_int8_t *)(cp); \
+ *t_cp++ = (l)->b[0]; \
+ *t_cp++ = (l)->b[1]; \
+ *t_cp++ = (l)->b[2]; \
+ *t_cp++ = (l)->b[3]; \
+ *t_cp++ = (l)->b[4]; \
+ *t_cp++ = (l)->b[5]; \
+ *t_cp++ = (l)->b[6]; \
+ *t_cp++ = (l)->b[7]; \
+ *t_cp++ = (l)->b[8]; \
+ *t_cp++ = (l)->b[9]; \
+ *t_cp++ = (l)->b[10]; \
+ *t_cp++ = (l)->b[11]; \
+ *t_cp++ = (l)->b[12]; \
+ *t_cp++ = (l)->b[13]; \
+ *t_cp++ = (l)->b[14]; \
+ *t_cp = (l)->b[15]; \
+ (cp) += 16; \
+}
+#endif /* BYTE_ORDER */
+
+void * sdp_open (bdaddr_t const *l, bdaddr_t const *r);
+void * sdp_open_local (void);
+int32_t sdp_close (void *xs);
+int32_t sdp_error (void *xs);
+
+int32_t sdp_search (void *xs,
+ u_int32_t plen, u_int16_t const *pp,
+ u_int32_t alen, u_int32_t const *ap,
+ u_int32_t vlen, sdp_attr_t *vp);
+
+char const * const sdp_attr2desc (u_int16_t attr);
+char const * const sdp_uuid2desc (u_int16_t uuid);
+void sdp_print (u_int32_t level, u_int8_t const *start,
+ u_int8_t const *end);
+
+__END_DECLS
+
+#endif /* ndef _SDP_H_ */
+
diff --git a/lib/libsdp/search.c b/lib/libsdp/search.c
new file mode 100644
index 000000000000..ab495e32115f
--- /dev/null
+++ b/lib/libsdp/search.c
@@ -0,0 +1,383 @@
+/*
+ * search.c
+ *
+ * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: search.c,v 1.2 2003/09/04 22:12:13 max Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <bluetooth.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sdp-int.h>
+#include <sdp.h>
+
+int32_t
+sdp_search(void *xss,
+ u_int32_t plen, u_int16_t const *pp,
+ u_int32_t alen, u_int32_t const *ap,
+ u_int32_t vlen, sdp_attr_t *vp)
+{
+ struct sdp_xpdu {
+ sdp_pdu_t pdu;
+ u_int16_t len;
+ } __attribute__ ((packed)) xpdu;
+
+ sdp_session_p ss = (sdp_session_p) xss;
+ u_int8_t *req = NULL, *rsp = NULL, *rsp_tmp = NULL;
+ int32_t type, len;
+
+ if (ss == NULL)
+ return (-1);
+
+ if (ss->req == NULL || ss->rsp == NULL ||
+ plen == 0 || pp == NULL || alen == 0 || ap == NULL) {
+ ss->error = EINVAL;
+ return (-1);
+ }
+
+ /* Calculate length of the request */
+ req = ss->req;
+ plen = plen * (sizeof(pp[0]) + 1);
+ alen = alen * (sizeof(ap[0]) + 1);
+
+ len = plen + sizeof(u_int8_t) + sizeof(u_int16_t) +
+ /* ServiceSearchPattern */
+ sizeof(u_int16_t) +
+ /* MaximumAttributeByteCount */
+ alen + sizeof(u_int8_t) + sizeof(u_int16_t);
+ /* AttributeIDList */
+
+ if (ss->req_e - req < len) {
+ ss->error = ENOBUFS;
+ return (-1);
+ }
+
+ /* Put ServiceSearchPattern */
+ SDP_PUT8(SDP_DATA_SEQ16, req);
+ SDP_PUT16(plen, req);
+ for (; plen > 0; pp ++, plen -= (sizeof(pp[0]) + 1)) {
+ SDP_PUT8(SDP_DATA_UUID16, req);
+ SDP_PUT16(*pp, req);
+ }
+
+ /* Put MaximumAttributeByteCount */
+ SDP_PUT16(0xffff, req);
+
+ /* Put AttributeIDList */
+ SDP_PUT8(SDP_DATA_SEQ16, req);
+ SDP_PUT16(alen, req);
+ for (; alen > 0; ap ++, alen -= (sizeof(ap[0]) + 1)) {
+ SDP_PUT8(SDP_DATA_UINT32, req);
+ SDP_PUT32(*ap, req);
+ }
+
+ /* Submit ServiceSearchAttributeRequest and wait for response */
+ ss->cslen = 0;
+ rsp = ss->rsp;
+
+ do {
+ struct iovec iov[2];
+ u_int8_t *req_cs = req;
+
+ /* Add continuation state (if any) */
+ if (ss->req_e - req_cs < ss->cslen + 1) {
+ ss->error = ENOBUFS;
+ return (-1);
+ }
+
+ SDP_PUT8(ss->cslen, req_cs);
+ if (ss->cslen > 0) {
+ memcpy(req_cs, ss->cs, ss->cslen);
+ req_cs += ss->cslen;
+ }
+
+ /* Prepare SDP PDU header */
+ xpdu.pdu.pid = SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_REQUEST;
+ xpdu.pdu.tid = htons(ss->tid);
+ xpdu.pdu.len = htons(req_cs - ss->req);
+
+ /* Submit request */
+ iov[0].iov_base = (void *) &xpdu;
+ iov[0].iov_len = sizeof(xpdu.pdu);
+ iov[1].iov_base = (void *) ss->req;
+ iov[1].iov_len = req_cs - ss->req;
+
+ len = writev(ss->s, iov, sizeof(iov)/sizeof(iov[0]));
+ if (len < 0) {
+ ss->error = errno;
+ return (-1);
+ }
+
+ /* Read response */
+ iov[0].iov_base = (void *) &xpdu;
+ iov[0].iov_len = sizeof(xpdu);
+ iov[1].iov_base = (void *) rsp;
+ iov[1].iov_len = ss->imtu;
+
+ len = readv(ss->s, iov, sizeof(iov)/sizeof(iov[0]));
+ if (len < 0) {
+ ss->error = errno;
+ return (-1);
+ }
+ if (len < sizeof(xpdu)) {
+ ss->error = ENOMSG;
+ return (-1);
+ }
+
+ xpdu.pdu.tid = ntohs(xpdu.pdu.tid);
+ xpdu.pdu.len = ntohs(xpdu.pdu.len);
+ xpdu.len = ntohs(xpdu.len);
+
+ if (xpdu.pdu.pid == SDP_PDU_ERROR_RESPONSE ||
+ xpdu.pdu.tid != ss->tid ||
+ xpdu.len > xpdu.pdu.len) {
+ ss->error = EIO;
+ return (-1);
+ }
+
+ /* Save continuation state (if any) */
+ ss->cslen = rsp[xpdu.len];
+ if (ss->cslen > 0) {
+ if (ss->cslen > sizeof(ss->cs)) {
+ ss->error = ENOBUFS;
+ return (-1);
+ }
+
+ memcpy(ss->cs, rsp + xpdu.len + 1, ss->cslen);
+
+ /*
+ * Ensure that we always have ss->imtu bytes
+ * available in the ss->rsp buffer
+ */
+
+ if (ss->rsp_e - rsp <= ss->imtu) {
+ u_int32_t size, offset;
+
+ size = ss->rsp_e - ss->rsp + ss->imtu;
+ offset = rsp - ss->rsp;
+
+ rsp_tmp = realloc(ss->rsp, size);
+ if (rsp_tmp == NULL) {
+ ss->error = ENOMEM;
+ return (-1);
+ }
+
+ ss->rsp = rsp_tmp;
+ ss->rsp_e = ss->rsp + size;
+ rsp = ss->rsp + offset;
+ }
+ }
+
+ rsp += xpdu.len;
+ ss->tid ++;
+ } while (ss->cslen > 0);
+
+ /*
+ * If we got here then we have completed SDP transaction and now
+ * we must populate attribute values into vp array. At this point
+ * ss->rsp points to the beginning of the response and rsp points
+ * to the end of the response.
+ *
+ * From Bluetooth v1.1 spec page 364
+ *
+ * The AttributeLists is a data element sequence where each element
+ * in turn is a data element sequence representing an attribute list.
+ * Each attribute list contains attribute IDs and attribute values
+ * from one service record. The first element in each attribute list
+ * contains the attribute ID of the first attribute to be returned for
+ * that service record. The second element in each attribute list
+ * contains the corresponding attribute value. Successive pairs of
+ * elements in each attribute list contain additional attribute ID
+ * and value pairs. Only attributes that have non-null values within
+ * the service record and whose attribute IDs were specified in the
+ * SDP_ServiceSearchAttributeRequest are contained in the AttributeLists
+ * Neither an attribute ID nor attribute value is placed in
+ * AttributeLists for attributes in the service record that have no
+ * value. Within each attribute list, the attributes are listed in
+ * ascending order of attribute ID value.
+ */
+
+ if (vp == NULL)
+ goto done;
+
+ rsp_tmp = ss->rsp;
+
+ /* Skip the first SEQ */
+ SDP_GET8(type, rsp_tmp);
+ switch (type) {
+ case SDP_DATA_SEQ8:
+ SDP_GET8(len, rsp_tmp);
+ break;
+
+ case SDP_DATA_SEQ16:
+ SDP_GET16(len, rsp_tmp);
+ break;
+
+ case SDP_DATA_SEQ32:
+ SDP_GET32(len, rsp_tmp);
+ break;
+
+ default:
+ ss->error = ENOATTR;
+ return (-1);
+ /* NOT REACHED */
+ }
+
+ for (; rsp_tmp < rsp && vlen > 0; ) {
+ /* Get set of attributes for the next record */
+ SDP_GET8(type, rsp_tmp);
+ switch (type) {
+ case SDP_DATA_SEQ8:
+ SDP_GET8(len, rsp_tmp);
+ break;
+
+ case SDP_DATA_SEQ16:
+ SDP_GET16(len, rsp_tmp);
+ break;
+
+ case SDP_DATA_SEQ32:
+ SDP_GET32(len, rsp_tmp);
+ break;
+
+ default:
+ ss->error = ENOATTR;
+ return (-1);
+ /* NOT REACHED */
+ }
+
+ /* Now rsp_tmp points to list of (attr,value) pairs */
+ for (; len > 0 && vlen > 0; vp ++, vlen --) {
+ /* Attribute */
+ SDP_GET8(type, rsp_tmp);
+ if (type != SDP_DATA_UINT16) {
+ ss->error = ENOATTR;
+ return (-1);
+ }
+ SDP_GET16(vp->attr, rsp_tmp);
+
+ /* Attribute value */
+ switch (rsp_tmp[0]) {
+ case SDP_DATA_NIL:
+ alen = 0;
+ break;
+
+ case SDP_DATA_UINT8:
+ case SDP_DATA_INT8:
+ case SDP_DATA_BOOL:
+ alen = sizeof(u_int8_t);
+ break;
+
+ case SDP_DATA_UINT16:
+ case SDP_DATA_INT16:
+ case SDP_DATA_UUID16:
+ alen = sizeof(u_int16_t);
+ break;
+
+ case SDP_DATA_UINT32:
+ case SDP_DATA_INT32:
+ case SDP_DATA_UUID32:
+ alen = sizeof(u_int32_t);
+ break;
+
+ case SDP_DATA_UINT64:
+ case SDP_DATA_INT64:
+ alen = sizeof(u_int64_t);
+ break;
+
+ case SDP_DATA_UINT128:
+ case SDP_DATA_INT128:
+ case SDP_DATA_UUID128:
+ alen = sizeof(u_int128_t);
+ break;
+
+ case SDP_DATA_STR8:
+ case SDP_DATA_URL8:
+ case SDP_DATA_SEQ8:
+ case SDP_DATA_ALT8:
+ alen = rsp_tmp[1] + sizeof(u_int8_t);
+ break;
+
+ case SDP_DATA_STR16:
+ case SDP_DATA_URL16:
+ case SDP_DATA_SEQ16:
+ case SDP_DATA_ALT16:
+ alen = ((u_int16_t)rsp_tmp[1] << 8)
+ | ((u_int16_t)rsp_tmp[2]);
+ alen += sizeof(u_int16_t);
+ break;
+
+ case SDP_DATA_STR32:
+ case SDP_DATA_URL32:
+ case SDP_DATA_SEQ32:
+ case SDP_DATA_ALT32:
+ alen = ((u_int32_t)rsp_tmp[1] << 24)
+ | ((u_int32_t)rsp_tmp[2] << 16)
+ | ((u_int32_t)rsp_tmp[3] << 8)
+ | ((u_int32_t)rsp_tmp[4]);
+ alen += sizeof(u_int32_t);
+ break;
+
+ default:
+ ss->error = ENOATTR;
+ return (-1);
+ /* NOT REACHED */
+ }
+
+ alen += sizeof(u_int8_t);
+
+ if (vp->value != NULL) {
+ if (alen <= vp->vlen) {
+ vp->flags = SDP_ATTR_OK;
+ vp->vlen = alen;
+ } else
+ vp->flags = SDP_ATTR_TRUNCATED;
+
+ memcpy(vp->value, rsp_tmp, vp->vlen);
+ } else
+ vp->flags = SDP_ATTR_INVALID;
+
+ len -= (
+ sizeof(u_int8_t) + sizeof(u_int16_t) +
+ alen
+ );
+
+ rsp_tmp += alen;
+ }
+ }
+done:
+ ss->error = 0;
+
+ return (0);
+}
+
diff --git a/lib/libsdp/session.c b/lib/libsdp/session.c
new file mode 100644
index 000000000000..199f8cd2c6e0
--- /dev/null
+++ b/lib/libsdp/session.c
@@ -0,0 +1,174 @@
+/*
+ * session.c
+ *
+ * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: session.c,v 1.2 2003/09/04 22:12:13 max Exp $
+ * $FreeBSD$
+ */
+
+#include <bluetooth.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sdp-int.h>
+#include <sdp.h>
+
+void *
+sdp_open(bdaddr_t const *l, bdaddr_t const *r)
+{
+ sdp_session_p ss = NULL;
+ struct sockaddr_l2cap sa;
+ socklen_t size;
+
+ if ((ss = calloc(1, sizeof(*ss))) == NULL)
+ goto fail;
+
+ if (l == NULL || r == NULL) {
+ ss->error = EINVAL;
+ goto fail;
+ }
+
+ ss->s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
+ if (ss->s < 0) {
+ ss->error = errno;
+ goto fail;
+ }
+
+ sa.l2cap_len = sizeof(sa);
+ sa.l2cap_family = AF_BLUETOOTH;
+ sa.l2cap_psm = 0;
+ memcpy(&sa.l2cap_bdaddr, l, sizeof(sa.l2cap_bdaddr));
+ if (bind(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
+ ss->error = errno;
+ goto fail;
+ }
+
+ sa.l2cap_psm = htole16(NG_L2CAP_PSM_SDP);
+ memcpy(&sa.l2cap_bdaddr, r, sizeof(sa.l2cap_bdaddr));
+ if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
+ ss->error = errno;
+ goto fail;
+ }
+
+ size = sizeof(ss->omtu);
+ if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_OMTU, &ss->omtu, &size) < 0) {
+ ss->error = errno;
+ goto fail;
+ }
+ if ((ss->req = malloc(ss->omtu)) == NULL) {
+ ss->error = ENOMEM;
+ goto fail;
+ }
+ ss->req_e = ss->req + ss->omtu;
+
+ size = sizeof(ss->imtu);
+ if (getsockopt(ss->s, SOL_L2CAP, SO_L2CAP_IMTU, &ss->imtu, &size) < 0) {
+ ss->error = errno;
+ goto fail;
+ }
+ if ((ss->rsp = malloc(ss->imtu)) == NULL) {
+ ss->error = ENOMEM;
+ goto fail;
+ }
+ ss->rsp_e = ss->rsp + ss->imtu;
+ ss->error = 0;
+fail:
+ return ((void *) ss);
+}
+
+void *
+sdp_open_local(void)
+{
+ sdp_session_p ss = NULL;
+ struct sockaddr_un sa;
+
+ if ((ss = calloc(1, sizeof(*ss))) == NULL)
+ goto fail;
+
+ ss->s = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (ss->s < 0) {
+ ss->error = errno;
+ goto fail;
+ }
+
+ sa.sun_len = sizeof(sa);
+ sa.sun_family = AF_UNIX;
+ strlcpy(sa.sun_path, SDP_UNSOCK_PATH, sizeof(sa.sun_path));
+
+ if (connect(ss->s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
+ ss->error = errno;
+ goto fail;
+ }
+
+ ss->flags |= SDP_SESSION_LOCAL;
+ ss->imtu = ss->omtu = SDP_UNSOCK_MTU;
+
+ if ((ss->req = malloc(ss->omtu)) == NULL) {
+ ss->error = ENOMEM;
+ goto fail;
+ }
+ ss->req_e = ss->req + ss->omtu;
+
+ if ((ss->rsp = malloc(ss->imtu)) == NULL) {
+ ss->error = ENOMEM;
+ goto fail;
+ }
+ ss->rsp_e = ss->rsp + ss->imtu;
+ ss->error = 0;
+fail:
+ return ((void *) ss);
+}
+
+int32_t
+sdp_close(void *xss)
+{
+ sdp_session_p ss = (sdp_session_p) xss;
+
+ if (ss != NULL) {
+ if (ss->s >= 0)
+ close(ss->s);
+
+ if (ss->req != NULL)
+ free(ss->req);
+ if (ss->rsp != NULL)
+ free(ss->rsp);
+
+ memset(ss, 0, sizeof(*ss));
+ free(ss);
+ }
+
+ return (0);
+}
+
+int32_t
+sdp_error(void *xss)
+{
+ sdp_session_p ss = (sdp_session_p) xss;
+
+ return ((ss != NULL)? ss->error : EINVAL);
+}
diff --git a/lib/libsdp/util.c b/lib/libsdp/util.c
new file mode 100644
index 000000000000..923b3472047d
--- /dev/null
+++ b/lib/libsdp/util.c
@@ -0,0 +1,439 @@
+/*
+ * util.c
+ *
+ * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: util.c,v 1.5 2003/09/08 02:29:35 max Exp $
+ * $FreeBSD$
+ */
+
+#include <bluetooth.h>
+#include <stdio.h>
+#include <sdp.h>
+
+/*
+ * SDP attribute description
+ */
+
+struct sdp_attr_desc {
+ u_int32_t attr;
+ char const *desc;
+};
+typedef struct sdp_attr_desc sdp_attr_desc_t;
+typedef struct sdp_attr_desc * sdp_attr_desc_p;
+
+static sdp_attr_desc_t sdp_uuids_desc[] = {
+{ SDP_UUID_PROTOCOL_SDP, "SDP", },
+{ SDP_UUID_PROTOCOL_UDP, "UDP", },
+{ SDP_UUID_PROTOCOL_RFCOMM, "RFCOMM", },
+{ SDP_UUID_PROTOCOL_TCP, "TCP", },
+{ SDP_UUID_PROTOCOL_TCS_BIN, "TCS BIN", },
+{ SDP_UUID_PROTOCOL_TCS_AT, "TCS AT", },
+{ SDP_UUID_PROTOCOL_OBEX, "OBEX", },
+{ SDP_UUID_PROTOCOL_IP, "IP", },
+{ SDP_UUID_PROTOCOL_FTP, "FTP", },
+{ SDP_UUID_PROTOCOL_HTTP, "HTTP", },
+{ SDP_UUID_PROTOCOL_WSP, "WSP", },
+{ SDP_UUID_PROTOCOL_BNEP, "BNEP", },
+{ SDP_UUID_PROTOCOL_UPNP, "UPNP", },
+{ SDP_UUID_PROTOCOL_HIDP, "HIDP", },
+{ SDP_UUID_PROTOCOL_HARDCOPY_CONTROL_CHANNEL, "Hardcopy Control Channel", },
+{ SDP_UUID_PROTOCOL_HARDCOPY_DATA_CHANNEL, "Hardcopy Data Channel", },
+{ SDP_UUID_PROTOCOL_HARDCOPY_NOTIFICATION, "Hardcopy Notification", },
+{ SDP_UUID_PROTOCOL_AVCTP, "AVCTP", },
+{ SDP_UUID_PROTOCOL_AVDTP, "AVDTP", },
+{ SDP_UUID_PROTOCOL_CMPT, "CMPT", },
+{ SDP_UUID_PROTOCOL_UDI_C_PLANE, "UDI C-Plane", },
+{ SDP_UUID_PROTOCOL_L2CAP, "L2CAP", },
+/* Service Class IDs/Bluetooth Profile IDs */
+{ SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER, "Service Discovery Server", },
+{ SDP_SERVICE_CLASS_BROWSE_GROUP_DESCRIPTOR, "Browse Group Descriptor", },
+{ SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP, "Public Browse Group", },
+{ SDP_SERVICE_CLASS_SERIAL_PORT, "Serial Port", },
+{ SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP, "LAN Access Using PPP", },
+{ SDP_SERVICE_CLASS_DIALUP_NETWORKING, "DailUp Networking", },
+{ SDP_SERVICE_CLASS_IR_MC_SYNC, "IrMC Sync", },
+{ SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH, "OBEX Object Push", },
+{ SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER, "OBEX File Transfer", },
+{ SDP_SERVICE_CLASS_IR_MC_SYNC_COMMAND, "IrMC Sync Command", },
+{ SDP_SERVICE_CLASS_HEADSET, "Headset", },
+{ SDP_SERVICE_CLASS_CORDLESS_TELEPHONY, "Cordless Telephony", },
+{ SDP_SERVICE_CLASS_AUDIO_SOURCE, "Audio Source", },
+{ SDP_SERVICE_CLASS_AUDIO_SINK, "Audio Sink", },
+{ SDP_SERVICE_CLASS_AV_REMOTE_CONTROL_TARGET, "A/V Remote Control Target", },
+{ SDP_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION, "Advanced Audio Distribution", },
+{ SDP_SERVICE_CLASS_AV_REMOTE_CONTROL, "A/V Remote Control", },
+{ SDP_SERVICE_CLASS_VIDEO_CONFERENCING, "Video Conferencing", },
+{ SDP_SERVICE_CLASS_INTERCOM, "Intercom", },
+{ SDP_SERVICE_CLASS_FAX, "Fax", },
+{ SDP_SERVICE_CLASS_HEADSET_AUDIO_GATEWAY, "Headset Audio Gateway", },
+{ SDP_SERVICE_CLASS_WAP, "WAP", },
+{ SDP_SERVICE_CLASS_WAP_CLIENT, "WAP Client", },
+{ SDP_SERVICE_CLASS_PANU, "PANU", },
+{ SDP_SERVICE_CLASS_NAP, "Network Access Point", },
+{ SDP_SERVICE_CLASS_GN, "GN", },
+{ SDP_SERVICE_CLASS_DIRECT_PRINTING, "Direct Printing", },
+{ SDP_SERVICE_CLASS_REFERENCE_PRINTING, "Reference Printing", },
+{ SDP_SERVICE_CLASS_IMAGING, "Imaging", },
+{ SDP_SERVICE_CLASS_IMAGING_RESPONDER, "Imaging Responder", },
+{ SDP_SERVICE_CLASS_IMAGING_AUTOMATIC_ARCHIVE, "Imaging Automatic Archive", },
+{ SDP_SERVICE_CLASS_IMAGING_REFERENCED_OBJECTS, "Imaging Referenced Objects", },
+{ SDP_SERVICE_CLASS_HANDSFREE, "Handsfree", },
+{ SDP_SERVICE_CLASS_HANDSFREE_AUDIO_GATEWAY, "Handsfree Audio Gateway", },
+{ SDP_SERVICE_CLASS_DIRECT_PRINTING_REFERENCE_OBJECTS, "Direct Printing Reference Objects", },
+{ SDP_SERVICE_CLASS_REFLECTED_UI, "Reflected UI", },
+{ SDP_SERVICE_CLASS_BASIC_PRINTING, "Basic Printing", },
+{ SDP_SERVICE_CLASS_PRINTING_STATUS, "Printing Status", },
+{ SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE, "Human Interface Device", },
+{ SDP_SERVICE_CLASS_HARDCOPY_CABLE_REPLACEMENT, "Hardcopy Cable Replacement", },
+{ SDP_SERVICE_CLASS_HCR_PRINT, "HCR Print", },
+{ SDP_SERVICE_CLASS_HCR_SCAN, "HCR Scan", },
+{ SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS, "Common ISDN Access", },
+{ SDP_SERVICE_CLASS_VIDEO_CONFERENCING_GW, "Video Conferencing Gateway", },
+{ SDP_SERVICE_CLASS_UDI_MT, "UDI MT", },
+{ SDP_SERVICE_CLASS_UDI_TA, "UDI TA", },
+{ SDP_SERVICE_CLASS_AUDIO_VIDEO, "Audio/Video", },
+{ SDP_SERVICE_CLASS_SIM_ACCESS, "SIM Access", },
+{ SDP_SERVICE_CLASS_PNP_INFORMATION, "PNP Information", },
+{ SDP_SERVICE_CLASS_GENERIC_NETWORKING, "Generic Networking", },
+{ SDP_SERVICE_CLASS_GENERIC_FILE_TRANSFER, "Generic File Transfer", },
+{ SDP_SERVICE_CLASS_GENERIC_AUDIO, "Generic Audio", },
+{ SDP_SERVICE_CLASS_GENERIC_TELEPHONY, "Generic Telephony", },
+{ SDP_SERVICE_CLASS_UPNP, "UPNP", },
+{ SDP_SERVICE_CLASS_UPNP_IP, "UPNP IP", },
+{ SDP_SERVICE_CLASS_ESDP_UPNP_IP_PAN, "ESDP UPNP IP PAN", },
+{ SDP_SERVICE_CLASS_ESDP_UPNP_IP_LAP, "ESDP UPNP IP LAP", },
+{ SDP_SERVICE_CLASS_ESDP_UPNP_L2CAP, "ESDP UPNP L2CAP", },
+{ 0xffff, NULL, }
+};
+
+static sdp_attr_desc_t sdp_attrs_desc[] = {
+{ SDP_ATTR_SERVICE_RECORD_HANDLE,
+ "Record handle",
+ },
+{ SDP_ATTR_SERVICE_CLASS_ID_LIST,
+ "Service Class ID list",
+ },
+{ SDP_ATTR_SERVICE_RECORD_STATE,
+ "Service Record State",
+ },
+{ SDP_ATTR_SERVICE_ID,
+ "Service ID",
+ },
+{ SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
+ "Protocol Descriptor List",
+ },
+{ SDP_ATTR_BROWSE_GROUP_LIST,
+ "Browse Group List",
+ },
+{ SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST,
+ "Language Base Attribute ID List",
+ },
+{ SDP_ATTR_SERVICE_INFO_TIME_TO_LIVE,
+ "Service Info Time-To-Live",
+ },
+{ SDP_ATTR_SERVICE_AVAILABILITY,
+ "Service Availability",
+ },
+{ SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST,
+ "Bluetooh Profile Descriptor List",
+ },
+{ SDP_ATTR_DOCUMENTATION_URL,
+ "Documentation URL",
+ },
+{ SDP_ATTR_CLIENT_EXECUTABLE_URL,
+ "Client Executable URL",
+ },
+{ SDP_ATTR_ICON_URL,
+ "Icon URL",
+ },
+{ SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS,
+ "Additional Protocol Descriptor Lists" },
+{ SDP_ATTR_GROUP_ID,
+/*SDP_ATTR_IP_SUBNET,
+ SDP_ATTR_VERSION_NUMBER_LIST*/
+ "Group ID/IP Subnet/Version Number List",
+ },
+{ SDP_ATTR_SERVICE_DATABASE_STATE,
+ "Service Database State",
+ },
+{ SDP_ATTR_SERVICE_VERSION,
+ "Service Version",
+ },
+{ SDP_ATTR_EXTERNAL_NETWORK,
+/*SDP_ATTR_NETWORK,
+ SDP_ATTR_SUPPORTED_DATA_STORES_LIST*/
+ "External Network/Network/Supported Data Stores List",
+ },
+{ SDP_ATTR_FAX_CLASS1_SUPPORT,
+/*SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL*/
+ "Fax Class1 Support/Remote Audio Volume Control",
+ },
+{ SDP_ATTR_FAX_CLASS20_SUPPORT,
+/*SDP_ATTR_SUPPORTED_FORMATS_LIST*/
+ "Fax Class20 Support/Supported Formats List",
+ },
+{ SDP_ATTR_FAX_CLASS2_SUPPORT,
+ "Fax Class2 Support",
+ },
+{ SDP_ATTR_AUDIO_FEEDBACK_SUPPORT,
+ "Audio Feedback Support",
+ },
+{ SDP_ATTR_NETWORK_ADDRESS,
+ "Network Address",
+ },
+{ SDP_ATTR_WAP_GATEWAY,
+ "WAP Gateway",
+ },
+{ SDP_ATTR_HOME_PAGE_URL,
+ "Home Page URL",
+ },
+{ SDP_ATTR_WAP_STACK_TYPE,
+ "WAP Stack Type",
+ },
+{ SDP_ATTR_SECURITY_DESCRIPTION,
+ "Security Description",
+ },
+{ SDP_ATTR_NET_ACCESS_TYPE,
+ "Net Access Type",
+ },
+{ SDP_ATTR_MAX_NET_ACCESS_RATE,
+ "Max Net Access Rate",
+ },
+{ SDP_ATTR_IPV4_SUBNET,
+ "IPv4 Subnet",
+ },
+{ SDP_ATTR_IPV6_SUBNET,
+ "IPv6 Subnet",
+ },
+{ SDP_ATTR_SUPPORTED_CAPABALITIES,
+ "Supported Capabalities",
+ },
+{ SDP_ATTR_SUPPORTED_FEATURES,
+ "Supported Features",
+ },
+{ SDP_ATTR_SUPPORTED_FUNCTIONS,
+ "Supported Functions",
+ },
+{ SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY,
+ "Total Imaging Data Capacity",
+ },
+{ 0xffff, NULL, }
+};
+
+char const * const
+sdp_attr2desc(u_int16_t attr)
+{
+ register sdp_attr_desc_p a = sdp_attrs_desc;
+
+ for (; a->desc != NULL; a++)
+ if (attr == a->attr)
+ break;
+
+ return ((a->desc != NULL)? a->desc : "Unknown");
+}
+
+char const * const
+sdp_uuid2desc(u_int16_t uuid)
+{
+ register sdp_attr_desc_p a = sdp_uuids_desc;
+
+ for (; a->desc != NULL; a++)
+ if (uuid == a->attr)
+ break;
+
+ return ((a->desc != NULL)? a->desc : "Unknown");
+}
+
+void
+sdp_print(u_int32_t level, u_int8_t const *start, u_int8_t const *end)
+{
+ union {
+ int8_t int8;
+ int16_t int16;
+ int32_t int32;
+ int64_t int64;
+ int128_t int128;
+ uint8_t uint8;
+ uint16_t uint16;
+ uint32_t uint32;
+ uint64_t uint64;
+ } value;
+ u_int8_t type;
+ u_int32_t i;
+
+ if (start == NULL || end == NULL)
+ return;
+
+ while (start < end) {
+ for (i = 0; i < level; i++)
+ printf("\t");
+
+ SDP_GET8(type, start);
+
+ switch (type) {
+ case SDP_DATA_NIL:
+ printf("nil\n");
+ break;
+
+ case SDP_DATA_UINT8:
+ SDP_GET8(value.uint8, start);
+ printf("uint8 %u\n", value.uint8);
+ break;
+ case SDP_DATA_UINT16:
+ SDP_GET16(value.uint16, start);
+ printf("uint16 %u\n", value.uint16);
+ break;
+ case SDP_DATA_UINT32:
+ SDP_GET32(value.uint32, start);
+ printf("uint32 %u\n", value.uint32);
+ break;
+ case SDP_DATA_UINT64:
+ SDP_GET64(value.uint64, start);
+ printf("uint64 %llu\n", value.uint64);
+ break;
+
+ case SDP_DATA_UINT128:
+ case SDP_DATA_INT128:
+ case SDP_DATA_UUID128:
+ SDP_GET128(&value.int128, start);
+ printf("int128/uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n",
+ *(u_int32_t *)&value.int128.b[0],
+ *(u_int16_t *)&value.int128.b[4],
+ *(u_int16_t *)&value.int128.b[6],
+ *(u_int16_t *)&value.int128.b[8],
+ *(u_int16_t *)&value.int128.b[10],
+ *(u_int32_t *)&value.int128.b[12]);
+ break;
+
+ case SDP_DATA_INT8:
+ SDP_GET8(value.int8, start);
+ printf("int8 %d\n", value.int8);
+ break;
+ case SDP_DATA_INT16:
+ SDP_GET16(value.int16, start);
+ printf("int16 %d\n", value.int16);
+ break;
+ case SDP_DATA_INT32:
+ SDP_GET32(value.int32, start);
+ printf("int32 %d\n", value.int32);
+ break;
+ case SDP_DATA_INT64:
+ SDP_GET64(value.int64, start);
+ printf("int64 %lld\n", value.int64);
+ break;
+
+ case SDP_DATA_UUID16:
+ SDP_GET16(value.uint16, start);
+ printf("uuid16 %#4.4x - %s\n", value.uint16,
+ sdp_uuid2desc(value.uint16));
+ break;
+ case SDP_DATA_UUID32:
+ SDP_GET32(value.uint32, start);
+ printf("uuid32 %#8.8x\n", value.uint32);
+ break;
+
+ case SDP_DATA_STR8:
+ SDP_GET8(value.uint8, start);
+ printf("str8 %*.*s\n", value.uint8, value.uint8, start);
+ start += value.uint8;
+ break;
+ case SDP_DATA_STR16:
+ SDP_GET16(value.uint16, start);
+ printf("str16 %*.*s\n", value.uint16, value.uint16, start);
+ start += value.uint16;
+ break;
+ case SDP_DATA_STR32:
+ SDP_GET32(value.uint32, start);
+ printf("str32 %*.*s\n", value.uint32, value.uint32, start);
+ start += value.uint32;
+ break;
+
+ case SDP_DATA_BOOL:
+ SDP_GET8(value.uint8, start);
+ printf("bool %d\n", value.uint8);
+ break;
+
+ case SDP_DATA_SEQ8:
+ SDP_GET8(value.uint8, start);
+ printf("seq8 %d\n", value.uint8);
+ sdp_print(level + 1, start, start + value.uint8);
+ start += value.uint8;
+ break;
+ case SDP_DATA_SEQ16:
+ SDP_GET16(value.uint16, start);
+ printf("seq16 %d\n", value.uint16);
+ sdp_print(level + 1, start, start + value.uint16);
+ start += value.uint16;
+ break;
+ case SDP_DATA_SEQ32:
+ SDP_GET32(value.uint32, start);
+ printf("seq32 %d\n", value.uint32);
+ sdp_print(level + 1, start, start + value.uint32);
+ start += value.uint32;
+ break;
+
+ case SDP_DATA_ALT8:
+ SDP_GET8(value.uint8, start);
+ printf("alt8 %d\n", value.uint8);
+ sdp_print(level + 1, start, start + value.uint8);
+ start += value.uint8;
+ break;
+ case SDP_DATA_ALT16:
+ SDP_GET16(value.uint16, start);
+ printf("alt16 %d\n", value.uint16);
+ sdp_print(level + 1, start, start + value.uint16);
+ start += value.uint16;
+ break;
+ case SDP_DATA_ALT32:
+ SDP_GET32(value.uint32, start);
+ printf("alt32 %d\n", value.uint32);
+ sdp_print(level + 1, start, start + value.uint32);
+ start += value.uint32;
+ break;
+
+ case SDP_DATA_URL8:
+ SDP_GET8(value.uint8, start);
+ printf("url8 %*.*s\n", value.uint8, value.uint8, start);
+ start += value.uint8;
+ break;
+ case SDP_DATA_URL16:
+ SDP_GET16(value.uint16, start);
+ printf("url16 %*.*s\n", value.uint16, value.uint16, start);
+ start += value.uint16;
+ break;
+ case SDP_DATA_URL32:
+ SDP_GET32(value.uint32, start);
+ printf("url32 %*.*s\n", value.uint32, value.uint32, start);
+ start += value.uint32;
+ break;
+
+ default:
+ printf("unknown data type: %#02x\n", *start ++);
+ break;
+ }
+ }
+}
+