Module Name:    src
Committed By:   plunky
Date:           Tue May 12 18:39:20 UTC 2009

Modified Files:
        src/usr.sbin/btdevctl: Makefile btdevctl.c sdp.c

Log Message:
update to use new sdp(3) and sdp_data(3) APIs


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/usr.sbin/btdevctl/Makefile
cvs rdiff -u -r1.7 -r1.8 src/usr.sbin/btdevctl/btdevctl.c
cvs rdiff -u -r1.6 -r1.7 src/usr.sbin/btdevctl/sdp.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/btdevctl/Makefile
diff -u src/usr.sbin/btdevctl/Makefile:1.4 src/usr.sbin/btdevctl/Makefile:1.5
--- src/usr.sbin/btdevctl/Makefile:1.4	Tue May 12 13:09:43 2009
+++ src/usr.sbin/btdevctl/Makefile	Tue May 12 18:39:20 2009
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.4 2009/05/12 13:09:43 plunky Exp $
+# $NetBSD: Makefile,v 1.5 2009/05/12 18:39:20 plunky Exp $
 
 PROG=		btdevctl
 MAN=		btdevctl.8
@@ -7,6 +7,4 @@
 DPADD+=		${LIBBLUETOOTH} ${LIBPROP} ${LIBUSBHID}
 LDADD+=		-lbluetooth -lprop -lusbhid
 
-CPPFLAGS+=	-DSDP_COMPAT
-
 .include <bsd.prog.mk>

Index: src/usr.sbin/btdevctl/btdevctl.c
diff -u src/usr.sbin/btdevctl/btdevctl.c:1.7 src/usr.sbin/btdevctl/btdevctl.c:1.8
--- src/usr.sbin/btdevctl/btdevctl.c:1.7	Mon Jul 21 13:36:57 2008
+++ src/usr.sbin/btdevctl/btdevctl.c	Tue May 12 18:39:20 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: btdevctl.c,v 1.7 2008/07/21 13:36:57 lukem Exp $	*/
+/*	$NetBSD: btdevctl.c,v 1.8 2009/05/12 18:39:20 plunky Exp $	*/
 
 /*-
  * Copyright (c) 2006 Itronix Inc.
@@ -32,8 +32,10 @@
  */
 
 #include <sys/cdefs.h>
-__COPYRIGHT("@(#) Copyright (c) 2006 Itronix, Inc.  All rights reserved.");
-__RCSID("$NetBSD: btdevctl.c,v 1.7 2008/07/21 13:36:57 lukem Exp $");
+__COPYRIGHT("@(#) Copyright (c) 2006 The NetBSD Foundation, Inc.\
+  @(#) Copyright (c) 2006 Itronix, Inc.\
+  All rights reserved.");
+__RCSID("$NetBSD: btdevctl.c,v 1.8 2009/05/12 18:39:20 plunky Exp $");
 
 #include <prop/proplib.h>
 #include <sys/ioctl.h>

