summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/Makefile.am2
-rw-r--r--include/sdp.h396
-rw-r--r--include/sdp_internal.h216
-rw-r--r--include/sdp_lib.h529
4 files changed, 1142 insertions, 1 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
index 27a769fa..f615705a 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -4,7 +4,7 @@
includedir = @includedir@/bluetooth
-include_HEADERS = bluetooth.h hci.h hci_lib.h hci_uart.h hci_vhci.h l2cap.h sco.h rfcomm.h
+include_HEADERS = bluetooth.h hci.h hci_lib.h hci_uart.h hci_vhci.h l2cap.h sco.h rfcomm.h sdp.h sdp_lib.h sdp_internal.h
bluetooth:
ln -s . bluetooth
diff --git a/include/sdp.h b/include/sdp.h
new file mode 100644
index 00000000..77564850
--- /dev/null
+++ b/include/sdp.h
@@ -0,0 +1,396 @@
+/*
+ Service Discovery Protocol (SDP)
+ Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
+
+ Based on original SDP implementation by Nokia Corporation.
+ Copyright (C) 2001,2002 Nokia Corporation.
+ Original author Guruprasad Krishnamurthy <guruprasad.krishnamurthy@nokia.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM,
+ OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS,
+ TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED.
+*/
+
+/*
+ * $Id$
+ */
+
+#ifndef SDP_H
+#define SDP_H
+
+#include <stdint.h>
+
+#define SDP_UNIX_PATH "/var/run/sdp"
+#define SDP_RESPONSE_TIMEOUT 20
+#define SDP_REQ_BUFFER_SIZE 2048
+#define SDP_RSP_BUFFER_SIZE 65535
+#define SDP_PDU_CHUNK_SIZE 1024
+
+/*
+ * All definitions are based on Bluetooth Assigned Numbers
+ * of the Bluetooth Specification
+ */
+#define SDP_PSM 0x0001
+
+/*
+ * Protocol UUIDs
+ */
+#define SDP_UUID 0x0001
+#define RFCOMM_UUID 0x0003
+#define TCS_BIN_UUID 0x0005
+#define L2CAP_UUID 0x0100
+#define IP_UUID 0x0009
+#define UDP_UUID 0x0002
+#define TCP_UUID 0x0004
+#define TCS_BIN_UUID 0x0005
+#define TCS_AT_UUID 0x0006
+#define OBEX_UUID 0x0008
+#define FTP_UUID 0x000A
+#define HTTP_UUID 0x000C
+#define WSP_UUID 0x000E
+#define BNEP_UUID 0x000F
+#define HIDP_UUID 0x0011
+#define CMTP_UUID 0x001B
+
+/*
+ * Service class identifiers of standard services and service groups
+ */
+#define SDP_SERVER_SVCLASS_ID 0x1000
+#define BROWSE_GRP_DESC_SVCLASS_ID 0x1001
+#define PUBLIC_BROWSE_GROUP 0x1002
+#define SERIAL_PORT_SVCLASS_ID 0x1101
+#define LAN_ACCESS_SVCLASS_ID 0x1102
+#define DIALUP_NET_SVCLASS_ID 0x1103
+#define IRMC_SYNC_SVCLASS_ID 0x1104
+#define OBEX_OBJPUSH_SVCLASS_ID 0x1105
+#define OBEX_FILETRANS_SVCLASS_ID 0x1106
+#define IRMC_SYNC_CMD_SVCLASS_ID 0x1107
+#define HEADSET_SVCLASS_ID 0x1108
+#define CORDLESS_TELEPHONY_SVCLASS_ID 0x1109
+#define INTERCOM_SVCLASS_ID 0x1110
+#define FAX_SVCLASS_ID 0x1111
+#define HEADSET_AGW_SVCLASS_ID 0x1112
+#define PANU_SVCLASS_ID 0x1115
+#define NAP_SVCLASS_ID 0x1116
+#define GN_SVCLASS_ID 0x1117
+#define IMAGING_SVCLASS_ID 0x111a
+#define IMAGING_RESPONDER_SVCLASS_ID 0x111b
+#define HANDSFREE_SVCLASS_ID 0x111e
+#define HANDSFREE_AUDIO_GW_SVCLASS_ID 0x111f
+#define HID_SVCLASS_ID 0x1124
+#define CIP_SVCLASS_ID 0x1128
+#define PNP_INFO_SVCLASS_ID 0x1200
+#define GENERIC_NETWORKING_SVCLASS_ID 0x1201
+#define GENERIC_FILETRANS_SVCLASS_ID 0x1202
+#define GENERIC_AUDIO_SVCLASS_ID 0x1203
+#define GENERIC_TELEPHONY_SVCLASS_ID 0x1204
+
+/*
+ * Standard profile descriptor identifiers; note these
+ * may be identical to some of the service classes defined above
+ */
+#define SERIAL_PORT_PROFILE_ID 0x1101
+#define LAN_ACCESS_PROFILE_ID 0x1102
+#define DIALUP_NET_PROFILE_ID 0x1103
+#define IRMC_SYNC_PROFILE_ID 0x1104
+#define OBEX_OBJPUSH_PROFILE_ID 0x1105
+#define OBEX_FILETRANS_PROFILE_ID 0x1106
+#define IRMC_SYNC_CMD_PROFILE_ID 0x1107
+#define HEADSET_PROFILE_ID 0x1108
+#define CORDLESS_TELEPHONY_PROFILE_ID 0x1109
+#define INTERCOM_PROFILE_ID 0x1110
+#define FAX_PROFILE_ID 0x1111
+#define HEADSET_AGW_PROFILE_ID 0x1112
+#define PANU_PROFILE_ID 0x1115
+#define NAP_PROFILE_ID 0x1116
+#define GN_PROFILE_ID 0x1117
+#define IMAGING_PROFILE_ID 0x111a
+#define IMAGING_RESPONDER_PROFILE_ID 0x111b
+#define HANDSFREE_PROFILE_ID 0x111e
+#define HID_PROFILE_ID 0x1124
+#define CIP_PROFILE_ID 0x1128
+
+/*
+ * Attribute identifier codes
+ */
+#define SDP_SERVER_RECORD_HANDLE 0x0000
+
+/*
+ * Possible values for attribute-id are listed below.
+ * See SDP Spec, section "Service Attribute Definitions" for more details.
+ */
+#define SDP_ATTR_RECORD_HANDLE 0x0000
+#define SDP_ATTR_SVCLASS_ID_LIST 0x0001
+#define SDP_ATTR_RECORD_STATE 0x0002
+#define SDP_ATTR_SERVICE_ID 0x0003
+#define SDP_ATTR_PROTO_DESC_LIST 0x0004
+#define SDP_ATTR_BROWSE_GRP_LIST 0x0005
+#define SDP_ATTR_LANG_BASE_ATTR_ID_LIST 0x0006
+#define SDP_ATTR_SVCINFO_TTL 0x0007
+#define SDP_ATTR_SERVICE_AVAILABILITY 0x0008
+#define SDP_ATTR_PFILE_DESC_LIST 0x0009
+#define SDP_ATTR_DOC_URL 0x000A
+#define SDP_ATTR_CLNT_EXEC_URL 0x000B
+#define SDP_ATTR_ICON_URL 0x000C
+
+#define SDP_ATTR_IP_SUBNET 0x0200
+#define SDP_ATTR_SERVICE_VERSION 0x0300
+#define SDP_EXTERNAL_NETWORK 0x0301
+#define SDP_ATTR_SUPPORTED_DATA_STORES_LIST 0x0301
+#define SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL 0x0302
+#define SDP_ATTR_SUPPORTED_FORMATS_LIST 0x0303
+#define SDP_ATTR_SECURITY_DESC 0x030A
+#define SDP_ATTR_NET_ACCESS_TYPE 0x030B
+#define SDP_ATTR_MAX_NET_ACCESSRATE 0x030C
+#define SDP_ATTR_IP4_SUBNET 0x030D
+#define SDP_ATTR_IP6_SUBNET 0x030E
+#define SDP_SUPPORTED_FEATURES 0x0311
+
+
+/*
+ * These identifiers are based on the SDP spec stating that
+ * "base attribute id of the primary (universal) language must be 0x0100"
+ */
+#define SDP_PRIMARY_LANG_BASE 0x0100
+
+#define SDP_ATTR_SVCNAME_PRIMARY 0x0000 + SDP_PRIMARY_LANG_BASE
+#define SDP_ATTR_SVCDESC_PRIMARY 0x0001 + SDP_PRIMARY_LANG_BASE
+#define SDP_ATTR_PROVNAME_PRIMARY 0x0002 + SDP_PRIMARY_LANG_BASE
+
+/*
+ * Other languages should have their own offset; e.g.:
+ * #define XXXLangBase yyyy
+ * #define AttrServiceName_XXX 0x0000+XXXLangBase
+ * ...
+ */
+
+/*
+ * These attributes are specific to the SDP server only; i.e.,
+ * can be present only in the service record of the SDP server
+ */
+#define SDP_ATTR_VERSION_NUM_LIST 0x0200
+#define SDP_ATTR_SVCDB_STATE 0x0201
+#define SDP_ATTR_GROUP_ID 0x0200
+
+/*
+ * The Data representation in SDP PDUs (pps 339, 340 of BT SDP Spec)
+ * These are the exact data type+size descriptor values
+ * that go into the PDU buffer.
+ *
+ * The datatype (leading 5bits) + size descriptor (last 3 bits)
+ * is 8 bits. The size descriptor is critical to extract the
+ * right number of bytes for the data value from the PDU.
+ *
+ * For most basic types, the datatype+size descriptor is
+ * straightforward. However for constructed types and strings,
+ * the size of the data is in the next "n" bytes following the
+ * 8 bits (datatype+size) descriptor. Exactly what the "n" is
+ * specified in the 3 bits of the data size descriptor.
+ *
+ * TextString and URLString can be of size 2^{8, 16, 32} bytes
+ * DataSequence and DataSequenceAlternates can be of size 2^{8, 16, 32}
+ * The size are computed post-facto in the API and are not known apriori
+ */
+#define SDP_DATA_NIL 0x00
+#define SDP_UINT8 0x08
+#define SDP_UINT16 0x09
+#define SDP_UINT32 0x0A
+#define SDP_UINT64 0x0B
+#define SDP_UINT128 0x0C
+#define SDP_INT8 0x10
+#define SDP_INT16 0x11
+#define SDP_INT32 0x12
+#define SDP_INT64 0x13
+#define SDP_INT128 0x14
+#define SDP_UUID_UNSPEC 0x18
+#define SDP_UUID16 0x19
+#define SDP_UUID32 0x1A
+#define SDP_UUID128 0x1C
+#define SDP_TEXT_STR_UNSPEC 0x20
+#define SDP_TEXT_STR8 0x25
+#define SDP_TEXT_STR16 0x26
+#define SDP_TEXT_STR32 0x27
+#define SDP_BOOL 0x28
+#define SDP_SEQ_UNSPEC 0x30
+#define SDP_SEQ8 0x35
+#define SDP_SEQ16 0x36
+#define SDP_SEQ32 0x37
+#define SDP_ALT_UNSPEC 0x38
+#define SDP_ALT8 0x3D
+#define SDP_ALT16 0x3E
+#define SDP_ALT32 0x3F
+#define SDP_URL_STR_UNSPEC 0x40
+#define SDP_URL_STR8 0x45
+#define SDP_URL_STR16 0x46
+#define SDP_URL_STR32 0x47
+
+/*
+ * The PDU identifiers of SDP packets between client and server
+ */
+#define SDP_ERROR_RSP 0x01
+#define SDP_SVC_SEARCH_REQ 0x02
+#define SDP_SVC_SEARCH_RSP 0x03
+#define SDP_SVC_ATTR_REQ 0x04
+#define SDP_SVC_ATTR_RSP 0x05
+#define SDP_SVC_SEARCH_ATTR_REQ 0x06
+#define SDP_SVC_SEARCH_ATTR_RSP 0x07
+
+/*
+ * Some additions to support service registration.
+ * These are outside the scope of the Bluetooth specification
+ */
+#define SDP_SVC_REGISTER_REQ 0x75
+#define SDP_SVC_REGISTER_RSP 0x76
+#define SDP_SVC_UPDATE_REQ 0x77
+#define SDP_SVC_UPDATE_RSP 0x78
+#define SDP_SVC_REMOVE_REQ 0x79
+#define SDP_SVC_REMOVE_RSP 0x80
+
+/*
+ * Values of the flags parameter to sdp_record_register
+ */
+#define SDP_RECORD_PERSIST 0x01
+
+/*
+ * Values of the flags parameter to sdp_connect
+ */
+#define SDP_RETRY_IF_BUSY 0x01
+
+/*
+ * SDP Error codes
+ */
+#define SDP_INVALID_VERSION 0x0001
+#define SDP_INVALID_RECORD_HANDLE 0x0002
+#define SDP_INVALID_SYNTAX 0x0003
+#define SDP_INVALID_PDU_SIZE 0x0004
+#define SDP_INVALID_CSTATE 0x0005
+
+/*
+ * SDP PDU
+ */
+typedef struct {
+ uint8_t pdu_id;
+ uint16_t tid;
+ uint16_t plen;
+} __attribute__ ((packed)) sdp_pdu_hdr_t;
+
+/*
+ * Common definitions for attributes in the SDP.
+ * Should the type of any of these change, you need only make a change here.
+ */
+typedef struct {
+ char data[16];
+} uint128_t;
+
+typedef struct {
+ uint8_t type;
+ union {
+ uint16_t uuid16;
+ uint32_t uuid32;
+ uint128_t uuid128;
+ } value;
+} uuid_t;
+
+#define SDP_IS_UUID(x) ((x) == SDP_UUID16 || (x) == SDP_UUID32 || (x) ==SDP_UUID128)
+
+typedef struct _sdp_list sdp_list_t;
+struct _sdp_list {
+ sdp_list_t *next;
+ void *data;
+};
+
+/*
+ * User-visible strings can be in many languages
+ * in addition to the universal language.
+ *
+ * Language meta-data includes language code in ISO639
+ * followed by the encoding format. The third field in this
+ * structure is the attribute offset for the language.
+ * User-visible strings in the specified language can be
+ * obtained at this offset.
+ */
+typedef struct {
+ uint16_t code_ISO639;
+ uint16_t encoding;
+ uint16_t base_offset;
+} sdp_lang_attr_t;
+
+/*
+ * Profile descriptor is the Bluetooth profile metadata. If a
+ * service conforms to a well-known profile, then its profile
+ * identifier (UUID) is an attribute of the service. In addition,
+ * if the profile has a version number it is specified here.
+ */
+typedef struct {
+ uuid_t uuid;
+ uint16_t version;
+} sdp_profile_desc_t;
+
+typedef struct {
+ uint8_t major;
+ uint8_t minor;
+} sdp_version_t;
+
+typedef struct {
+ char *data;
+ int data_size;
+ int buf_size;
+} sdp_buf_t;
+
+typedef struct {
+ uint32_t handle;
+
+ /*
+ * Search pattern: a sequence of all UUIDs seen in this record
+ */
+ sdp_list_t *pattern;
+ sdp_list_t *attrlist;
+} sdp_record_t;
+
+typedef struct sdp_data_struct sdp_data_t;
+struct sdp_data_struct {
+ uint8_t dtd;
+ uint16_t attrId;
+ union {
+ int8_t int8;
+ int16_t int16;
+ int32_t int32;
+ int64_t int64;
+ uint128_t int128;
+ uint8_t uint8;
+ uint16_t uint16;
+ uint32_t uint32;
+ uint64_t uint64;
+ uint128_t uint128;
+ uuid_t uuid;
+ char *str;
+ sdp_data_t *dataseq;
+ } val;
+ sdp_data_t *next;
+ int unitSize;
+};
+
+/*
+ * a session with an SDP server
+ */
+typedef struct {
+ int sock;
+ int state;
+ int local;
+ int flags;
+ uint16_t tid; // Current transaction ID
+} sdp_session_t;
+
+#endif
diff --git a/include/sdp_internal.h b/include/sdp_internal.h
new file mode 100644
index 00000000..fabf7a0d
--- /dev/null
+++ b/include/sdp_internal.h
@@ -0,0 +1,216 @@
+/*
+ Service Discovery Protocol (SDP)
+ Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>, Stephen Crane <steve.crane@rococosoft.com>
+
+ Based on original SDP implementation by Nokia Corporation.
+ Copyright (C) 2001,2002 Nokia Corporation.
+ Original author Guruprasad Krishnamurthy <guruprasad.krishnamurthy@nokia.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM,
+ OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS,
+ TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED.
+*/
+
+/*
+ * $Id$
+ */
+
+#ifndef SDP_INTERNAL_H
+#define SDP_INTERNAL_H
+
+#include <syslog.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <bluetooth/bluetooth.h>
+
+#define SDPINF(fmt, arg...) syslog(LOG_INFO, fmt "\n", ## arg)
+#define SDPERR(fmt, arg...) syslog(LOG_ERR, "%s: " fmt "\n", __func__ , ## arg)
+
+#ifdef SDP_DEBUG
+#define SDPDBG(fmt, arg...) syslog(LOG_DEBUG, "%s: " fmt "\n", __func__ , ## arg)
+#else
+#define SDPDBG(fmt...)
+#endif
+
+#define SDP_BASIC_ATTR_PDUFORM_SIZE 32
+#define SDP_SEQ_PDUFORM_SIZE 128
+#define SDP_UUID_SEQ_SIZE 256
+#define SDP_MAX_ATTR_LEN 65535
+
+/*
+ * Generate unique transaction identifiers
+ */
+static inline uint16_t sdp_gen_tid(sdp_session_t *session)
+{
+ return session->tid++;
+}
+
+sdp_record_t *sdp_extract_pdu(const char *pdata, int *scanned);
+sdp_data_t *sdp_extract_string(char *, int *);
+
+void sdp_data_print(sdp_data_t *data);
+void sdp_print_service_attr(sdp_list_t *alist);
+
+int sdp_attrid_comp_func(const void *key1, const void *key2);
+
+void sdp_set_seq_len(char *ptr, int length);
+void sdp_set_attrid(sdp_buf_t *pdu, uint16_t id);
+void sdp_append_to_pdu(sdp_buf_t *dst, sdp_data_t *d);
+void sdp_append_to_buf(sdp_buf_t *dst, char *data, int len);
+
+int sdp_gen_pdu(sdp_buf_t *pdu, sdp_data_t *data);
+int sdp_gen_record_pdu(const sdp_record_t *rec, sdp_buf_t *pdu);
+
+int sdp_extract_seqtype(const char *buf, uint8_t *dtdp, int *seqlen);
+
+sdp_data_t *sdp_extract_attr(const char *pdata, int *extractedLength, sdp_record_t *rec);
+
+void sdp_pattern_add_uuid(sdp_record_t *rec, uuid_t *uuid);
+void sdp_pattern_add_uuidseq(sdp_record_t *rec, sdp_list_t *seq);
+
+int sdp_send_req_w4_rsp(sdp_session_t *session, char *req, char *rsp, int reqsize, int *rspsize);
+
+typedef struct {
+ uint8_t length;
+ unsigned char data[16];
+} __attribute__ ((packed)) sdp_cstate_t;
+
+/*
+ * SDP unaligned access.
+ * based on linux/asm-<arch>/unaligned.h
+ */
+#if defined(__i386__)
+
+#define sdp_get_unaligned(ptr) (*(ptr))
+#define sdp_put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+
+#else
+
+struct __una_u64 { uint64_t x; } __attribute__((packed));
+struct __una_u32 { uint32_t x; } __attribute__((packed));
+struct __una_u16 { uint16_t x; } __attribute__((packed));
+
+static inline unsigned long long __uldq(const unsigned long *r11)
+{
+ const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
+ return ptr->x;
+}
+
+static inline unsigned long __uldl(const unsigned int * r11)
+{
+ const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
+ return ptr->x;
+}
+
+static inline unsigned long __uldw(const unsigned short * r11)
+{
+ const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
+ return ptr->x;
+}
+
+static inline void __ustq(unsigned long r5, unsigned long * r11)
+{
+ struct __una_u64 *ptr = (struct __una_u64 *) r11;
+ ptr->x = r5;
+}
+
+static inline void __ustl(unsigned long r5, unsigned int * r11)
+{
+ struct __una_u32 *ptr = (struct __una_u32 *) r11;
+ ptr->x = r5;
+}
+
+static inline void __ustw(unsigned long r5, unsigned short * r11)
+{
+ struct __una_u16 *ptr = (struct __una_u16 *) r11;
+ ptr->x = r5;
+}
+
+static inline unsigned long long __sdp_get_unaligned(const void *ptr, size_t size)
+{
+ unsigned long long val = 0;
+ switch (size) {
+ case 1:
+ val = *(const unsigned char *)ptr;
+ break;
+ case 2:
+ val = __uldw((const unsigned short *)ptr);
+ break;
+ case 4:
+ val = __uldl((const unsigned int *)ptr);
+ break;
+ case 8:
+ val = __uldq((const unsigned long *)ptr);
+ break;
+ }
+ return val;
+}
+
+static inline void __sdp_put_unaligned(unsigned long val, void *ptr, size_t size)
+{
+ switch (size) {
+ case 1:
+ *(unsigned char *)ptr = (val);
+ break;
+ case 2:
+ __ustw(val, (unsigned short *)ptr);
+ break;
+ case 4:
+ __ustl(val, (unsigned int *)ptr);
+ break;
+ case 8:
+ __ustq(val, (unsigned long *)ptr);
+ break;
+ }
+}
+
+#define sdp_get_unaligned(ptr) \
+ ((__typeof__(*(ptr)))__sdp_get_unaligned((ptr), sizeof(*(ptr))))
+
+#define sdp_put_unaligned(x,ptr) \
+ __sdp_put_unaligned((unsigned long)(x), (ptr), sizeof(*(ptr)))
+
+#endif
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define ntoh64(x) x
+static inline void ntoh128(uint128_t *src, uint128_t *dst)
+{
+ int i;
+ for (i=0; i < 16; i++)
+ dst->data[i] = src->data[i];
+}
+#else
+static inline uint64_t ntoh64(uint64_t n)
+{
+ uint64_t h;
+ uint64_t tmp = ntohl(n & 0x00000000ffffffff);
+ h = ntohl(n >> 32);
+ h |= tmp << 32;
+ return h;
+}
+
+static inline void ntoh128(uint128_t *src, uint128_t *dst)
+{
+ int i;
+ for (i=0; i < 16; i++)
+ dst->data[15 - i] = src->data[i];
+}
+#endif
+
+#define hton64(x) ntoh64(x)
+#define hton128(x,y) ntoh128(x,y)
+
+#endif
diff --git a/include/sdp_lib.h b/include/sdp_lib.h
new file mode 100644
index 00000000..4306eb55
--- /dev/null
+++ b/include/sdp_lib.h
@@ -0,0 +1,529 @@
+/*
+ Service Discovery Protocol (SDP)
+ Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>, Stephen Crane <steve.crane@rococosoft.com>
+
+ Based on original SDP implementation by Nokia Corporation.
+ Copyright (C) 2001,2002 Nokia Corporation.
+ Original author Guruprasad Krishnamurthy <guruprasad.krishnamurthy@nokia.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 as
+ published by the Free Software Foundation;
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM,
+ OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+ RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ USE OR PERFORMANCE OF THIS SOFTWARE.
+
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS,
+ TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef SDP_LIB_H
+#define SDP_LIB_H
+
+#include <sys/socket.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * SDP lists
+ */
+typedef void(*sdp_list_func_t)(void *, void *);
+typedef void(*sdp_free_func_t)(void *);
+typedef int (*sdp_comp_func_t)(const void *, const void *);
+
+sdp_list_t *sdp_list_append(sdp_list_t *list, void *d);
+sdp_list_t *sdp_list_remove(sdp_list_t *list, void *d);
+sdp_list_t *sdp_list_insert_sorted(sdp_list_t *list, void *data, sdp_comp_func_t f);
+void sdp_list_free(sdp_list_t *list, sdp_free_func_t f);
+
+static inline int sdp_list_len(const sdp_list_t *list)
+{
+ int n = 0;
+ for (; list; list = list->next)
+ n++;
+ return n;
+}
+
+static inline sdp_list_t *sdp_list_find(sdp_list_t *list, void *u, sdp_comp_func_t f)
+{
+ for (; list; list = list->next)
+ if (f(list->data, u) == 0)
+ return list;
+ return NULL;
+}
+
+static inline void sdp_list_foreach(sdp_list_t *list, sdp_list_func_t f, void *u)
+{
+ for (; list; list = list->next)
+ f(list->data, u);
+}
+
+/*
+ * create an L2CAP connection to a Bluetooth device
+ *
+ * INPUT:
+ *
+ * bdaddr_t *src:
+ * Address of the local device to use to make the connection
+ * (or BDADDR_ANY)
+ *
+ * bdaddr_t *dst:
+ * Address of the SDP server device
+ */
+sdp_session_t *sdp_connect(const bdaddr_t *src, const bdaddr_t *dst, uint32_t flags);
+int sdp_close(sdp_session_t *session);
+
+static inline int sdp_get_socket(const sdp_session_t *s)
+{
+ return s->sock;
+}
+
+/*
+ * find all devices in the piconet
+ */
+int sdp_general_inquiry(inquiry_info *ii, int dev_num, int duration, uint8_t *found);
+
+/* flexible extraction of basic attributes - Jean II */
+int sdp_get_int_attr(const sdp_record_t *rec, uint16_t attr, int *value);
+int sdp_get_string_attr(const sdp_record_t *rec, uint16_t attr, char *value, int valuelen);
+
+/*
+ * Basic sdp data functions
+ */
+sdp_data_t *sdp_data_alloc(uint8_t dtd, const void *value);
+void sdp_data_free(sdp_data_t *data);
+sdp_data_t *sdp_data_get(const sdp_record_t *rec, uint16_t attr_id);
+
+sdp_data_t *sdp_seq_alloc(void **dtds, void **values, int len);
+sdp_data_t *sdp_seq_append(sdp_data_t *seq, sdp_data_t *data);
+
+int sdp_attr_add(sdp_record_t *rec, uint16_t attr, sdp_data_t *data);
+void sdp_attr_remove(sdp_record_t *rec, uint16_t attr);
+void sdp_attr_replace(sdp_record_t *rec, uint16_t attr, sdp_data_t *data);
+int sdp_set_uuidseq_attr(sdp_record_t *rec, uint16_t attr, sdp_list_t *seq);
+int sdp_get_uuidseq_attr(const sdp_record_t *rec, uint16_t attr, sdp_list_t **seqp);
+
+/*
+ * NOTE that none of the functions below will update the SDP server,
+ * unless the {register, update}sdp_record_t() function is invoked.
+ * All functions which return an integer value, return 0 on success
+ * or -1 on failure.
+ */
+
+/*
+ * Create an attribute and add it to the service record's attribute list.
+ * This consists of the data type descriptor of the attribute,
+ * the value of the attribute and the attribute identifier.
+ */
+int sdp_attr_add_new(sdp_record_t *rec, uint16_t attr, uint8_t dtd, const void *p);
+
+/*
+ * Set the information attributes of the service record.
+ * The set of attributes comprises service name, description
+ * and provider name
+ */
+void sdp_set_info_attr(sdp_record_t *rec, const char *name, const char *prov, const char *desc);
+
+/*
+ * Set the ServiceClassID attribute to the sequence specified by seq.
+ * Note that the identifiers need to be in sorted order from the most
+ * specific to the most generic service class that this service
+ * conforms to.
+ */
+static inline int sdp_set_service_classes(sdp_record_t *rec, sdp_list_t *seq)
+{
+ return sdp_set_uuidseq_attr(rec, SDP_ATTR_SVCLASS_ID_LIST, seq);
+}
+
+/*
+ * Get the service classes to which the service conforms.
+ *
+ * When set, the list contains elements of ServiceClassIdentifer(uint16_t)
+ * ordered from most specific to most generic
+ */
+static inline int sdp_get_service_classes(const sdp_record_t *rec, sdp_list_t **seqp)
+{
+ return sdp_get_uuidseq_attr(rec, SDP_ATTR_SVCLASS_ID_LIST, seqp);
+}
+
+/*
+ * Set the BrowseGroupList attribute to the list specified by seq.
+ *
+ * A service can belong to one or more service groups
+ * and the list comprises such group identifiers (UUIDs)
+ */
+static inline int sdp_set_browse_groups(sdp_record_t *rec, sdp_list_t *seq)
+{
+ return sdp_set_uuidseq_attr(rec, SDP_ATTR_BROWSE_GRP_LIST, seq);
+}
+
+/*
+ * Set the access protocols of the record to those specified in proto
+ */
+int sdp_set_access_protos(sdp_record_t *rec, const sdp_list_t *proto);
+
+/*
+ * Get protocol port (i.e. PSM for L2CAP, Channel for RFCOMM)
+ */
+int sdp_get_proto_port(const sdp_list_t *list, int proto);
+
+/*
+ * Get protocol descriptor.
+ */
+sdp_data_t *sdp_get_proto_desc(sdp_list_t *list, int proto);
+
+/*
+ * Set the LanguageBase attributes to the values specified in list
+ * (a linked list of sdp_lang_attr_t objects, one for each language in
+ * which user-visible attributes are present).
+ */
+int sdp_set_lang_attr(sdp_record_t *rec, const sdp_list_t *list);
+
+/*
+ * Set the ServiceInfoTimeToLive attribute of the service.
+ * This is the number of seconds that this record is guaranteed
+ * not to change after being obtained by a client.
+ */
+static inline int sdp_set_service_ttl(sdp_record_t *rec, uint32_t ttl)
+{
+ return sdp_attr_add_new(rec, SDP_ATTR_SVCINFO_TTL, SDP_UINT32, &ttl);
+}
+
+/*
+ * Set the ServiceRecordState attribute of a service. This is
+ * guaranteed to change if there is any kind of modification to
+ * the record.
+ */
+static inline int sdp_set_record_state(sdp_record_t *rec, uint32_t state)
+{
+ return sdp_attr_add_new(rec, SDP_ATTR_RECORD_STATE, SDP_UINT32, &state);
+}
+
+/*
+ * Set the ServiceID attribute of a service.
+ */
+void sdp_set_service_id(sdp_record_t *rec, uuid_t uuid);
+
+/*
+ * Set the GroupID attribute of a service
+ */
+void sdp_set_group_id(sdp_record_t *rec, uuid_t grouuuid);
+
+/*
+ * Set the ServiceAvailability attribute of a service.
+ *
+ * Note that this represents the relative availability
+ * of the service: 0x00 means completely unavailable;
+ * 0xFF means maximum availability.
+ */
+static inline int sdp_set_service_avail(sdp_record_t *rec, uint8_t avail)
+{
+ return sdp_attr_add_new(rec, SDP_ATTR_SERVICE_AVAILABILITY, SDP_UINT8, &avail);
+}
+
+/*
+ * Set the profile descriptor list attribute of a record.
+ *
+ * Each element in the list is an object of type
+ * sdp_profile_desc_t which is a definition of the
+ * Bluetooth profile that this service conforms to.
+ */
+int sdp_set_profile_descs(sdp_record_t *rec, const sdp_list_t *desc);
+
+/*
+ * Set URL attributes of a record.
+ *
+ * ClientExecutableURL: a URL to a client's platform specific (WinCE,
+ * PalmOS) executable code that can be used to access this service.
+ *
+ * DocumentationURL: a URL pointing to service documentation
+ *
+ * IconURL: a URL to an icon that can be used to represent this service.
+ *
+ * Note: pass NULL for any URLs that you don't want to set or remove
+ */
+void sdp_set_url_attr(sdp_record_t *rec, const char *clientExecURL, const char *docURL, const char *iconURL);
+
+/*
+ * a service search request.
+ *
+ * INPUT :
+ *
+ * sdp_list_t *search_list
+ * list containing elements of the search
+ * pattern. Each entry in the list is a UUID
+ * of the service to be searched
+ *
+ * uint16_t max_rec_num
+ * An integer specifying the maximum number of
+ * entries that the client can handle in the response.
+ *
+ * OUTPUT :
+ *
+ * int return value
+ * 0
+ * The request completed successfully. This does not
+ * mean the requested services were found
+ * -1
+ * The request completed unsuccessfully
+ *
+ * sdp_list_t *rsp_list
+ * This variable is set on a successful return if there are
+ * non-zero service handles. It is a singly linked list of
+ * service records (sdp_record_t)
+ */
+int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search_list, uint16_t max_rec_num, sdp_list_t **rsp_list);
+
+/*
+ * a service attribute request.
+ *
+ * INPUT :
+ *
+ * uint32_t handle
+ * The handle of the service for which the attribute(s) are
+ * requested
+ *
+ * sdp_attrreq_type_t reqtype
+ * Attribute identifiers are 16 bit unsigned integers specified
+ * in one of 2 ways described below :
+ * SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers
+ * They are the actual attribute identifiers in ascending order
+ *
+ * SDP_ATTR_REQ_RANGE - 32bit identifier range
+ * The high-order 16bits is the start of range
+ * the low-order 16bits are the end of range
+ * 0x0000 to 0xFFFF gets all attributes
+ *
+ * sdp_list_t *attrid_list
+ * Singly linked list containing attribute identifiers desired.
+ * Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL)
+ * or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE)
+ *
+ * OUTPUT :
+ * int return value
+ * 0
+ * The request completed successfully. This does not
+ * mean the requested services were found
+ * -1
+ * The request completed unsuccessfully due to a timeout
+ */
+
+typedef enum {
+ /*
+ * Attributes are specified as individual elements
+ */
+ SDP_ATTR_REQ_INDIVIDUAL = 1,
+ /*
+ * Attributes are specified as a range
+ */
+ SDP_ATTR_REQ_RANGE
+} sdp_attrreq_type_t;
+
+sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list);
+
+/*
+ * This is a service search request combined with the service
+ * attribute request. First a service class match is done and
+ * for matching service, requested attributes are extracted
+ *
+ * INPUT :
+ *
+ * sdp_list_t *search_list
+ * Singly linked list containing elements of the search
+ * pattern. Each entry in the list is a UUID(DataTypeSDP_UUID16)
+ * of the service to be searched
+ *
+ * AttributeSpecification attrSpec
+ * Attribute identifiers are 16 bit unsigned integers specified
+ * in one of 2 ways described below :
+ * SDP_ATTR_REQ_INDIVIDUAL - 16bit individual identifiers
+ * They are the actual attribute identifiers in ascending order
+ *
+ * SDP_ATTR_REQ_RANGE - 32bit identifier range
+ * The high-order 16bits is the start of range
+ * the low-order 16bits are the end of range
+ * 0x0000 to 0xFFFF gets all attributes
+ *
+ * sdp_list_t *attrid_list
+ * Singly linked list containing attribute identifiers desired.
+ * Every element is either a uint16_t(attrSpec = SDP_ATTR_REQ_INDIVIDUAL)
+ * or a uint32_t(attrSpec=SDP_ATTR_REQ_RANGE)
+ *
+ * OUTPUT :
+ * int return value
+ * 0
+ * The request completed successfully. This does not
+ * mean the requested services were found
+ * -1
+ * The request completed unsuccessfully due to a timeout
+ *
+ * sdp_list_t *rsp_list
+ * This variable is set on a successful return to point to
+ * service(s) found. Each element of this list is of type
+ * sdp_record_t *.
+ */
+int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search_list, sdp_attrreq_type_t reqtype, const sdp_list_t *attrid_list, sdp_list_t **rsp_list);
+
+/*
+ * Allocate/free a service record and its attributes
+ */
+sdp_record_t *sdp_record_alloc(void);
+void sdp_record_free(sdp_record_t *rec);
+
+/*
+ * Register a service record.
+ *
+ * Note: It is the responsbility of the Service Provider to create the
+ * record first and set its attributes using setXXX() methods.
+ *
+ * The service provider must then call sdp_record_register() to make
+ * the service record visible to SDP clients.
+ */
+int sdp_record_register(sdp_session_t *sess, sdp_record_t *rec, uint8_t flags);
+
+/*
+ * Unregister a service record.
+ */
+int sdp_record_unregister(sdp_session_t *sess, sdp_record_t *rec);
+
+/*
+ * Update an existing service record. (Calling this function
+ * before a previous call to sdp_record_register() will result
+ * in an error.)
+ */
+int sdp_record_update(sdp_session_t *sess, const sdp_record_t *rec);
+
+void sdp_record_print(const sdp_record_t *rec);
+
+/*
+ * UUID functions
+ */
+uuid_t *sdp_uuid16_create(uuid_t *uuid, uint16_t data);
+uuid_t *sdp_uuid32_create(uuid_t *uuid, uint32_t data);
+uuid_t *sdp_uuid128_create(uuid_t *uuid, const void *data);
+int sdp_uuid16_cmp(const void *p1, const void *p2);
+int sdp_uuid128_cmp(const void *p1, const void *p2);
+uuid_t *sdp_uuid_to_uuid128(uuid_t *uuid);
+void sdp_uuid16_to_uuid128(uuid_t *uuid128, uuid_t *uuid16);
+int sdp_uuid128_to_uuid(uuid_t *uuid);
+int sdp_uuid_to_proto(uuid_t *uuid);
+int sdp_uuid_extract(const char *buffer, uuid_t *uuid, int *scanned);
+void sdp_uuid_print(const uuid_t *uuid);
+
+#define MAX_LEN_UUID_STR 37
+#define MAX_LEN_PROTOCOL_UUID_STR 8
+#define MAX_LEN_SERVICECLASS_UUID_STR 24
+#define MAX_LEN_PROFILEDESCRIPTOR_UUID_STR 22
+
+int sdp_uuid2strn(const uuid_t *uuid, char *str, size_t n);
+int sdp_proto_uuid2strn(const uuid_t *uuid, char *str, size_t n);
+int sdp_svclass_uuid2strn(const uuid_t *uuid, char *str, size_t n);
+int sdp_profile_uuid2strn(const uuid_t *uuid, char *str, size_t n);
+
+/*
+ * In all the sdp_get_XXX(handle, XXX *xxx) functions below,
+ * the XXX * is set to point to the value, should it exist
+ * and 0 is returned. If the value does not exist, -1 is
+ * returned and errno set to ENODATA.
+ *
+ * In all the methods below, the memory management rules are
+ * simple. Don't free anything! The pointer returned, in the
+ * case of constructed types, is a pointer to the contents
+ * of the sdp_record_t.
+ */
+
+/*
+ * Get the access protocols from the service record
+ */
+int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **protos);
+
+/*
+ * Extract the list of browse groups to which the service belongs.
+ * When set, seqp contains elements of GroupID (uint16_t)
+ */
+static inline int sdp_get_browse_groups(const sdp_record_t *rec, sdp_list_t **seqp)
+{
+ return sdp_get_uuidseq_attr(rec, SDP_ATTR_BROWSE_GRP_LIST, seqp);
+}
+
+/*
+ * Extract language attribute meta-data of the service record.
+ * For each language in the service record, LangSeq has a struct of type
+ * sdp_lang_attr_t.
+ */
+int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq);
+
+/*
+ * Extract the Bluetooth profile descriptor sequence from a record.
+ * Each element in the list is of type sdp_profile_desc_t
+ * which contains the UUID of the profile and its version number
+ * (encoded as major and minor in the high-order 8bits
+ * and low-order 8bits respectively of the uint16_t)
+ */
+int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDesc);
+
+/*
+ * Extract SDP server version numbers
+ *
+ * Note: that this is an attribute of the SDP server only and
+ * contains a list of uint16_t each of which represent the
+ * major and minor SDP version numbers supported by this server
+ */
+int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **pVnumList);
+
+int sdp_get_service_id(const sdp_record_t *rec, uuid_t *uuid);
+int sdp_get_group_id(const sdp_record_t *rec, uuid_t *uuid);
+int sdp_get_record_state(const sdp_record_t *rec, uint32_t *svcRecState);
+int sdp_get_service_avail(const sdp_record_t *rec, uint8_t *svcAvail);
+int sdp_get_service_ttl(const sdp_record_t *rec, uint32_t *svcTTLInfo);
+int sdp_get_database_state(const sdp_record_t *rec, uint32_t *svcDBState);
+
+static inline int sdp_get_service_name(const sdp_record_t *rec, char *str, int len)
+{
+ return sdp_get_string_attr(rec, SDP_ATTR_SVCNAME_PRIMARY, str, len);
+}
+
+static inline int sdp_get_service_desc(const sdp_record_t *rec, char *str, int len)
+{
+ return sdp_get_string_attr(rec, SDP_ATTR_SVCDESC_PRIMARY, str, len);
+}
+
+static inline int sdp_get_provider_name(const sdp_record_t *rec, char *str, int len)
+{
+ return sdp_get_string_attr(rec, SDP_ATTR_PROVNAME_PRIMARY, str, len);
+}
+
+static inline int sdp_get_doc_url(const sdp_record_t *rec, char *str, int len)
+{
+ return sdp_get_string_attr(rec, SDP_ATTR_DOC_URL, str, len);
+}
+
+static inline int sdp_get_clnt_exec_url(const sdp_record_t *rec, char *str, int len)
+{
+ return sdp_get_string_attr(rec, SDP_ATTR_CLNT_EXEC_URL, str, len);
+}
+
+static inline int sdp_get_icon_url(const sdp_record_t *rec, char *str, int len)
+{
+ return sdp_get_string_attr(rec, SDP_ATTR_ICON_URL, str, len);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif