Module Name:    src
Committed By:   plunky
Date:           Mon Nov 22 19:56:52 UTC 2010

Modified Files:
        src/sys/netbt: hci.h hci_event.c hci_ioctl.c

Log Message:
upon device initialisation, query and cache the device features,
and cache the maximum ACL/SCO packet buffers.

provide an additional SIOCGBTFEAT ioctl to retrieve the cached
features, and add the max values to the SIOC?BTINFO results.

(btreq does not change size)


To generate a diff of this commit:
cvs rdiff -u -r1.33 -r1.34 src/sys/netbt/hci.h
cvs rdiff -u -r1.21 -r1.22 src/sys/netbt/hci_event.c
cvs rdiff -u -r1.9 -r1.10 src/sys/netbt/hci_ioctl.c

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

Modified files:

Index: src/sys/netbt/hci.h
diff -u src/sys/netbt/hci.h:1.33 src/sys/netbt/hci.h:1.34
--- src/sys/netbt/hci.h:1.33	Fri Sep 11 18:35:50 2009
+++ src/sys/netbt/hci.h	Mon Nov 22 19:56:51 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: hci.h,v 1.33 2009/09/11 18:35:50 plunky Exp $	*/
+/*	$NetBSD: hci.h,v 1.34 2010/11/22 19:56:51 plunky Exp $	*/
 
 /*-
  * Copyright (c) 2005 Iain Hibbert.
@@ -54,7 +54,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: hci.h,v 1.33 2009/09/11 18:35:50 plunky Exp $
+ * $Id: hci.h,v 1.34 2010/11/22 19:56:51 plunky Exp $
  * $FreeBSD: src/sys/netgraph/bluetooth/include/ng_hci.h,v 1.6 2005/01/07 01:45:43 imp Exp $
  */
 
@@ -2297,6 +2297,8 @@
 #define SIOCBTDUMP	 _IOW('b', 13, struct btreq) /* print debug info */
 #define SIOCSBTSCOMTU	_IOWR('b', 17, struct btreq) /* set sco_mtu value */
 
+#define SIOCGBTFEAT	_IOWR('b', 18, struct btreq) /* get unit features */
+
 struct bt_stats {
 	uint32_t	err_tx;
 	uint32_t	err_rx;
@@ -2324,7 +2326,13 @@
 		uint16_t btri_sco_mtu;		/* SCO mtu */
 		uint16_t btri_link_policy;	/* Link Policy */
 		uint16_t btri_packet_type;	/* Packet Type */
+		uint16_t btri_max_acl;		/* max ACL buffers */
+		uint16_t btri_max_sco;		/* max SCO buffers */
 	    } btri;
+	    struct {
+		uint8_t btrf_page0[HCI_FEATURES_SIZE];	/* basic */
+		uint8_t btrf_page1[HCI_FEATURES_SIZE];	/* extended */
+	    } btrf;
 	    struct bt_stats btrs;   /* unit stats */
 	} btru;
 };
@@ -2338,6 +2346,10 @@
 #define btr_sco_mtu	btru.btri.btri_sco_mtu
 #define btr_link_policy btru.btri.btri_link_policy
 #define btr_packet_type btru.btri.btri_packet_type
+#define btr_max_acl	btru.btri.btri_max_acl
+#define btr_max_sco	btru.btri.btri_max_sco
+#define btr_features0	btru.btrf.btrf_page0
+#define btr_features1	btru.btrf.btrf_page1
 #define btr_stats	btru.btrs
 
 /* hci_unit & btr_flags */
@@ -2481,14 +2493,18 @@
 	uint16_t	 hci_link_policy;	/* link policy */
 	uint16_t	 hci_lmp_mask;		/* link policy capabilities */
 
+	uint8_t		 hci_feat0[HCI_FEATURES_SIZE]; /* features mask */
+	uint8_t		 hci_feat1[HCI_FEATURES_SIZE]; /* extended */
 	uint8_t		 hci_cmds[HCI_COMMANDS_SIZE]; /* opcode bitmask */
 
 	/* flow control */
 	uint16_t	 hci_max_acl_size;	/* ACL payload mtu */
 	uint16_t	 hci_num_acl_pkts;	/* free ACL packet buffers */
+	uint16_t	 hci_max_acl_pkts;	/* max ACL packet buffers */
 	uint8_t		 hci_num_cmd_pkts;	/* free CMD packet buffers */
 	uint8_t		 hci_max_sco_size;	/* SCO payload mtu */
 	uint16_t	 hci_num_sco_pkts;	/* free SCO packet buffers */
