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;