Module Name:    src
Committed By:   plunky
Date:           Wed Apr 28 06:18:08 UTC 2010

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

Log Message:
additionally query the "PnP Information" service record to discover
any USB Forum vendor-id and product-id values and store them in the
property list if found.


To generate a diff of this commit:
cvs rdiff -u -r1.9 -r1.10 src/usr.sbin/btdevctl/print.c
cvs rdiff -u -r1.7 -r1.8 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/print.c
diff -u src/usr.sbin/btdevctl/print.c:1.9 src/usr.sbin/btdevctl/print.c:1.10
--- src/usr.sbin/btdevctl/print.c:1.9	Fri Aug 17 17:59:16 2007
+++ src/usr.sbin/btdevctl/print.c	Wed Apr 28 06:18:07 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: print.c,v 1.9 2007/08/17 17:59:16 pavel Exp $	*/
+/*	$NetBSD: print.c,v 1.10 2010/04/28 06:18:07 plunky Exp $	*/
 
 /*-
  * Copyright (c) 2006 Itronix Inc.
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: print.c,v 1.9 2007/08/17 17:59:16 pavel Exp $");
+__RCSID("$NetBSD: print.c,v 1.10 2010/04/28 06:18:07 plunky Exp $");
 
 #include <sys/types.h>
 
@@ -86,6 +86,7 @@
 cfg_print(prop_dictionary_t dict)
 {
 	prop_object_t obj;
+	uint16_t v;
 
 	obj = prop_dictionary_get(dict, BTDEVladdr);
 	if (prop_object_type(obj) != PROP_TYPE_DATA) {
@@ -103,6 +104,12 @@
 	if (prop_object_type(obj) == PROP_TYPE_STRING)
 		printf("link mode: %s\n", prop_string_cstring_nocopy(obj));
 
+	if (prop_dictionary_get_uint16(dict, BTDEVvendor, &v))
+		printf("vendor id: 0x%04x\n", v);
+
+	if (prop_dictionary_get_uint16(dict, BTDEVproduct, &v))
+		printf("product id: 0x%04x\n", v);
+
 	obj = prop_dictionary_get(dict, BTDEVtype);
 	if (prop_object_type(obj) != PROP_TYPE_STRING) {
 		printf("No device type!\n");

Index: src/usr.sbin/btdevctl/sdp.c
diff -u src/usr.sbin/btdevctl/sdp.c:1.7 src/usr.sbin/btdevctl/sdp.c:1.8
--- src/usr.sbin/btdevctl/sdp.c:1.7	Tue May 12 18:39:20 2009
+++ src/usr.sbin/btdevctl/sdp.c	Wed Apr 28 06:18:07 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: sdp.c,v 1.7 2009/05/12 18:39:20 plunky Exp $	*/
+/*	$NetBSD: sdp.c,v 1.8 2010/04/28 06:18:07 plunky Exp $	*/
 
 /*-
  * Copyright (c) 2006 Itronix Inc.
@@ -56,7 +56,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: sdp.c,v 1.7 2009/05/12 18:39:20 plunky Exp $");
+__RCSID("$NetBSD: sdp.c,v 1.8 2010/04/28 06:18:07 plunky Exp $");
 
 #include <sys/types.h>
 
@@ -84,10 +84,15 @@
 static int32_t parse_pdl(sdp_data_t *, uint16_t);
 static int32_t parse_apdl(sdp_data_t *, uint16_t);
 
+static int config_pnp(prop_dictionary_t, sdp_data_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 pnp_services[] = {
+	SDP_SERVICE_CLASS_PNP_INFORMATION,
+};
+
 uint16_t hid_services[] = {
 	SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE,
 };
@@ -123,14 +128,58 @@
 
 #define MAX_SSP		(2 + 1 * 3)	/* largest nservices is 1 */
 