+	uint16_t	 hci_max_sco_pkts;	/* max SCO packet buffers */
 
 	TAILQ_HEAD(,hci_link)	hci_links;	/* list of ACL/SCO links */
 	LIST_HEAD(,hci_memo)	hci_memos;	/* cached memo list */

Index: src/sys/netbt/hci_event.c
diff -u src/sys/netbt/hci_event.c:1.21 src/sys/netbt/hci_event.c:1.22
--- src/sys/netbt/hci_event.c:1.21	Sat Sep 12 18:31:46 2009
+++ src/sys/netbt/hci_event.c	Mon Nov 22 19:56:51 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: hci_event.c,v 1.21 2009/09/12 18:31:46 plunky Exp $	*/
+/*	$NetBSD: hci_event.c,v 1.22 2010/11/22 19:56:51 plunky Exp $	*/
 
 /*-
  * Copyright (c) 2005 Iain Hibbert.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hci_event.c,v 1.21 2009/09/12 18:31:46 plunky Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hci_event.c,v 1.22 2010/11/22 19:56:51 plunky Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -60,6 +60,7 @@
 static void hci_cmd_read_bdaddr(struct hci_unit *, struct mbuf *);
 static void hci_cmd_read_buffer_size(struct hci_unit *, struct mbuf *);
 static void hci_cmd_read_local_features(struct hci_unit *, struct mbuf *);
+static void hci_cmd_read_local_extended_features(struct hci_unit *, struct mbuf *);
 static void hci_cmd_read_local_ver(struct hci_unit *, struct mbuf *);
 static void hci_cmd_read_local_commands(struct hci_unit *, struct mbuf *);
 static void hci_cmd_reset(struct hci_unit *, struct mbuf *);
@@ -330,6 +331,10 @@
 		hci_cmd_read_local_features(unit, m);
 		break;
 
+	case HCI_CMD_READ_LOCAL_EXTENDED_FEATURES:
+		hci_cmd_read_local_extended_features(unit, m);
+		break;
+
 	case HCI_CMD_READ_LOCAL_VER:
 		hci_cmd_read_local_ver(unit, m);
 		break;
@@ -897,8 +902,10 @@
 
 	unit->hci_max_acl_size = le16toh(rp.max_acl_size);
 	unit->hci_num_acl_pkts = le16toh(rp.num_acl_pkts);
+	unit->hci_max_acl_pkts = le16toh(rp.num_acl_pkts);
 	unit->hci_max_sco_size = rp.max_sco_size;
 	unit->hci_num_sco_pkts = le16toh(rp.num_sco_pkts);
+	unit->hci_max_sco_pkts = le16toh(rp.num_sco_pkts);
 
 	unit->hci_flags &= ~BTF_INIT_BUFFER_SIZE;
 
@@ -923,6 +930,8 @@
 	if ((unit->hci_flags & BTF_INIT_FEATURES) == 0)
 		return;
 
+	memcpy(unit->hci_feat0, rp.features, HCI_FEATURES_SIZE);
+
 	unit->hci_lmp_mask = 0;
 
 	if (rp.features[0] & HCI_LMP_ROLE_SWITCH)
@@ -937,6 +946,9 @@
 	if (rp.features[1] & HCI_LMP_PARK_MODE)
 		unit->hci_lmp_mask |= HCI_LINK_POLICY_ENABLE_PARK_MODE;
 
+	DPRINTFN(1, "%s: lmp_mask %4.4x\n",
+		device_xname(unit->hci_dev), unit->hci_lmp_mask);
+
 	/* ACL packet mask */
 	unit->hci_acl_mask = HCI_PKT_DM1 | HCI_PKT_DH1;
 
@@ -964,6 +976,9 @@
 		unit->hci_acl_mask |= HCI_PKT_2MBPS_DH5
 				    | HCI_PKT_3MBPS_DH5;
 
+	DPRINTFN(1, "%s: acl_mask %4.4x\n",
+		device_xname(unit->hci_dev), unit->hci_acl_mask);
+
 	unit->hci_packet_type = unit->hci_acl_mask;
 
 	/* SCO packet mask */
@@ -988,13 +1003,67 @@
 
 	/* XXX what do 2MBPS/3MBPS/3SLOT eSCO mean? */
 
-	unit->hci_flags &= ~BTF_INIT_FEATURES;
+	DPRINTFN(1, "%s: sco_mask %4.4x\n",
+		device_xname(unit->hci_dev), unit->hci_sco_mask);
+
+	/* extended feature masks */
+	if (rp.features[7] & HCI_LMP_EXTENDED_FEATURES) {
+		hci_read_local_extended_features_cp cp;
+
+		cp.page = 0;
+		hci_send_cmd(unit, HCI_CMD_READ_LOCAL_EXTENDED_FEATURES,
+		    &cp, sizeof(cp));
+
+		return;
+	}
 