Index: src/usr.sbin/btdevctl/sdp.c
diff -u src/usr.sbin/btdevctl/sdp.c:1.6 src/usr.sbin/btdevctl/sdp.c:1.7
--- src/usr.sbin/btdevctl/sdp.c:1.6	Wed Apr 15 00:35:04 2009
+++ src/usr.sbin/btdevctl/sdp.c	Tue May 12 18:39:20 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdp.c,v 1.6 2009/04/15 00:35:04 lukem Exp $	*/
+/*	$NetBSD: sdp.c,v 1.7 2009/05/12 18:39:20 plunky Exp $	*/
 
 /*-
  * Copyright (c) 2006 Itronix Inc.
@@ -29,6 +29,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 /*
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
  * Copyright (c) 2004 Maksim Yevmenkin <m_evmen...@yahoo.com>
  * All rights reserved.
  *
@@ -55,7 +56,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: sdp.c,v 1.6 2009/04/15 00:35:04 lukem Exp $");
+__RCSID("$NetBSD: sdp.c,v 1.7 2009/05/12 18:39:20 plunky Exp $");
 
 #include <sys/types.h>
 
@@ -72,125 +73,104 @@
 #include <errno.h>
 #include <sdp.h>
 #include <stdlib.h>
+#include <strings.h>
 #include <usbhid.h>
 
 #include "btdevctl.h"
 
-static int32_t parse_l2cap_psm(sdp_attr_t *);
-static int32_t parse_rfcomm_channel(sdp_attr_t *);
-static int32_t parse_hid_descriptor(sdp_attr_t *);
-static int32_t parse_boolean(sdp_attr_t *);
-
-static int config_hid(prop_dictionary_t);
-static int config_hset(prop_dictionary_t);
-static int config_hf(prop_dictionary_t);
+static bool parse_hid_descriptor(sdp_data_t *);
+static int32_t parse_boolean(sdp_data_t *);
+static int32_t parse_pdl_param(sdp_data_t *, uint16_t);
+static int32_t parse_pdl(sdp_data_t *, uint16_t);
+static int32_t parse_apdl(sdp_data_t *, uint16_t);
+
+static int config_hid(prop_dictionary_t, sdp_data_t *);
+static int config_hset(prop_dictionary_t, sdp_data_t *);
+static int config_hf(prop_dictionary_t, sdp_data_t *);
 
 uint16_t hid_services[] = {
-	SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE
-};
-
-uint32_t hid_attrs[] = {
-	SDP_ATTR_RANGE(	SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
-			SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST),
-	SDP_ATTR_RANGE( SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS,
-			SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS),
-	SDP_ATTR_RANGE(	0x0205,		/* HIDReconnectInitiate */
-			0x0206),	/* HIDDescriptorList */
-	SDP_ATTR_RANGE(	0x0209,		/* HIDBatteryPower */
-			0x0209),
-	SDP_ATTR_RANGE(	0x020d,		/* HIDNormallyConnectable */
-			0x020d)
+	SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE,
 };
 
 uint16_t hset_services[] = {
-	SDP_SERVICE_CLASS_HEADSET
-};
-
-uint32_t hset_attrs[] = {
-	SDP_ATTR_RANGE(	SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
-			SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST),
+	SDP_SERVICE_CLASS_HEADSET,
 };
 
 uint16_t hf_services[] = {
-	SDP_SERVICE_CLASS_HANDSFREE_AUDIO_GATEWAY
-};
-
-uint32_t hf_attrs[] = {
-	SDP_ATTR_RANGE(	SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
-			SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST),
+	SDP_SERVICE_CLASS_HANDSFREE_AUDIO_GATEWAY,
 };
 
 static struct {
 	const char		*name;
-	int			(*handler)(prop_dictionary_t);
+	int			(*handler)(prop_dictionary_t, sdp_data_t *);
 	const char		*description;
 	uint16_t		*services;
-	int			nservices;
-	uint32_t		*attrs;
-	int			nattrs;
+	size_t			nservices;
 } cfgtype[] = {
     {
 	"HID",		config_hid,	"Human Interface Device",
 	hid_services,	__arraycount(hid_services),
-	hid_attrs,	__arraycount(hid_attrs),
     },
     {
 	"HSET",		config_hset,	"Headset",
 	hset_services,	__arraycount(hset_services),
-	hset_attrs,	__arraycount(hset_attrs),
     },
     {
 	"HF",		config_hf,	"Handsfree",
 	hf_services,	__arraycount(hf_services),
-	hf_attrs,	__arraycount(hf_attrs),
     },
 };
 