+static bool
+cfg_ssa(sdp_session_t ss, uint16_t *services, size_t nservices, sdp_data_t *rsp)
+{
+	uint8_t buf[MAX_SSP];
+	sdp_data_t ssp;
+	size_t i;
+
+	ssp.next = buf;
+	ssp.end = buf + sizeof(buf);
+
+	for (i = 0; i < nservices; i++)
+		sdp_put_uuid16(&ssp, services[i]);
+
+	ssp.end = ssp.next;
+	ssp.next = buf;
+
+	return sdp_service_search_attribute(ss, &ssp, NULL, rsp);
+}
+
+static bool
+cfg_search(sdp_session_t ss, int i, prop_dictionary_t dict)
+{
+	sdp_data_t rsp, rec;
+
+	/* check PnP Information first */
+	if (!cfg_ssa(ss, pnp_services, __arraycount(pnp_services), &rsp))
+		return false;
+
+	while (sdp_get_seq(&rsp, &rec)) {
+		if (config_pnp(dict, &rec) == 0)
+			break;
+	}
+
+	/* then requested service */
+	if (!cfg_ssa(ss, cfgtype[i].services, cfgtype[i].nservices, &rsp))
+		return false;
+
+	while (sdp_get_seq(&rsp, &rec)) {
+		errno = (*cfgtype[i].handler)(dict, &rec);
+		if (errno == 0)
+			return true;
+	}
+
+	return false;
+}
+
 prop_dictionary_t
 cfg_query(bdaddr_t *laddr, bdaddr_t *raddr, const char *service)
 {
 	prop_dictionary_t dict;
 	sdp_session_t ss;
-	uint8_t buf[MAX_SSP];
-	sdp_data_t ssp, rsp, rec;
-	size_t i, n;
+	size_t i;
 	bool rv;
 
 	dict = prop_dictionary_create();
@@ -140,35 +189,15 @@
 	for (i = 0; i < __arraycount(cfgtype); i++) {
 		if (strcasecmp(service, cfgtype[i].name) == 0) {
 			ss = sdp_open(laddr, raddr);
-			if (ss == NULL)
-				return NULL;
+			if (ss != NULL) {
+				rv = cfg_search(ss, i, dict);
 
-			/* 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;
-			}
 
-			while (sdp_get_seq(&rsp, &rec)) {
-				errno = (*cfgtype[i].handler)(dict, &rec);
-				if (errno == 0) {
-					sdp_close(ss);
+				if (rv == true)
 					return dict;
-				}
 			}
 
-			sdp_close(ss);
 			prop_object_release(dict);
 			return NULL;
 		}
@@ -182,6 +211,64 @@
 }
 
 /*
+ * Configure PnP Information results
+ */
+static int
+config_pnp(prop_dictionary_t dict, sdp_data_t *rec)
+{
+	sdp_data_t value;
+	uintmax_t v;
+	uint16_t attr;
+	int vendor, product, source;
+
+	vendor = -1;
+	product = -1;
+	source = -1;
+
+	while (sdp_get_attr(rec, &attr, &value)) {
+		switch (attr) {
+		case 0x0201:	/* Vendor ID */
+			if (sdp_get_uint(&value, &v)
+			    && v <= UINT16_MAX)
+				vendor = (int)v;
+
+			break;
+
+		case 0x0202:	/* Product ID */
+			if (sdp_get_uint(&value, &v)
+			    && v <= UINT16_MAX)
+				product = (int)v;
+
+			break;
+
+		case 0x0205:	/* Vendor ID Source */
+			if (sdp_get_uint(&value, &v)
+			    && v <= UINT16_MAX)
+				source = (int)v;
+
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	if (vendor == -1 || product == -1)
+		return ENOATTR;
+
+	if (source != 0x0002)	/* "USB Implementers Forum" */
+		return ENOATTR;
+
+	if (!prop_dictionary_set_uint16(dict, BTDEVvendor, (uint16_t)vendor))
+		return errno;
+
+	if (!prop_dictionary_set_uint16(dict, BTDEVproduct, (uint16_t)product))
+		return errno;
+
+	return 0;
+}
+
+/*
  * Configure HID results
  */
 static int

Reply via email to