+	unit->hci_flags &= ~BTF_INIT_FEATURES;
 	cv_broadcast(&unit->hci_init);
+}
+
+/*
+ * process results of read_local_extended_features command_complete event
+ */
+static void
+hci_cmd_read_local_extended_features(struct hci_unit *unit, struct mbuf *m)
+{
+	hci_read_local_extended_features_rp rp;
+
+	KASSERT(m->m_pkthdr.len >= sizeof(rp));
+	m_copydata(m, 0, sizeof(rp), &rp);
+	m_adj(m, sizeof(rp));
+
+	if (rp.status > 0)
+		return;
+
+	if ((unit->hci_flags & BTF_INIT_FEATURES) == 0)
+		return;
+
+	DPRINTFN(1, "%s: page %d of %d\n", device_xname(unit->hci_dev),
+	    rp.page, rp.max_page);
+
+	switch (rp.page) {
+	case 1:
+		memcpy(unit->hci_feat1, rp.features, HCI_FEATURES_SIZE);
+		break;
 
-	DPRINTFN(1, "%s: lmp_mask %4.4x, acl_mask %4.4x, sco_mask %4.4x\n",
-		device_xname(unit->hci_dev), unit->hci_lmp_mask,
-		unit->hci_acl_mask, unit->hci_sco_mask);
+	case 0:	/* (already handled) */
+	default: 
+		break;
+	}
+
+	if (rp.page < rp.max_page) {
+		hci_read_local_extended_features_cp cp;
+
+		cp.page = rp.page + 1;
+		hci_send_cmd(unit, HCI_CMD_READ_LOCAL_EXTENDED_FEATURES,
+		    &cp, sizeof(cp));
+
+		return;
+	}
+
+	unit->hci_flags &= ~BTF_INIT_FEATURES;
+	cv_broadcast(&unit->hci_init);
 }
 
 /*

Index: src/sys/netbt/hci_ioctl.c
diff -u src/sys/netbt/hci_ioctl.c:1.9 src/sys/netbt/hci_ioctl.c:1.10
--- src/sys/netbt/hci_ioctl.c:1.9	Thu Aug 20 21:40:59 2009
+++ src/sys/netbt/hci_ioctl.c	Mon Nov 22 19:56:51 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: hci_ioctl.c,v 1.9 2009/08/20 21:40:59 plunky Exp $	*/
+/*	$NetBSD: hci_ioctl.c,v 1.10 2010/11/22 19:56:51 plunky Exp $	*/
 
 /*-
  * Copyright (c) 2005 Iain Hibbert.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hci_ioctl.c,v 1.9 2009/08/20 21:40:59 plunky Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hci_ioctl.c,v 1.10 2010/11/22 19:56:51 plunky Exp $");
 
 #include <sys/param.h>
 #include <sys/domain.h>
@@ -175,6 +175,7 @@
 	case SIOCGBTSTATS:
 	case SIOCZBTSTATS:
 	case SIOCSBTSCOMTU:
+	case SIOCGBTFEAT:
 		SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) {
 			if (strncmp(device_xname(unit->hci_dev),
 			    btr->btr_name, HCI_DEVNAME_SIZE) == 0)
@@ -216,6 +217,8 @@
 		btr->btr_num_sco = unit->hci_num_sco_pkts;
 		btr->btr_acl_mtu = unit->hci_max_acl_size;
 		btr->btr_sco_mtu = unit->hci_max_sco_size;
+		btr->btr_max_acl = unit->hci_max_acl_pkts;
+		btr->btr_max_sco = unit->hci_max_sco_pkts;
 
 		btr->btr_packet_type = unit->hci_packet_type;
 		btr->btr_link_policy = unit->hci_link_policy;
@@ -303,6 +306,13 @@
 		unit->hci_max_sco_size = btr->btr_sco_mtu;
 		break;
 
+	case SIOCGBTFEAT:	/* get unit features */
+		memset(btr, 0, sizeof(struct btreq));
+		strlcpy(btr->btr_name, device_xname(unit->hci_dev), HCI_DEVNAME_SIZE);
+		memcpy(btr->btr_features0, unit->hci_feat0, HCI_FEATURES_SIZE);
+		memcpy(btr->btr_features1, unit->hci_feat1, HCI_FEATURES_SIZE);
+		break;
+
 	default:
 		err = EFAULT;
 		break;

Reply via email to