-static sdp_attr_t	values[8];
-static uint8_t		buffer[__arraycount(values)][512];
+#define MAX_SSP		(2 + 1 * 3)	/* largest nservices is 1 */
 
 prop_dictionary_t
 cfg_query(bdaddr_t *laddr, bdaddr_t *raddr, const char *service)
 {
 	prop_dictionary_t dict;
-	void *ss;
-	int rv;
-	size_t i;
+	sdp_session_t ss;
+	uint8_t buf[MAX_SSP];
+	sdp_data_t ssp, rsp, rec;
+	size_t i, n;
+	bool rv;
 
 	dict = prop_dictionary_create();
 	if (dict == NULL)
 		return NULL;
 
-	for (i = 0; i < __arraycount(values); i++) {
-		values[i].flags = SDP_ATTR_INVALID;
-		values[i].attr = 0;
-		values[i].vlen = sizeof(buffer[i]);
-		values[i].value = buffer[i];
-	}
-
 	for (i = 0; i < __arraycount(cfgtype); i++) {
 		if (strcasecmp(service, cfgtype[i].name) == 0) {
 			ss = sdp_open(laddr, raddr);
-
-			if (ss == NULL || (errno = sdp_error(ss)) != 0)
+			if (ss == NULL)
 				return NULL;
 
-			rv = sdp_search(ss,
-				cfgtype[i].nservices, cfgtype[i].services,
-				cfgtype[i].nattrs, cfgtype[i].attrs,
-				__arraycount(values), values);
-
-			if (rv != 0) {
-				errno = sdp_error(ss);
+			/* build ServiceSearchPattern */
+			ssp.next = buf;
+			ssp.end = buf + sizeof(buf);
+
+			for (n = 0; n < cfgtype[i].nservices; n++)
+				sdp_put_uuid16(&ssp, cfgtype[i].services[n]);
+
+			ssp.end = ssp.next;
+			ssp.next = buf;
+
+			rv = sdp_service_search_attribute(ss, &ssp, NULL, &rsp);
+			if (!rv) {
+				prop_object_release(dict);
+				sdp_close(ss);
 				return NULL;
 			}
-			sdp_close(ss);
 
-			rv = (*cfgtype[i].handler)(dict);
-			if (rv != 0)
-				return NULL;
+			while (sdp_get_seq(&rsp, &rec)) {
+				errno = (*cfgtype[i].handler)(dict, &rec);
+				if (errno == 0) {
+					sdp_close(ss);
+					return dict;
+				}
+			}
 
-			return dict;
+			sdp_close(ss);
+			prop_object_release(dict);
+			return NULL;
 		}
 	}
 
@@ -205,54 +185,44 @@
  * Configure HID results
  */
 static int
-config_hid(prop_dictionary_t dict)
+config_hid(prop_dictionary_t dict, sdp_data_t *rec)
 {
 	prop_object_t obj;
 	int32_t control_psm, interrupt_psm,
-		reconnect_initiate, battery_power,
-		normally_connectable, hid_length;
+		reconnect_initiate, hid_length;
 	uint8_t *hid_descriptor;
+	sdp_data_t value;
 	const char *mode;
-	size_t i;
+	uint16_t attr;
 
 	control_psm = -1;
 	interrupt_psm = -1;
 	reconnect_initiate = -1;
-	normally_connectable = 0;
-	battery_power = 0;
 	hid_descriptor = NULL;
 	hid_length = -1;
 
-	for (i = 0; i < __arraycount(values); i++) {
-		if (values[i].flags != SDP_ATTR_OK)
-			continue;
-
-		switch (values[i].attr) {
+	while (sdp_get_attr(rec, &attr, &value)) {
+		switch (attr) {
 		case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST:
-			control_psm = parse_l2cap_psm(&values[i]);
+			control_psm = parse_pdl(&value, SDP_UUID_PROTOCOL_L2CAP);
 			break;
 
 		case SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS:
-			interrupt_psm = parse_l2cap_psm(&values[i]);
+			interrupt_psm = parse_apdl(&value, SDP_UUID_PROTOCOL_L2CAP);
 			break;
 
 		case 0x0205: /* HIDReconnectInitiate */
-			reconnect_initiate = parse_boolean(&values[i]);
+			reconnect_initiate = parse_boolean(&value);
 			break;
 
 		case 0x0206: /* HIDDescriptorList */
-			if (parse_hid_descriptor(&values[i]) == 0) {
-				hid_descriptor = values[i].value;
-				hid_length = values[i].vlen;
+			if (parse_hid_descriptor(&value)) {
+				hid_descriptor = value.next;
+				hid_length = value.end - value.next;
 			}
 			break;
 
-		case 0x0209: /* HIDBatteryPower */
-			battery_power = parse_boolean(&values[i]);
-			break;
-
-		case 0x020d: /* HIDNormallyConnectable */
-			normally_connectable = parse_boolean(&values[i]);
+		default:
 			break;
 		}
 	}
@@ -310,26 +280,27 @@
  * Configure HSET results
  */
 static int
-config_hset(prop_dictionary_t dict)
+config_hset(prop_dictionary_t dict, sdp_data_t *rec)
 {
 	prop_object_t obj;
-	uint32_t channel;
-	size_t i;
+	sdp_data_t value;
+	int32_t channel;
+	uint16_t attr;
 
 	channel = -1;
 
-	for (i = 0; i < __arraycount(values); i++) {
-		if (values[i].flags != SDP_ATTR_OK)
-			continue;
-
-		switch (values[i].attr) {
+	while (sdp_get_attr(rec, &attr, &value)) {
+		switch (attr) {
 		case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST:
-			channel = parse_rfcomm_channel(&values[i]);
+			channel = parse_pdl(&value, SDP_UUID_PROTOCOL_RFCOMM);
+			break;
+
+		default:
 			break;
 		}
 	}
 
-	if (channel == (uint32_t)-1)
+	if (channel == -1)
 		return ENOATTR;
 
 	obj = prop_string_create_cstring_nocopy("btsco");
@@ -351,26 +322,27 @@
  * Configure HF results
  */
 static int
-config_hf(prop_dictionary_t dict)
+config_hf(prop_dictionary_t dict, sdp_data_t *rec)
 {
 	prop_object_t obj;
-	uint32_t channel;
-	size_t i;
+	sdp_data_t value;
+	int32_t channel;
+	uint16_t attr;
 
 	channel = -1;
 
-	for (i = 0; i < __arraycount(values); i++) {
-		if (values[i].flags != SDP_ATTR_OK)
-			continue;
-
-		switch (values[i].attr) {
+	while (sdp_get_attr(rec, &attr, &value)) {
+		switch (attr) {
 		case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST:
-			channel = parse_rfcomm_channel(&values[i]);
+			channel = parse_pdl(&value, SDP_UUID_PROTOCOL_RFCOMM);
+			break;
+
+		default:
 			break;
 		}
 	}
 
-	if (channel == (uint32_t)-1)
+	if (channel == -1)
 		return ENOATTR;
 
 	obj = prop_string_create_cstring_nocopy("btsco");
@@ -395,381 +367,138 @@
 }
 
 /*
- * Parse [additional] protocol descriptor list for L2CAP PSM
+ * Parse HIDDescriptorList . This is a sequence of HIDDescriptors, of which
+ * each is a data element sequence containing, minimally, a ClassDescriptorType
+ * and ClassDescriptorData containing a byte array of data. Any extra elements
+ * should be ignored.
  *
- * seq8 len8				2
- *	seq8 len8			2
- *		uuid16 value16		3	L2CAP
- *		uint16 value16		3	PSM
- *	seq8 len8			2
- *		uuid16 value16		3	HID Protocol
- *				      ===
- *				       15
+ * If a ClassDescriptorType "Report" is found, set SDP data value to the
+ * ClassDescriptorData content and return true. Note that we don't need to
+ * extract the actual length as the SDP data is guaranteed valid.
  */
 
-static int32_t
-parse_l2cap_psm(sdp_attr_t *a)
+static bool
+parse_hid_descriptor(sdp_data_t *value)
 {
-	uint8_t	*ptr = a->value;
-	uint8_t	*end = a->value + a->vlen;
-	int32_t	 type, len, uuid, psm;
-
-	if (end - ptr < 15)
-		return (-1);
-
-	if (a->attr == SDP_ATTR_ADDITIONAL_PROTOCOL_DESCRIPTOR_LISTS) {
-		SDP_GET8(type, ptr);
-		switch (type) {
-		case SDP_DATA_SEQ8:
-			SDP_GET8(len, ptr);
-			break;
-
-		case SDP_DATA_SEQ16:
-			SDP_GET16(len, ptr);
-			break;
-
-		case SDP_DATA_SEQ32:
-			SDP_GET32(len, ptr);
-			break;
-
-		default:
-			return (-1);
+	sdp_data_t list, desc;
+	uintmax_t type;
+	char *str;
+	size_t len;
+
+	if (!sdp_get_seq(value, &list))
+		return false;
+
+	while (sdp_get_seq(&list, &desc)) {
+		if (sdp_get_uint(&desc, &type)
+		    && type == UDESC_REPORT
+		    && sdp_get_str(&desc, &str, &len)) {
+			value->next = (uint8_t *)str;
+			value->end = (uint8_t *)(str + len);
+			return true;
 		}
-		if (ptr + len > end)
-			return (-1);
 	}
 
-	SDP_GET8(type, ptr);
-	switch (type) {
-	case SDP_DATA_SEQ8:
-		SDP_GET8(len, ptr);
-		break;
-
-	case SDP_DATA_SEQ16:
-		SDP_GET16(len, ptr);
-		break;
-
-	case SDP_DATA_SEQ32:
-		SDP_GET32(len, ptr);
-		break;
-
-	default:
-		return (-1);
-	}
-	if (ptr + len > end)
-		return (-1);
-
-	/* Protocol */
-	SDP_GET8(type, ptr);
-	switch (type) {
-	case SDP_DATA_SEQ8:
-		SDP_GET8(len, ptr);
-		break;
-
-	case SDP_DATA_SEQ16:
-		SDP_GET16(len, ptr);
-		break;
-
-	case SDP_DATA_SEQ32:
-		SDP_GET32(len, ptr);
-		break;
-
-	default:
-		return (-1);
-	}
-	if (ptr + len > end)
-		return (-1);
-
-	/* UUID */
-	if (ptr + 3 > end)
-		return (-1);
-	SDP_GET8(type, ptr);
-	switch (type) {
-	case SDP_DATA_UUID16:
-		SDP_GET16(uuid, ptr);
-		if (uuid != SDP_UUID_PROTOCOL_L2CAP)
-			return (-1);
-		break;
+	return false;
+}
 
-	case SDP_DATA_UUID32:  /* XXX FIXME can we have 32-bit UUID */
-	case SDP_DATA_UUID128: /* XXX FIXME can we have 128-bit UUID */
-	default:
-		return (-1);
-	}
+static int32_t
+parse_boolean(sdp_data_t *value)
+{
+	bool bv;
 
-	/* PSM */
-	if (ptr + 3 > end)
-		return (-1);
-	SDP_GET8(type, ptr);
-	if (type != SDP_DATA_UINT16)
-		return (-1);
-	SDP_GET16(psm, ptr);
+	if (!sdp_get_bool(value, &bv))
+		return -1;
 
-	return (psm);
+	return bv;
 }
 
 /*
- * Parse HID descriptor string
+ * The ProtocolDescriptorList attribute describes one or
+ * more protocol stacks that may be used to gain access to
+ * the service dscribed by the service record.
+ *
+ * If the ProtocolDescriptorList describes a single stack,
+ * the attribute value takes the form of a data element
+ * sequence in which each element of the sequence is a
+ * protocol descriptor.
  *
- * seq8 len8			2
- *	seq8 len8		2
- *		uint8 value8	2
- *		str value	3
- *			      ===
- *			        9
+ *	seq
+ *	  <list>
+ *
+ * If it is possible for more than one kind of protocol
+ * stack to be used to gain access to the service, the
+ * ProtocolDescriptorList takes the form of a data element
+ * alternative where each member is a data element sequence
+ * consisting of a list of sequences describing each protocol
+ *
+ *	alt
+ *	  seq
+ *	    <list>
+ *	  seq
+ *	    <list>
+ *
+ * Each ProtocolDescriptorList is a list containing a sequence for
+ * each protocol, where each sequence contains the protocol UUUID
+ * and any protocol specific parameters.
+ *
+ *	seq
+ *	  uuid		L2CAP
+ *	  uint16	psm
+ *	seq
+ *	  uuid		RFCOMM
+ *	  uint8		channel
+ *
+ * We want to extract the ProtocolSpecificParameter#1 for the
+ * given protocol, which will be an unsigned int.
  */
-
 static int32_t
-parse_hid_descriptor(sdp_attr_t *a)
+parse_pdl_param(sdp_data_t *pdl, uint16_t proto)
 {
-	uint8_t	*ptr = a->value;
-	uint8_t	*end = a->value + a->vlen;
-	int32_t	 type, len, descriptor_type;
-
-	if (end - ptr < 9)
-		return (-1);
-
-	SDP_GET8(type, ptr);
-	switch (type) {
-	case SDP_DATA_SEQ8:
-		SDP_GET8(len, ptr);
-		break;
+	sdp_data_t seq;
+	uintmax_t param;
 
-	case SDP_DATA_SEQ16:
-		SDP_GET16(len, ptr);
-		break;
-
-	case SDP_DATA_SEQ32:
-		SDP_GET32(len, ptr);
-		break;
-
-	default:
-		return (-1);
-	}
-	if (ptr + len > end)
-		return (-1);
-
-	while (ptr < end) {
-		/* Descriptor */
-		SDP_GET8(type, ptr);
-		switch (type) {
-		case SDP_DATA_SEQ8:
-			if (ptr + 1 > end)
-				return (-1);
-			SDP_GET8(len, ptr);
-			break;
-
-		case SDP_DATA_SEQ16:
-			if (ptr + 2 > end)
-				return (-1);
-			SDP_GET16(len, ptr);
-			break;
-
-		case SDP_DATA_SEQ32:
-			if (ptr + 4 > end)
-				return (-1);
-			SDP_GET32(len, ptr);
-			break;
-
-		default:
-			return (-1);
-		}
-
-		/* Descripor type */
-		if (ptr + 1 > end)
-			return (-1);
-		SDP_GET8(type, ptr);
-		if (type != SDP_DATA_UINT8 || ptr + 1 > end)
-			return (-1);
-		SDP_GET8(descriptor_type, ptr);
-
-		/* Descriptor value */
-		if (ptr + 1 > end)
-			return (-1);
-		SDP_GET8(type, ptr);
-		switch (type) {
-		case SDP_DATA_STR8:
-			if (ptr + 1 > end)
-				return (-1);
-			SDP_GET8(len, ptr);
-			break;
-
-		case SDP_DATA_STR16:
-			if (ptr + 2 > end)
-				return (-1);
-			SDP_GET16(len, ptr);
-			break;
-
-		case SDP_DATA_STR32:
-			if (ptr + 4 > end)
-				return (-1);
-			SDP_GET32(len, ptr);
-			break;
-
-		default:
-			return (-1);
-		}
-		if (ptr + len > end)
-			return (-1);
-
-		if (descriptor_type == UDESC_REPORT && len > 0) {
-			a->value = ptr;
-			a->vlen = len;
+	while (sdp_get_seq(pdl, &seq)) {
+		if (!sdp_match_uuid16(&seq, proto))
+			continue;
 
-			return (0);
-		}
+		if (sdp_get_uint(&seq, &param))
+			return param;
 
-		ptr += len;
+		break;
 	}
 
-	return (-1);
+	return -1;
 }
 
-/*
- * Parse boolean value
- *
- * bool8 int8
- */
-
 static int32_t
-parse_boolean(sdp_attr_t *a)
+parse_pdl(sdp_data_t *value, uint16_t proto)
 {
-	if (a->vlen != 2 || a->value[0] != SDP_DATA_BOOL)
-		return (-1);
+	sdp_data_t seq;
+	int32_t param = -1;
+
+	sdp_get_alt(value, value);	/* strip any alt header */
 
-	return (a->value[1]);
+	while (param == -1 && sdp_get_seq(value, &seq))
+		param = parse_pdl_param(&seq, proto);
+
+	return param;
 }
 
 /*
- * Parse protocol descriptor list for the RFCOMM channel
- *
- * seq8 len8				2
- *	seq8 len8			2
- *		uuid16 value16		3	L2CAP
- *	seq8 len8			2
- *		uuid16 value16		3	RFCOMM
- *		uint8 value8		2	channel
- *				      ===
- *				       14
+ * Parse AdditionalProtocolDescriptorList
  */
-
 static int32_t
-parse_rfcomm_channel(sdp_attr_t *a)
+parse_apdl(sdp_data_t *value, uint16_t proto)
 {
-	uint8_t	*ptr = a->value;
-	uint8_t	*end = a->value + a->vlen;
-	int32_t	 type, len, uuid, channel;
-
-	if (end - ptr < 14)
-		return (-1);
-
-	SDP_GET8(type, ptr);
-	switch (type) {
-	case SDP_DATA_SEQ8:
-		SDP_GET8(len, ptr);
-		break;
-
-	case SDP_DATA_SEQ16:
-		SDP_GET16(len, ptr);
-		break;
-
-	case SDP_DATA_SEQ32:
-		SDP_GET32(len, ptr);
-		break;
-
-	default:
-		return (-1);
-	}
-	if (ptr + len > end)
-		return (-1);
-
-	/* Protocol */
-	SDP_GET8(type, ptr);
-	switch (type) {
-	case SDP_DATA_SEQ8:
-		SDP_GET8(len, ptr);
-		break;
-
-	case SDP_DATA_SEQ16:
-		SDP_GET16(len, ptr);
-		break;
-
-	case SDP_DATA_SEQ32:
-		SDP_GET32(len, ptr);
-		break;
-
-	default:
-		return (-1);
-	}
-	if (ptr + len > end)
-		return (-1);
-
-	/* UUID */
-	if (ptr + 3 > end)
-		return (-1);
-	SDP_GET8(type, ptr);
-	switch (type) {
-	case SDP_DATA_UUID16:
-		SDP_GET16(uuid, ptr);
-		if (uuid != SDP_UUID_PROTOCOL_L2CAP)
-			return (-1);
-		break;
-
-	case SDP_DATA_UUID32:  /* XXX FIXME can we have 32-bit UUID */
-	case SDP_DATA_UUID128: /* XXX FIXME can we have 128-bit UUID */
-	default:
-		return (-1);
-	}
-
-	/* Protocol */
-	SDP_GET8(type, ptr);
-	switch (type) {
-	case SDP_DATA_SEQ8:
-		SDP_GET8(len, ptr);
-		break;
-
-	case SDP_DATA_SEQ16:
-		SDP_GET16(len, ptr);
-		break;
-
-	case SDP_DATA_SEQ32:
-		SDP_GET32(len, ptr);
-		break;
-
-	default:
-		return (-1);
-	}
-	if (ptr + len > end)
-		return (-1);
-
-	/* UUID */
-	if (ptr + 3 > end)
-		return (-1);
-	SDP_GET8(type, ptr);
-	switch (type) {
-	case SDP_DATA_UUID16:
-		SDP_GET16(uuid, ptr);
-		if (uuid != SDP_UUID_PROTOCOL_RFCOMM)
-			return (-1);
-		break;
-
-	case SDP_DATA_UUID32:  /* XXX FIXME can we have 32-bit UUID */
-	case SDP_DATA_UUID128: /* XXX FIXME can we have 128-bit UUID */
-	default:
-		return (-1);
-	}
-
-	/* channel */
-	if (ptr + 2 > end)
-		return (-1);
+	sdp_data_t seq;
+	int32_t param = -1;
 
-	SDP_GET8(type, ptr);
-	if (type != SDP_DATA_UINT8)
-		return (-1);
+	sdp_get_seq(value, value);	/* strip seq header */
 
-	SDP_GET8(channel, ptr);
+	while (param == -1 && sdp_get_seq(value, &seq))
+		param = parse_pdl_param(&seq, proto);
 
-	return (channel);
+	return param;
 }
 
 /*

Reply via email to