summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/sdmmc/sbt.c199
-rw-r--r--sys/dev/usb/ubt.c298
-rw-r--r--sys/netbt/bluetooth.h10
-rw-r--r--sys/netbt/hci.h521
-rw-r--r--sys/netbt/hci_event.c328
-rw-r--r--sys/netbt/hci_ioctl.c30
-rw-r--r--sys/netbt/hci_link.c92
-rw-r--r--sys/netbt/hci_misc.c43
-rw-r--r--sys/netbt/hci_socket.c421
-rw-r--r--sys/netbt/hci_unit.c250
-rw-r--r--sys/netbt/l2cap.h6
-rw-r--r--sys/netbt/l2cap_lower.c10
-rw-r--r--sys/netbt/l2cap_misc.c15
-rw-r--r--sys/netbt/l2cap_signal.c18
-rw-r--r--sys/netbt/rfcomm.h7
-rw-r--r--sys/netbt/rfcomm_dlc.c6
-rw-r--r--sys/netbt/rfcomm_session.c6
-rw-r--r--sys/netbt/rfcomm_socket.c16
-rw-r--r--sys/netbt/rfcomm_upper.c44
19 files changed, 1667 insertions, 653 deletions
diff --git a/sys/dev/sdmmc/sbt.c b/sys/dev/sdmmc/sbt.c
index 070d53c5ee8..6f94f164f64 100644
--- a/sys/dev/sdmmc/sbt.c
+++ b/sys/dev/sdmmc/sbt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sbt.c,v 1.9 2007/06/19 07:59:57 uwe Exp $ */
+/* $OpenBSD: sbt.c,v 1.10 2008/02/24 21:34:48 uwe Exp $ */
/*
* Copyright (c) 2007 Uwe Stuehler <uwe@openbsd.org>
@@ -53,13 +53,20 @@
struct sbt_softc {
struct device sc_dev; /* base device */
- struct hci_unit sc_unit; /* MI host controller */
struct sdmmc_function *sc_sf; /* SDIO function */
- struct proc *sc_thread; /* inquiry thread */
+ struct workq *sc_workq; /* transfer deferred packets */
+ int sc_enabled; /* HCI enabled */
int sc_dying; /* shutdown in progress */
+ int sc_busy; /* transmitting or receiving */
void *sc_ih;
u_char *sc_buf;
int sc_rxtry;
+
+ struct hci_unit *sc_unit; /* MI host controller */
+ struct bt_stats sc_stats; /* MI bluetooth stats */
+ struct ifqueue sc_cmdq;
+ struct ifqueue sc_acltxq;
+ struct ifqueue sc_scotxq;
};
int sbt_match(struct device *, void *, void *);
@@ -71,17 +78,20 @@ int sbt_read_packet(struct sbt_softc *, u_char *, size_t *);
int sbt_intr(void *);
-int sbt_enable(struct hci_unit *);
-void sbt_disable(struct hci_unit *);
-void sbt_start(struct hci_unit *, struct ifqueue *, int);
-void sbt_start_cmd(struct hci_unit *);
-void sbt_start_acl(struct hci_unit *);
-void sbt_start_sco(struct hci_unit *);
+int sbt_enable(struct device *);
+void sbt_disable(struct device *);
+void sbt_start(struct sbt_softc *, struct mbuf *, struct ifqueue *, int);
+void sbt_xmit_cmd(struct device *, struct mbuf *);
+void sbt_xmit_acl(struct device *, struct mbuf *);
+void sbt_xmit_sco(struct device *, struct mbuf *);
+void sbt_start_task(void *, void *);
+
+void sbt_stats(struct device *, struct bt_stats *, int);
#undef DPRINTF
#define SBT_DEBUG
#ifdef SBT_DEBUG
-int sbt_debug = 1;
+int sbt_debug = 0;
#define DPRINTF(s) printf s
#define DNPRINTF(n, s) do { if ((n) <= sbt_debug) printf s; } while (0)
#else
@@ -114,6 +124,16 @@ static const struct sbt_product {
SDMMC_CIS_SOCKETCOM_BTCARD }
};
+const struct hci_if sbt_hci = {
+ .enable = sbt_enable,
+ .disable = sbt_disable,
+ .output_cmd = sbt_xmit_cmd,
+ .output_acl = sbt_xmit_acl,
+ .output_sco = sbt_xmit_sco,
+ .get_stats = sbt_stats,
+ .ipl = IPL_SDMMC
+};
+
int
sbt_match(struct device *parent, void *match, void *aux)
{
@@ -155,13 +175,20 @@ sbt_attach(struct device *parent, struct device *self, void *aux)
/* It may be Type-B, but we use it only in Type-A mode. */
printf("%s: SDIO Bluetooth Type-A\n", DEVNAME(sc));
- sc->sc_buf = malloc(SBT_PKT_BUFSIZ, M_DEVBUF,
- M_NOWAIT | M_CANFAIL);
+ /* Create a shared buffer for receive and transmit. */
+ sc->sc_buf = malloc(SBT_PKT_BUFSIZ, M_DEVBUF, M_NOWAIT | M_CANFAIL);
if (sc->sc_buf == NULL) {
printf("%s: can't allocate cmd buffer\n", DEVNAME(sc));
return;
}
+ /* Create a work thread to transmit deferred packets. */
+ sc->sc_workq = workq_create(DEVNAME(sc), 1);
+ if (sc->sc_workq == NULL) {
+ printf("%s: can't allocate workq\n", DEVNAME(sc));
+ return;
+ }
+
/* Enable the HCI packet transport read interrupt. */
CSR_WRITE_1(sc, SBT_REG_IENA, ISTAT_INTRD);
@@ -176,15 +203,7 @@ sbt_attach(struct device *parent, struct device *self, void *aux)
/*
* Attach Bluetooth unit (machine-independent HCI).
*/
- sc->sc_unit.hci_softc = self;
- sc->sc_unit.hci_devname = DEVNAME(sc);
- sc->sc_unit.hci_enable = sbt_enable;
- sc->sc_unit.hci_disable = sbt_disable;
- sc->sc_unit.hci_start_cmd = sbt_start_cmd;
- sc->sc_unit.hci_start_acl = sbt_start_acl;
- sc->sc_unit.hci_start_sco = sbt_start_sco;
- sc->sc_unit.hci_ipl = IPL_TTY; /* XXX */
- hci_attach(&sc->sc_unit);
+ sc->sc_unit = hci_attach(&sbt_hci, &sc->sc_dev, 0);
}
int
@@ -193,14 +212,25 @@ sbt_detach(struct device *self, int flags)
struct sbt_softc *sc = (struct sbt_softc *)self;
sc->sc_dying = 1;
- while (sc->sc_thread != NULL)
- tsleep(sc, PWAIT, "dying", 0);
- hci_detach(&sc->sc_unit);
+ while (sc->sc_busy)
+ tsleep(&sc->sc_busy, PWAIT, "sbtdie", 0);
+
+ /* Detach HCI interface */
+ if (sc->sc_unit) {
+ hci_detach(sc->sc_unit);
+ sc->sc_unit = NULL;
+ }
if (sc->sc_ih != NULL)
sdmmc_intr_disestablish(sc->sc_ih);
+ if (sc->sc_workq != NULL)
+ workq_destroy(sc->sc_workq);
+
+ if (sc->sc_buf != NULL)
+ free(sc->sc_buf, M_DEVBUF);
+
return 0;
}
@@ -302,6 +332,7 @@ out:
* Interrupt handling
*/
+/* This function is called from the SDIO interrupt thread. */
int
sbt_intr(void *arg)
{
@@ -311,6 +342,7 @@ sbt_intr(void *arg)
size_t len;
int s;
+ /* Block further SDIO interrupts; XXX not really needed? */
s = splsdmmc();
status = CSR_READ_1(sc, SBT_REG_ISTAT);
@@ -348,27 +380,27 @@ eoi:
case HCI_ACL_DATA_PKT:
DNPRINTF(1,("%s: recv ACL packet (%d bytes)\n",
DEVNAME(sc), m->m_pkthdr.len));
- hci_input_acl(&sc->sc_unit, m);
+ hci_input_acl(sc->sc_unit, m);
break;
case HCI_SCO_DATA_PKT:
DNPRINTF(1,("%s: recv SCO packet (%d bytes)\n",
DEVNAME(sc), m->m_pkthdr.len));
- hci_input_sco(&sc->sc_unit, m);
+ hci_input_sco(sc->sc_unit, m);
break;
case HCI_EVENT_PKT:
DNPRINTF(1,("%s: recv EVENT packet (%d bytes)\n",
DEVNAME(sc), m->m_pkthdr.len));
- hci_input_event(&sc->sc_unit, m);
+ hci_input_event(sc->sc_unit, m);
break;
default:
DPRINTF(("%s: recv 0x%x packet (%d bytes)\n",
DEVNAME(sc), sc->sc_buf[0], m->m_pkthdr.len));
- sc->sc_unit.hci_stats.err_rx++;
+ sc->sc_stats.err_rx++;
m_free(m);
break;
}
} else
- sc->sc_unit.hci_stats.err_rx++;
+ sc->sc_stats.err_rx++;
splx(s);
@@ -382,22 +414,27 @@ eoi:
*/
int
-sbt_enable(struct hci_unit *unit)
+sbt_enable(struct device *self)
{
- if (unit->hci_flags & BTF_RUNNING)
+ struct sbt_softc *sc = (struct sbt_softc *)self;
+
+ if (sc->sc_enabled)
return 0;
- unit->hci_flags |= BTF_RUNNING;
- unit->hci_flags &= ~BTF_XMIT;
+ sc->sc_enabled = 1;
return 0;
}
void
-sbt_disable(struct hci_unit *unit)
+sbt_disable(struct device *self)
{
- if (!(unit->hci_flags & BTF_RUNNING))
+ struct sbt_softc *sc = (struct sbt_softc *)self;
+ int s;
+
+ if (!sc->sc_enabled)
return;
+ s = splsdmmc();
#ifdef notyet /* XXX */
if (sc->sc_rxp) {
m_freem(sc->sc_rxp);
@@ -409,22 +446,38 @@ sbt_disable(struct hci_unit *unit)
sc->sc_txp = NULL;
}
#endif
-
- unit->hci_flags &= ~BTF_RUNNING;
+ sc->sc_enabled = 0;
+ splx(s);
}
void
-sbt_start(struct hci_unit *unit, struct ifqueue *q, int xmit)
+sbt_start(struct sbt_softc *sc, struct mbuf *m, struct ifqueue *q, int xmit)
{
- struct sbt_softc *sc = (struct sbt_softc *)unit->hci_softc;
- struct mbuf *m;
+ int s;
int len;
#ifdef SBT_DEBUG
const char *what;
#endif
- if (sc->sc_dying || IF_IS_EMPTY(q))
+ s = splsdmmc();
+ if (m != NULL)
+ IF_ENQUEUE(q, m);
+
+ if (sc->sc_dying || IF_IS_EMPTY(q)) {
+ splx(s);
return;
+ }
+
+ if (curproc == NULL || sc->sc_busy) {
+ (void)workq_add_task(sc->sc_workq, 0, sbt_start_task,
+ sc, (void *)xmit);
+ splx(s);
+ return;
+ }
+
+ /* Defer additional transfers and reception of packets. */
+ sdmmc_intr_disable(sc->sc_sf);
+ sc->sc_busy++;
IF_DEQUEUE(q, m);
@@ -444,7 +497,7 @@ sbt_start(struct hci_unit *unit, struct ifqueue *q, int xmit)
what, m->m_pkthdr.len));
#endif
- unit->hci_flags |= xmit;
+ sc->sc_unit->hci_flags |= xmit;
len = m->m_pkthdr.len;
m_copydata(m, 0, len, sc->sc_buf);
@@ -453,23 +506,71 @@ sbt_start(struct hci_unit *unit, struct ifqueue *q, int xmit)
if (sbt_write_packet(sc, sc->sc_buf, len))
DPRINTF(("%s: sbt_write_packet failed\n", DEVNAME(sc)));
- unit->hci_flags &= ~xmit;
+ sc->sc_unit->hci_flags &= ~xmit;
+
+ sc->sc_busy--;
+ sdmmc_intr_enable(sc->sc_sf);
+
+ if (sc->sc_dying)
+ wakeup(&sc->sc_busy);
+
+ splx(s);
+}
+
+void
+sbt_xmit_cmd(struct device *self, struct mbuf *m)
+{
+ struct sbt_softc *sc = (struct sbt_softc *)self;
+
+ sbt_start(sc, m, &sc->sc_cmdq, BTF_XMIT_CMD);
}
void
-sbt_start_cmd(struct hci_unit *unit)
+sbt_xmit_acl(struct device *self, struct mbuf *m)
{
- sbt_start(unit, &unit->hci_cmdq, BTF_XMIT_CMD);
+ struct sbt_softc *sc = (struct sbt_softc *)self;
+
+ sbt_start(sc, m, &sc->sc_acltxq, BTF_XMIT_ACL);
}
void
-sbt_start_acl(struct hci_unit *unit)
+sbt_xmit_sco(struct device *self, struct mbuf *m)
{
- sbt_start(unit, &unit->hci_acltxq, BTF_XMIT_ACL);
+ struct sbt_softc *sc = (struct sbt_softc *)self;
+
+ sbt_start(sc, m, &sc->sc_scotxq, BTF_XMIT_SCO);
}
void
-sbt_start_sco(struct hci_unit *unit)
+sbt_start_task(void *arg1, void *arg2)
{
- sbt_start(unit, &unit->hci_scotxq, BTF_XMIT_SCO);
+ struct sbt_softc *sc = arg1;
+ int xmit = (int)arg2;
+
+ switch (xmit) {
+ case BTF_XMIT_CMD:
+ sbt_xmit_cmd(&sc->sc_dev, NULL);
+ break;
+ case BTF_XMIT_ACL:
+ sbt_xmit_acl(&sc->sc_dev, NULL);
+ break;
+ case BTF_XMIT_SCO:
+ sbt_xmit_sco(&sc->sc_dev, NULL);
+ break;
+ }
+}
+
+void
+sbt_stats(struct device *self, struct bt_stats *dest, int flush)
+{
+ struct sbt_softc *sc = (struct sbt_softc *)self;
+ int s;
+
+ s = splsdmmc();
+ memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
+
+ if (flush)
+ memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
+
+ splx(s);
}
diff --git a/sys/dev/usb/ubt.c b/sys/dev/usb/ubt.c
index d9d1058ba54..b662936eb33 100644
--- a/sys/dev/usb/ubt.c
+++ b/sys/dev/usb/ubt.c
@@ -1,4 +1,5 @@
-/* $OpenBSD: ubt.c,v 1.10 2007/11/09 18:05:51 miod Exp $ */
+/* $OpenBSD: ubt.c,v 1.11 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: ubt.c,v 1.30 2007/12/16 19:01:37 christos Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -73,8 +74,6 @@
* reference.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/device.h>
#include <sys/ioctl.h>
@@ -100,6 +99,7 @@
#undef DPRINTF
#undef DPRINTFN
+#define UBT_DEBUG 0
#ifdef UBT_DEBUG
int ubt_debug = UBT_DEBUG;
@@ -162,6 +162,7 @@ struct ubt_softc {
usbd_device_handle sc_udev;
int sc_refcnt;
int sc_dying;
+ int sc_enabled;
/* Control Interface */
usbd_interface_handle sc_iface0;
@@ -169,6 +170,8 @@ struct ubt_softc {
/* Commands (control) */
usbd_xfer_handle sc_cmd_xfer;
uint8_t *sc_cmd_buf;
+ int sc_cmd_busy; /* write active */
+ struct ifqueue sc_cmd_queue; /* output queue */
/* Events (interrupt) */
int sc_evt_addr; /* endpoint address */
@@ -187,6 +190,8 @@ struct ubt_softc {
usbd_pipe_handle sc_aclwr_pipe; /* write pipe */
usbd_xfer_handle sc_aclwr_xfer; /* write xfer */
uint8_t *sc_aclwr_buf; /* write buffer */
+ int sc_aclwr_busy; /* write active */
+ struct ifqueue sc_aclwr_queue;/* output queue */
/* ISOC interface */
usbd_interface_handle sc_iface1; /* ISOC interface */
@@ -207,9 +212,12 @@ struct ubt_softc {
int sc_scowr_size; /* frame length */
struct ubt_isoc_xfer sc_scowr[UBT_NXFERS];
struct mbuf *sc_scowr_mbuf; /* current packet */
+ int sc_scowr_busy; /* write active */
+ struct ifqueue sc_scowr_queue;/* output queue */
/* Protocol structure */
- struct hci_unit sc_unit;
+ struct hci_unit *sc_unit;
+ struct bt_stats sc_stats;
/* Successfully attached */
int sc_ok;
@@ -218,18 +226,21 @@ struct ubt_softc {
/*
* Bluetooth unit/USB callback routines
*/
-int ubt_enable(struct hci_unit *);
-void ubt_disable(struct hci_unit *);
+int ubt_enable(struct device *);
+void ubt_disable(struct device *);
-void ubt_xmit_cmd_start(struct hci_unit *);
+void ubt_xmit_cmd(struct device *, struct mbuf *);
+void ubt_xmit_cmd_start(struct ubt_softc *);
void ubt_xmit_cmd_complete(usbd_xfer_handle,
usbd_private_handle, usbd_status);
-void ubt_xmit_acl_start(struct hci_unit *);
+void ubt_xmit_acl(struct device *, struct mbuf *);
+void ubt_xmit_acl_start(struct ubt_softc *);
void ubt_xmit_acl_complete(usbd_xfer_handle,
usbd_private_handle, usbd_status);
-void ubt_xmit_sco_start(struct hci_unit *);
+void ubt_xmit_sco(struct device *, struct mbuf *);
+void ubt_xmit_sco_start(struct ubt_softc *);
void ubt_xmit_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *);
void ubt_xmit_sco_complete(usbd_xfer_handle,
usbd_private_handle, usbd_status);
@@ -245,6 +256,8 @@ void ubt_recv_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *);
void ubt_recv_sco_complete(usbd_xfer_handle,
usbd_private_handle, usbd_status);
+void ubt_stats(struct device *, struct bt_stats *, int);
+
int ubt_match(struct device *, void *, void *);
void ubt_attach(struct device *, struct device *, void *);
int ubt_detach(struct device *, int);
@@ -262,6 +275,16 @@ const struct cfattach ubt_ca = {
ubt_activate,
};
+const struct hci_if ubt_hci = {
+ .enable = ubt_enable,
+ .disable = ubt_disable,
+ .output_cmd = ubt_xmit_cmd,
+ .output_acl = ubt_xmit_acl,
+ .output_sco = ubt_xmit_sco,
+ .get_stats = ubt_stats,
+ .ipl = IPL_USB, /* IPL_SOFTUSB ??? */
+};
+
static int ubt_set_isoc_config(struct ubt_softc *);
static void ubt_abortdealloc(struct ubt_softc *);
@@ -274,7 +297,6 @@ static void ubt_abortdealloc(struct ubt_softc *);
* to the ubt_ignore list.
*/
static const struct usb_devno ubt_ignore[] = {
- { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM2033 },
{ USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM2033NF },
{ 0, 0 } /* end of list */
};
@@ -282,7 +304,6 @@ static const struct usb_devno ubt_ignore[] = {
int
ubt_match(struct device *parent, void *match, void *aux)
{
-
struct usb_attach_arg *uaa = aux;
usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
@@ -314,6 +335,12 @@ ubt_attach(struct device *parent, struct device *self, void *aux)
sc->sc_udev = uaa->device;
+#ifndef __OpenBSD__ /* ??? */
+ MBUFQ_INIT(&sc->sc_cmd_queue);
+ MBUFQ_INIT(&sc->sc_aclwr_queue);
+ MBUFQ_INIT(&sc->sc_scowr_queue);
+#endif
+
/*
* Move the device into the configured state
*/
@@ -424,22 +451,12 @@ ubt_attach(struct device *parent, struct device *self, void *aux)
}
/* Attach HCI */
- sc->sc_unit.hci_softc = self;
- sc->sc_unit.hci_devname = sc->sc_dev.dv_xname;
- sc->sc_unit.hci_enable = ubt_enable;
- sc->sc_unit.hci_disable = ubt_disable;
- sc->sc_unit.hci_start_cmd = ubt_xmit_cmd_start;
- sc->sc_unit.hci_start_acl = ubt_xmit_acl_start;
- sc->sc_unit.hci_start_sco = ubt_xmit_sco_start;
- sc->sc_unit.hci_ipl = IPL_USB; /* XXX: IPL_SOFTUSB ?? */
- hci_attach(&sc->sc_unit);
+ sc->sc_unit = hci_attach(&ubt_hci, &sc->sc_dev, 0);
usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
&sc->sc_dev);
sc->sc_ok = 1;
-
- return;
}
int
@@ -456,7 +473,10 @@ ubt_detach(struct device *self, int flags)
return 0;
/* Detach HCI interface */
- hci_detach(&sc->sc_unit);
+ if (sc->sc_unit) {
+ hci_detach(sc->sc_unit);
+ sc->sc_unit = NULL;
+ }
/*
* Abort all pipes. Causes processes waiting for transfer to wake.
@@ -488,17 +508,21 @@ ubt_activate(struct device *self, enum devact act)
struct ubt_softc *sc = (struct ubt_softc *)self;
int error = 0;
- DPRINTFN(1, "ubt_activate: sc=%p, act=%d\n", sc, act);
+ DPRINTFN(1, "sc=%p, act=%d\n", sc, act);
switch (act) {
case DVACT_ACTIVATE:
- return EOPNOTSUPP;
break;
case DVACT_DEACTIVATE:
sc->sc_dying = 1;
break;
+
+ default:
+ error = EOPNOTSUPP;
+ break;
}
+
return error;
}
@@ -691,6 +715,11 @@ ubt_abortdealloc(struct ubt_softc *sc)
m_freem(sc->sc_scowr_mbuf);
sc->sc_scowr_mbuf = NULL;
}
+
+ /* Empty mbuf queues */
+ IF_PURGE(&sc->sc_cmd_queue);
+ IF_PURGE(&sc->sc_aclwr_queue);
+ IF_PURGE(&sc->sc_scowr_queue);
}
/*******************************************************************************
@@ -700,17 +729,19 @@ ubt_abortdealloc(struct ubt_softc *sc)
* All of this will be called at the IPL_ we specified above
*/
int
-ubt_enable(struct hci_unit *unit)
+ubt_enable(struct device *self)
{
- struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
+ struct ubt_softc *sc = (struct ubt_softc *)self;
usbd_status err;
- int i, error;
+ int s, i, error;
DPRINTFN(1, "sc=%p\n", sc);
- if (unit->hci_flags & BTF_RUNNING)
+ if (sc->sc_enabled)
return 0;
+ s = splusb();
+
/* Events */
sc->sc_evt_buf = malloc(UBT_BUFSIZ_EVENT, M_USBDEV, M_NOWAIT);
if (sc->sc_evt_buf == NULL) {
@@ -742,6 +773,7 @@ ubt_enable(struct hci_unit *unit)
error = ENOMEM;
goto bad;
}
+ sc->sc_cmd_busy = 0;
/* ACL read */
err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclrd_addr,
@@ -780,6 +812,7 @@ ubt_enable(struct hci_unit *unit)
error = ENOMEM;
goto bad;
}
+ sc->sc_aclwr_busy = 0;
/* SCO read */
if (sc->sc_scord_size > 0) {
@@ -832,36 +865,58 @@ ubt_enable(struct hci_unit *unit)
sc->sc_scowr[i].softc = sc;
sc->sc_scowr[i].busy = 0;
}
+
+ sc->sc_scowr_busy = 0;
}
- unit->hci_flags &= ~BTF_XMIT;
- unit->hci_flags |= BTF_RUNNING;
+ sc->sc_enabled = 1;
+ splx(s);
return 0;
bad:
ubt_abortdealloc(sc);
+ splx(s);
return error;
}
void
-ubt_disable(struct hci_unit *unit)
+ubt_disable(struct device *self)
{
- struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
+ struct ubt_softc *sc = (struct ubt_softc *)self;
+ int s;
DPRINTFN(1, "sc=%p\n", sc);
- if ((unit->hci_flags & BTF_RUNNING) == 0)
+ if (sc->sc_enabled == 0)
return;
+ s = splusb();
ubt_abortdealloc(sc);
- unit->hci_flags &= ~BTF_RUNNING;
+ sc->sc_enabled = 0;
+ splx(s);
}
void
-ubt_xmit_cmd_start(struct hci_unit *unit)
+ubt_xmit_cmd(struct device *self, struct mbuf *m)
+{
+ struct ubt_softc *sc = (struct ubt_softc *)self;
+ int s;
+
+ KASSERT(sc->sc_enabled);
+
+ s = splusb();
+ IF_ENQUEUE(&sc->sc_cmd_queue, m);
+
+ if (sc->sc_cmd_busy == 0)
+ ubt_xmit_cmd_start(sc);
+
+ splx(s);
+}
+
+void
+ubt_xmit_cmd_start(struct ubt_softc *sc)
{
- struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
usb_device_request_t req;
usbd_status status;
struct mbuf *m;
@@ -870,16 +925,17 @@ ubt_xmit_cmd_start(struct hci_unit *unit)
if (sc->sc_dying)
return;
- if (IF_IS_EMPTY(&unit->hci_cmdq))
+ if (IF_IS_EMPTY(&sc->sc_cmd_queue))
return;
- IF_DEQUEUE(&unit->hci_cmdq, m);
+ IF_DEQUEUE(&sc->sc_cmd_queue, m);
+ KASSERT(m != NULL);
DPRINTFN(15, "%s: xmit CMD packet (%d bytes)\n",
- unit->hci_devname, m->m_pkthdr.len);
+ &sc->sc_dev, m->m_pkthdr.len);
sc->sc_refcnt++;
- unit->hci_flags |= BTF_XMIT_CMD;
+ sc->sc_cmd_busy = 1;
len = m->m_pkthdr.len - 1;
m_copydata(m, 1, len, sc->sc_cmd_buf);
@@ -891,7 +947,7 @@ ubt_xmit_cmd_start(struct hci_unit *unit)
usbd_setup_default_xfer(sc->sc_cmd_xfer,
sc->sc_udev,
- unit,
+ sc,
UBT_CMD_TIMEOUT,
&req,
sc->sc_cmd_buf,
@@ -908,7 +964,7 @@ ubt_xmit_cmd_start(struct hci_unit *unit)
usbd_errstr(status), status);
sc->sc_refcnt--;
- unit->hci_flags &= ~BTF_XMIT_CMD;
+ sc->sc_cmd_busy = 0;
}
}
@@ -916,14 +972,13 @@ void
ubt_xmit_cmd_complete(usbd_xfer_handle xfer,
usbd_private_handle h, usbd_status status)
{
- struct hci_unit *unit = h;
- struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
+ struct ubt_softc *sc = h;
uint32_t count;
DPRINTFN(15, "%s: CMD complete status=%s (%d)\n",
- unit->hci_devname, usbd_errstr(status), status);
+ sc->sc_dev.dv_xname, usbd_errstr(status), status);
- unit->hci_flags &= ~BTF_XMIT_CMD;
+ sc->sc_cmd_busy = 0;
if (--sc->sc_refcnt < 0) {
DPRINTF("sc_refcnt=%d\n", sc->sc_refcnt);
@@ -940,21 +995,37 @@ ubt_xmit_cmd_complete(usbd_xfer_handle xfer,
DPRINTF("status=%s (%d)\n",
usbd_errstr(status), status);
- unit->hci_stats.err_tx++;
+ sc->sc_stats.err_tx++;
return;
}
usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
- unit->hci_stats.cmd_tx++;
- unit->hci_stats.byte_tx += count;
+ sc->sc_stats.cmd_tx++;
+ sc->sc_stats.byte_tx += count;
- ubt_xmit_cmd_start(unit);
+ ubt_xmit_cmd_start(sc);
}
void
-ubt_xmit_acl_start(struct hci_unit *unit)
+ubt_xmit_acl(struct device *self, struct mbuf *m)
+{
+ struct ubt_softc *sc = (struct ubt_softc *)self;
+ int s;
+
+ KASSERT(sc->sc_enabled);
+
+ s = splusb();
+ IF_ENQUEUE(&sc->sc_aclwr_queue, m);
+
+ if (sc->sc_aclwr_busy == 0)
+ ubt_xmit_acl_start(sc);
+
+ splx(s);
+}
+
+void
+ubt_xmit_acl_start(struct ubt_softc *sc)
{
- struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
struct mbuf *m;
usbd_status status;
int len;
@@ -962,21 +1033,22 @@ ubt_xmit_acl_start(struct hci_unit *unit)
if (sc->sc_dying)
return;
- if (IF_IS_EMPTY(&unit->hci_acltxq))
+ if (IF_IS_EMPTY(&sc->sc_aclwr_queue))
return;
sc->sc_refcnt++;
- unit->hci_flags |= BTF_XMIT_ACL;
+ sc->sc_aclwr_busy = 1;
- IF_DEQUEUE(&unit->hci_acltxq, m);
+ IF_DEQUEUE(&sc->sc_aclwr_queue, m);
+ KASSERT(m != NULL);
DPRINTFN(15, "%s: xmit ACL packet (%d bytes)\n",
- unit->hci_devname, m->m_pkthdr.len);
+ sc->sc_dev.dv_xname, m->m_pkthdr.len);
len = m->m_pkthdr.len - 1;
if (len > UBT_BUFSIZ_ACL) {
DPRINTF("%s: truncating ACL packet (%d => %d)!\n",
- unit->hci_devname, len, UBT_BUFSIZ_ACL);
+ sc->sc_dev.dv_xname, len, UBT_BUFSIZ_ACL);
len = UBT_BUFSIZ_ACL;
}
@@ -984,12 +1056,12 @@ ubt_xmit_acl_start(struct hci_unit *unit)
m_copydata(m, 1, len, sc->sc_aclwr_buf);
m_freem(m);
- unit->hci_stats.acl_tx++;
- unit->hci_stats.byte_tx += len;
+ sc->sc_stats.acl_tx++;
+ sc->sc_stats.byte_tx += len;
usbd_setup_xfer(sc->sc_aclwr_xfer,
sc->sc_aclwr_pipe,
- unit,
+ sc,
sc->sc_aclwr_buf,
len,
USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
@@ -1005,7 +1077,7 @@ ubt_xmit_acl_start(struct hci_unit *unit)
usbd_errstr(status), status);
sc->sc_refcnt--;
- unit->hci_flags &= ~BTF_XMIT_ACL;
+ sc->sc_aclwr_busy = 0;
}
}
@@ -1013,13 +1085,12 @@ void
ubt_xmit_acl_complete(usbd_xfer_handle xfer,
usbd_private_handle h, usbd_status status)
{
- struct hci_unit *unit = h;
- struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
+ struct ubt_softc *sc = h;
DPRINTFN(15, "%s: ACL complete status=%s (%d)\n",
- unit->hci_devname, usbd_errstr(status), status);
+ sc->sc_dev.dv_xname, usbd_errstr(status), status);
- unit->hci_flags &= ~BTF_XMIT_ACL;
+ sc->sc_aclwr_busy = 0;
if (--sc->sc_refcnt < 0) {
usb_detach_wakeup(&sc->sc_dev);
@@ -1033,7 +1104,7 @@ ubt_xmit_acl_complete(usbd_xfer_handle xfer,
DPRINTF("status=%s (%d)\n",
usbd_errstr(status), status);
- unit->hci_stats.err_tx++;
+ sc->sc_stats.err_tx++;
if (status == USBD_STALLED)
usbd_clear_endpoint_stall_async(sc->sc_aclwr_pipe);
@@ -1041,13 +1112,29 @@ ubt_xmit_acl_complete(usbd_xfer_handle xfer,
return;
}
- ubt_xmit_acl_start(unit);
+ ubt_xmit_acl_start(sc);
}
void
-ubt_xmit_sco_start(struct hci_unit *unit)
+ubt_xmit_sco(struct device *self, struct mbuf *m)
+{
+ struct ubt_softc *sc = (struct ubt_softc *)self;
+ int s;
+
+ KASSERT(sc->sc_enabled);
+
+ s = splusb();
+ IF_ENQUEUE(&sc->sc_scowr_queue, m);
+
+ if (sc->sc_scowr_busy == 0)
+ ubt_xmit_sco_start(sc);
+
+ splx(s);
+}
+
+void
+ubt_xmit_sco_start(struct ubt_softc *sc)
{
- struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
int i;
if (sc->sc_dying || sc->sc_scowr_size == 0)
@@ -1084,7 +1171,7 @@ ubt_xmit_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
m = sc->sc_scowr_mbuf;
while (space > 0) {
if (m == NULL) {
- IF_DEQUEUE(&sc->sc_unit.hci_scotxq, m);
+ IF_DEQUEUE(&sc->sc_scowr_queue, m);
if (m == NULL)
break;
@@ -1103,8 +1190,10 @@ ubt_xmit_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
}
if (m->m_pkthdr.len == 0) {
- sc->sc_unit.hci_stats.sco_tx++;
- hci_complete_sco(&sc->sc_unit, m);
+ sc->sc_stats.sco_tx++;
+ if (!hci_complete_sco(sc->sc_unit, m))
+ sc->sc_stats.err_tx++;
+
m = NULL;
}
}
@@ -1116,8 +1205,8 @@ ubt_xmit_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
return;
sc->sc_refcnt++;
- sc->sc_unit.hci_flags |= BTF_XMIT_SCO;
- sc->sc_unit.hci_stats.byte_tx += len;
+ sc->sc_scowr_busy = 1;
+ sc->sc_stats.byte_tx += len;
isoc->busy = 1;
/*
@@ -1160,7 +1249,7 @@ ubt_xmit_sco_complete(usbd_xfer_handle xfer,
for (i = 0 ; ; i++) {
if (i == UBT_NXFERS) {
- sc->sc_unit.hci_flags &= ~BTF_XMIT_SCO;
+ sc->sc_scowr_busy = 0;
break;
}
@@ -1180,7 +1269,7 @@ ubt_xmit_sco_complete(usbd_xfer_handle xfer,
DPRINTF("status=%s (%d)\n",
usbd_errstr(status), status);
- sc->sc_unit.hci_stats.err_tx++;
+ sc->sc_stats.err_tx++;
if (status == USBD_STALLED)
usbd_clear_endpoint_stall_async(sc->sc_scowr_pipe);
@@ -1188,7 +1277,7 @@ ubt_xmit_sco_complete(usbd_xfer_handle xfer,
return;
}
- ubt_xmit_sco_start(&sc->sc_unit);
+ ubt_xmit_sco_start(sc);
}
/*
@@ -1236,18 +1325,16 @@ ubt_recv_event(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status)
if (count < sizeof(hci_event_hdr_t) - 1) {
DPRINTF("dumped undersized event (count = %d)\n", count);
- sc->sc_unit.hci_stats.err_rx++;
+ sc->sc_stats.err_rx++;
return;
}
- sc->sc_unit.hci_stats.evt_rx++;
- sc->sc_unit.hci_stats.byte_rx += count;
+ sc->sc_stats.evt_rx++;
+ sc->sc_stats.byte_rx += count;
m = ubt_mbufload(buf, count, HCI_EVENT_PKT);
- if (m != NULL)
- hci_input_event(&sc->sc_unit, m);
- else
- sc->sc_unit.hci_stats.err_rx++;
+ if (m == NULL || !hci_input_event(sc->sc_unit, m))
+ sc->sc_stats.err_rx++;
}
void
@@ -1319,7 +1406,7 @@ ubt_recv_acl_complete(usbd_xfer_handle xfer,
DPRINTF("status=%s (%d)\n",
usbd_errstr(status), status);
- sc->sc_unit.hci_stats.err_rx++;
+ sc->sc_stats.err_rx++;
if (status == USBD_STALLED)
usbd_clear_endpoint_stall_async(sc->sc_aclrd_pipe);
@@ -1330,16 +1417,14 @@ ubt_recv_acl_complete(usbd_xfer_handle xfer,
if (count < sizeof(hci_acldata_hdr_t) - 1) {
DPRINTF("dumped undersized packet (%d)\n", count);
- sc->sc_unit.hci_stats.err_rx++;
+ sc->sc_stats.err_rx++;
} else {
- sc->sc_unit.hci_stats.acl_rx++;
- sc->sc_unit.hci_stats.byte_rx += count;
+ sc->sc_stats.acl_rx++;
+ sc->sc_stats.byte_rx += count;
m = ubt_mbufload(buf, count, HCI_ACL_DATA_PKT);
- if (m != NULL)
- hci_input_acl(&sc->sc_unit, m);
- else
- sc->sc_unit.hci_stats.err_rx++;
+ if (m == NULL || !hci_input_acl(sc->sc_unit, m))
+ sc->sc_stats.err_rx++;
}
}
@@ -1412,7 +1497,7 @@ ubt_recv_sco_complete(usbd_xfer_handle xfer,
DPRINTF("status=%s (%d)\n",
usbd_errstr(status), status);
- sc->sc_unit.hci_stats.err_rx++;
+ sc->sc_stats.err_rx++;
if (status == USBD_STALLED) {
usbd_clear_endpoint_stall_async(sc->sc_scord_pipe);
@@ -1429,7 +1514,7 @@ ubt_recv_sco_complete(usbd_xfer_handle xfer,
DPRINTFN(15, "sc=%p, isoc=%p, count=%u\n",
sc, isoc, count);
- sc->sc_unit.hci_stats.byte_rx += count;
+ sc->sc_stats.byte_rx += count;
/*
* Extract SCO packets from ISOC frames. The way we have it,
@@ -1466,7 +1551,7 @@ ubt_recv_sco_complete(usbd_xfer_handle xfer,
printf("%s: out of memory (xfer halted)\n",
sc->sc_dev.dv_xname);
- sc->sc_unit.hci_stats.err_rx++;
+ sc->sc_stats.err_rx++;
return; /* lost sync */
}
@@ -1499,8 +1584,10 @@ ubt_recv_sco_complete(usbd_xfer_handle xfer,
if (got == want) {
m->m_pkthdr.len = m->m_len = got;
- sc->sc_unit.hci_stats.sco_rx++;
- hci_input_sco(&sc->sc_unit, m);
+ sc->sc_stats.sco_rx++;
+ if (!hci_input_sco(sc->sc_unit, m))
+ sc->sc_stats.err_rx++;
+
m = NULL;
}
}
@@ -1517,3 +1604,18 @@ ubt_recv_sco_complete(usbd_xfer_handle xfer,
restart: /* and restart */
ubt_recv_sco_start1(sc, isoc);
}
+
+void
+ubt_stats(struct device *self, struct bt_stats *dest, int flush)
+{
+ struct ubt_softc *sc = (struct ubt_softc *)self;
+ int s;
+
+ s = splusb();
+ memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
+
+ if (flush)
+ memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
+
+ splx(s);
+}
diff --git a/sys/netbt/bluetooth.h b/sys/netbt/bluetooth.h
index 796c26625aa..5c0752e16ce 100644
--- a/sys/netbt/bluetooth.h
+++ b/sys/netbt/bluetooth.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: bluetooth.h,v 1.4 2007/05/30 03:42:53 uwe Exp $ */
-/* $NetBSD: bluetooth.h,v 1.5 2007/04/21 06:15:22 plunky Exp $ */
+/* $OpenBSD: bluetooth.h,v 1.5 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: bluetooth.h,v 1.6 2007/09/17 01:23:17 rillig Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@@ -138,9 +138,9 @@ extern int bluetooth_debug;
# define UNKNOWN(value) \
printf("%s: %s = %d unknown!\n", __func__, #value, (value));
#else
-# define DPRINTF(...)
-# define DPRINTFN(...)
-# define UNKNOWN(x)
+# define DPRINTF(...) ((void)0)
+# define DPRINTFN(...) ((void)0)
+# define UNKNOWN(x) ((void)0)
#endif /* BLUETOOTH_DEBUG */
#endif /* _KERNEL */
diff --git a/sys/netbt/hci.h b/sys/netbt/hci.h
index 254ec3a4171..384dbadfea8 100644
--- a/sys/netbt/hci.h
+++ b/sys/netbt/hci.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: hci.h,v 1.9 2007/07/22 21:05:00 gwk Exp $ */
-/* $NetBSD: hci.h,v 1.10 2007/04/21 06:15:23 plunky Exp $ */
+/* $OpenBSD: hci.h,v 1.10 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: hci.h,v 1.22 2008/02/10 17:40:54 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@@ -55,14 +55,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: hci.h,v 1.9 2007/07/22 21:05:00 gwk Exp $
+ * $Id: hci.h,v 1.10 2008/02/24 21:34:48 uwe Exp $
* $FreeBSD: src/sys/netgraph/bluetooth/include/ng_hci.h,v 1.6 2005/01/07 01:45:43 imp Exp $
*/
/*
* This file contains everything that applications need to know from
* Host Controller Interface (HCI). Information taken from Bluetooth
- * Core Specifications (v1.1 and v2.0)
+ * Core Specifications (v1.1, v2.0 and v2.1)
*
* This file can be included by both kernel and userland applications.
*
@@ -77,6 +77,8 @@
#include <netbt/bluetooth.h>
+#include <sys/mutex.h>
+
/**************************************************************************
**************************************************************************
** Common defines and types (HCI)
@@ -91,13 +93,15 @@
#define HCI_FEATURES_SIZE 8 /* LMP features */
#define HCI_UNIT_NAME_SIZE 248 /* unit name size */
#define HCI_DEVNAME_SIZE 16 /* same as dv_xname */
+#define HCI_COMMANDS_SIZE 64 /* supported commands mask */
/* HCI specification */
#define HCI_SPEC_V10 0x00 /* v1.0 */
#define HCI_SPEC_V11 0x01 /* v1.1 */
#define HCI_SPEC_V12 0x02 /* v1.2 */
#define HCI_SPEC_V20 0x03 /* v2.0 */
-/* 0x02 - 0xFF - reserved for future use */
+#define HCI_SPEC_V21 0x04 /* v2.1 */
+/* 0x05 - 0xFF - reserved for future use */
/* LMP features (and page 0 of extended features) */
/* ------------------- byte 0 --------------------*/
@@ -147,16 +151,25 @@
#define HCI_LMP_3SLOT_EDR_ACL 0x80
/* ------------------- byte 5 --------------------*/
#define HCI_LMP_5SLOT_EDR_ACL 0x01
-/* reserved 0x02 */
-/* reserved 0x04 */
+#define HCI_LMP_SNIFF_SUBRATING 0x02
+#define HCI_LMP_PAUSE_ENCRYPTION 0x04
#define HCI_LMP_AFH_CAPABLE_MASTER 0x08
#define HCI_LMP_AFH_CLASS_MASTER 0x10
#define HCI_LMP_EDR_eSCO_2MBPS 0x20
#define HCI_LMP_EDR_eSCO_3MBPS 0x40
#define HCI_LMP_3SLOT_EDR_eSCO 0x80
/* ------------------- byte 6 --------------------*/
-/* reserved */
+#define HCI_LMP_EXTENDED_INQUIRY 0x01
+/* reserved 0x02 */
+/* reserved 0x04 */
+#define HCI_LMP_SIMPLE_PAIRING 0x08
+#define HCI_LMP_ENCAPSULATED_PDU 0x10
+#define HCI_LMP_ERRDATA_REPORTING 0x20
+#define HCI_LMP_NOFLUSH_PB_FLAG 0x40
+/* reserved 0x80 */
/* ------------------- byte 7 --------------------*/
+#define HCI_LMP_LINK_SUPERVISION_TO 0x01
+#define HCI_LMP_INQ_RSP_TX_POWER 0x02
#define HCI_LMP_EXTENDED_FEATURES 0x80
/* Link types */
@@ -474,8 +487,8 @@ typedef hci_status_rp hci_exit_periodic_inquiry_rp;
#define HCI_OCF_CREATE_CON 0x0005
#define HCI_CMD_CREATE_CON 0x0405
typedef struct {
- bdaddr_t bdaddr; /* destination address */
- uint16_t pkt_type; /* packet type */
+ bdaddr_t bdaddr; /* destination address */
+ uint16_t pkt_type; /* packet type */
uint8_t page_scan_rep_mode; /* page scan repetition mode */
uint8_t page_scan_mode; /* reserved - set to 0x00 */
uint16_t clock_offset; /* clock offset */
@@ -530,7 +543,7 @@ typedef struct {
#define HCI_OCF_LINK_KEY_REP 0x000b
#define HCI_CMD_LINK_KEY_REP 0x040B
typedef struct {
- bdaddr_t bdaddr; /* remote address */
+ bdaddr_t bdaddr; /* remote address */
uint8_t key[HCI_KEY_SIZE]; /* key */
} __attribute__ ((__packed__)) hci_link_key_rep_cp;
@@ -553,8 +566,8 @@ typedef struct {
#define HCI_OCF_PIN_CODE_REP 0x000d
#define HCI_CMD_PIN_CODE_REP 0x040D
typedef struct {
- bdaddr_t bdaddr; /* remote address */
- uint8_t pin_size; /* pin code length (in bytes) */
+ bdaddr_t bdaddr; /* remote address */
+ uint8_t pin_size; /* pin code length (in bytes) */
uint8_t pin[HCI_PIN_SIZE]; /* pin code */
} __attribute__ ((__packed__)) hci_pin_code_rep_cp;
@@ -592,7 +605,7 @@ typedef struct {
#define HCI_OCF_SET_CON_ENCRYPTION 0x0013
#define HCI_CMD_SET_CON_ENCRYPTION 0x0413
typedef struct {
- uint16_t con_handle; /* connection handle */
+ uint16_t con_handle; /* connection handle */
uint8_t encryption_enable; /* 0x00 - disable, 0x01 - enable */
} __attribute__ ((__packed__)) hci_set_con_encryption_cp;
/* No return parameter(s) */
@@ -614,7 +627,7 @@ typedef struct {
#define HCI_OCF_REMOTE_NAME_REQ 0x0019
#define HCI_CMD_REMOTE_NAME_REQ 0x0419
typedef struct {
- bdaddr_t bdaddr; /* remote address */
+ bdaddr_t bdaddr; /* remote address */
uint8_t page_scan_rep_mode; /* page scan repetition mode */
uint8_t page_scan_mode; /* page scan mode */
uint16_t clock_offset; /* clock offset */
@@ -624,12 +637,12 @@ typedef struct {
#define HCI_OCF_REMOTE_NAME_REQ_CANCEL 0x001a
#define HCI_CMD_REMOTE_NAME_REQ_CANCEL 0x041A
typedef struct {
- bdaddr_t bdaddr; /* remote address */
+ bdaddr_t bdaddr; /* remote address */
} __attribute__ ((__packed__)) hci_remote_name_req_cancel_cp;
typedef struct {
uint8_t status; /* 0x00 - success */
- bdaddr_t bdaddr; /* remote address */
+ bdaddr_t bdaddr; /* remote address */
} __attribute__ ((__packed__)) hci_remote_name_req_cancel_rp;
#define HCI_OCF_READ_REMOTE_FEATURES 0x001b
@@ -708,6 +721,101 @@ typedef struct {
} __attribute__ ((__packed__)) hci_reject_sco_con_req_cp;
/* No return parameter(s) */
+#define HCI_OCF_IO_CAPABILITY_REP 0x002b
+#define HCI_CMD_IO_CAPABILITY_REP 0x042a
+typedef struct {
+ bdaddr_t bdaddr; /* remote address */
+ uint8_t io_cap; /* IO capability */
+ uint8_t oob_data; /* OOB data present */
+ uint8_t auth_req; /* auth requirements */
+} __attribute__ ((__packed__)) hci_io_capability_rep_cp;
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_io_capability_rep_rp;
+
+#define HCI_OCF_USER_CONFIRM_REP 0x002c
+#define HCI_CMD_USER_CONFIRM_REP 0x042c
+typedef struct {
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_user_confirm_rep_cp;
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_user_confirm_rep_rp;
+
+#define HCI_OCF_USER_CONFIRM_NEG_REP 0x002d
+#define HCI_CMD_USER_CONFIRM_NEG_REP 0x042d
+typedef struct {
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_user_confirm_neg_rep_cp;
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_user_confirm_neg_rep_rp;
+
+#define HCI_OCF_USER_PASSKEY_REP 0x002e
+#define HCI_CMD_USER_PASSKEY_REP 0x042e
+typedef struct {
+ bdaddr_t bdaddr; /* remote address */
+ uint32_t value; /* 000000 - 999999 */
+} __attribute__ ((__packed__)) hci_user_passkey_rep_cp;
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_user_passkey_rep_rp;
+
+#define HCI_OCF_USER_PASSKEY_NEG_REP 0x002f
+#define HCI_CMD_USER_PASSKEY_NEG_REP 0x042f
+typedef struct {
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_user_passkey_neg_rep_cp;
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_user_passkey_neg_rep_rp;
+
+#define HCI_OCF_OOB_DATA_REP 0x0030
+#define HCI_CMD_OOB_DATA_REP 0x0430
+typedef struct {
+ bdaddr_t bdaddr; /* remote address */
+ uint8_t c[16]; /* pairing hash */
+ uint8_t r[16]; /* pairing randomizer */
+} __attribute__ ((__packed__)) hci_user_oob_data_rep_cp;
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_user_oob_data_rep_rp;
+
+#define HCI_OCF_OOB_DATA_NEG_REP 0x0033
+#define HCI_CMD_OOB_DATA_NEG_REP 0x0433
+typedef struct {
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_user_oob_data_neg_rep_cp;
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_user_oob_data_neg_rep_rp;
+
+#define HCI_OCF_IO_CAPABILITY_NEG_REP 0x0034
+#define HCI_CMD_IO_CAPABILITY_NEG_REP 0x0434
+typedef struct {
+ bdaddr_t bdaddr; /* remote address */
+ uint8_t reason; /* error code */
+} __attribute__ ((__packed__)) hci_io_capability_neg_rep_cp;
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_io_capability_neg_rep_rp;
+
/**************************************************************************
**************************************************************************
** OGF 0x02 Link policy commands and return parameters
@@ -763,11 +871,11 @@ typedef struct {
#define HCI_CMD_QOS_SETUP 0x0807
typedef struct {
uint16_t con_handle; /* connection handle */
- uint8_t flags; /* reserved for future use */
+ uint8_t flags; /* reserved for future use */
uint8_t service_type; /* service type */
uint32_t token_rate; /* bytes per second */
uint32_t peak_bandwidth; /* bytes per second */
- uint32_t latency; /* microseconds */
+ uint32_t latency; /* microseconds */
uint32_t delay_variation; /* microseconds */
} __attribute__ ((__packed__)) hci_qos_setup_cp;
/* No return parameter(s) */
@@ -846,6 +954,20 @@ typedef struct {
} __attribute__ ((__packed__)) hci_flow_specification_cp;
/* No return parameter(s) */
+#define HCI_OCF_SNIFF_SUBRATING 0x0011
+#define HCI_CMD_SNIFF_SUBRATING 0x0810
+typedef struct {
+ uint16_t con_handle; /* connection handle */
+ uint16_t max_latency;
+ uint16_t max_timeout; /* max remote timeout */
+ uint16_t min_timeout; /* min local timeout */
+} __attribute__ ((__packed__)) hci_sniff_subrating_cp;
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ uint16_t con_handle; /* connection handle */
+} __attribute__ ((__packed__)) hci_sniff_subrating_rp;
+
/**************************************************************************
**************************************************************************
** OGF 0x03 Host Controller and Baseband commands and return parameters
@@ -870,7 +992,7 @@ typedef hci_status_rp hci_reset_rp;
#define HCI_OCF_SET_EVENT_FILTER 0x0005
#define HCI_CMD_SET_EVENT_FILTER 0x0C05
typedef struct {
- uint8_t filter_type; /* filter type */
+ uint8_t filter_type; /* filter type */
uint8_t filter_condition_type; /* filter condition type */
/* variable size condition
uint8_t condition[]; -- conditions */
@@ -918,7 +1040,7 @@ typedef struct {
} __attribute__ ((__packed__)) hci_read_stored_link_key_cp;
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint16_t max_num_keys; /* Max. number of keys */
uint16_t num_keys_read; /* Number of stored keys */
} __attribute__ ((__packed__)) hci_read_stored_link_key_rp;
@@ -933,7 +1055,7 @@ typedef struct {
} __attribute__ ((__packed__)) hci_write_stored_link_key_cp;
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint8_t num_keys_written; /* # of keys successfully written */
} __attribute__ ((__packed__)) hci_write_stored_link_key_rp;
@@ -945,7 +1067,7 @@ typedef struct {
} __attribute__ ((__packed__)) hci_delete_stored_link_key_cp;
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint16_t num_keys_deleted; /* Number of keys deleted */
} __attribute__ ((__packed__)) hci_delete_stored_link_key_rp;
@@ -961,7 +1083,7 @@ typedef hci_status_rp hci_write_local_name_rp;
#define HCI_CMD_READ_LOCAL_NAME 0x0C14
/* No command parameter(s) */
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
char name[HCI_UNIT_NAME_SIZE]; /* unit name */
} __attribute__ ((__packed__)) hci_read_local_name_rp;
@@ -1017,7 +1139,7 @@ typedef hci_status_rp hci_write_scan_enable_rp;
#define HCI_CMD_READ_PAGE_SCAN_ACTIVITY 0x0C1B
/* No command parameter(s) */
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint16_t page_scan_interval; /* interval * 0.625 msec */
uint16_t page_scan_window; /* window * 0.625 msec */
} __attribute__ ((__packed__)) hci_read_page_scan_activity_rp;
@@ -1035,7 +1157,7 @@ typedef hci_status_rp hci_write_page_scan_activity_rp;
#define HCI_CMD_READ_INQUIRY_SCAN_ACTIVITY 0x0C1D
/* No command parameter(s) */
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint16_t inquiry_scan_interval; /* interval * 0.625 msec */
uint16_t inquiry_scan_window; /* window * 0.625 msec */
} __attribute__ ((__packed__)) hci_read_inquiry_scan_activity_rp;
@@ -1065,14 +1187,16 @@ typedef struct {
typedef hci_status_rp hci_write_auth_enable_rp;
+/* Read Encryption Mode is deprecated */
#define HCI_OCF_READ_ENCRYPTION_MODE 0x0021
#define HCI_CMD_READ_ENCRYPTION_MODE 0x0C21
/* No command parameter(s) */
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint8_t encryption_mode; /* encryption mode */
} __attribute__ ((__packed__)) hci_read_encryption_mode_rp;
+/* Write Encryption Mode is deprecated */
#define HCI_OCF_WRITE_ENCRYPTION_MODE 0x0022
#define HCI_CMD_WRITE_ENCRYPTION_MODE 0x0C22
typedef struct {
@@ -1085,7 +1209,7 @@ typedef hci_status_rp hci_write_encryption_mode_rp;
#define HCI_CMD_READ_UNIT_CLASS 0x0C23
/* No command parameter(s) */
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint8_t uclass[HCI_CLASS_SIZE]; /* unit class */
} __attribute__ ((__packed__)) hci_read_unit_class_rp;
@@ -1157,7 +1281,7 @@ typedef hci_status_rp hci_write_num_broadcast_retrans_rp;
#define HCI_CMD_READ_HOLD_MODE_ACTIVITY 0x0C2B
/* No command parameter(s) */
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint8_t hold_mode_activity; /* Hold mode activities */
} __attribute__ ((__packed__)) hci_read_hold_mode_activity_rp;
@@ -1279,14 +1403,16 @@ typedef struct {
typedef hci_status_rp hci_write_iac_lap_rp;
+/* Read Page Scan Period Mode is deprecated */
#define HCI_OCF_READ_PAGE_SCAN_PERIOD 0x003b
#define HCI_CMD_READ_PAGE_SCAN_PERIOD 0x0C3B
/* No command parameter(s) */
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint8_t page_scan_period_mode; /* Page scan period mode */
} __attribute__ ((__packed__)) hci_read_page_scan_period_rp;
+/* Write Page Scan Period Mode is deprecated */
#define HCI_OCF_WRITE_PAGE_SCAN_PERIOD 0x003c
#define HCI_CMD_WRITE_PAGE_SCAN_PERIOD 0x0C3C
typedef struct {
@@ -1300,7 +1426,7 @@ typedef hci_status_rp hci_write_page_scan_period_rp;
#define HCI_CMD_READ_PAGE_SCAN 0x0C3D
/* No command parameter(s) */
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint8_t page_scan_mode; /* Page scan mode */
} __attribute__ ((__packed__)) hci_read_page_scan_rp;
@@ -1389,6 +1515,115 @@ typedef struct {
typedef hci_status_rp hci_write_afh_assessment_rp;
+#define HCI_OCF_READ_EXTENDED_INQUIRY_RSP 0x0051
+#define HCI_CMD_READ_EXTENDED_INQUIRY_RSP 0x0C51
+/* No command parameter(s) */
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ uint8_t fec_required;
+ uint8_t response[240];
+} __attribute__ ((__packed__)) hci_read_extended_inquiry_rsp_rp;
+
+#define HCI_OCF_WRITE_EXTENDED_INQUIRY_RSP 0x0052
+#define HCI_CMD_WRITE_EXTENDED_INQUIRY_RSP 0x0C52
+typedef struct {
+ uint8_t fec_required;
+ uint8_t response[240];
+} __attribute__ ((__packed__)) hci_write_extended_inquiry_rsp_cp;
+
+typedef hci_status_rp hci_write_extended_inquiry_rsp_rp;
+
+#define HCI_OCF_REFRESH_ENCRYPTION_KEY 0x0053
+#define HCI_CMD_REFRESH_ENCRYPTION_KEY 0x0C53
+typedef struct {
+ uint16_t con_handle; /* connection handle */
+} __attribute__ ((__packed__)) hci_refresh_encryption_key_cp;
+
+typedef hci_status_rp hci_refresh_encryption_key_rp;
+
+#define HCI_OCF_READ_SIMPLE_PAIRING_MODE 0x0055
+#define HCI_CMD_READ_SIMPLE_PAIRING_MODE 0x0C55
+/* No command parameter(s) */
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ uint8_t mode; /* simple pairing mode */
+} __attribute__ ((__packed__)) hci_read_simple_pairing_mode_rp;
+
+#define HCI_OCF_WRITE_SIMPLE_PAIRING_MODE 0x0056
+#define HCI_CMD_WRITE_SIMPLE_PAIRING_MODE 0x0C56
+typedef struct {
+ uint8_t mode; /* simple pairing mode */
+} __attribute__ ((__packed__)) hci_write_simple_pairing_mode_cp;
+
+typedef hci_status_rp hci_write_simple_pairing_mode_rp;
+
+#define HCI_OCF_READ_LOCAL_OOB_DATA 0x0057
+#define HCI_CMD_READ_LOCAL_OOB_DATA 0x0C57
+/* No command parameter(s) */
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ uint8_t c[16]; /* pairing hash */
+ uint8_t r[16]; /* pairing randomizer */
+} __attribute__ ((__packed__)) hci_read_local_oob_data_rp;
+
+#define HCI_OCF_READ_INQUIRY_RSP_XMIT_POWER 0x0058
+#define HCI_CMD_READ_INQUIRY_RSP_XMIT_POWER 0x0C58
+/* No command parameter(s) */
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ int8_t power; /* TX power */
+} __attribute__ ((__packed__)) hci_read_inquiry_rsp_xmit_power_rp;
+
+#define HCI_OCF_WRITE_INQUIRY_RSP_XMIT_POWER 0x0059
+#define HCI_CMD_WRITE_INQUIRY_RSP_XMIT_POWER 0x0C59
+typedef struct {
+ int8_t power; /* TX power */
+} __attribute__ ((__packed__)) hci_write_inquiry_rsp_xmit_power_cp;
+
+typedef hci_status_rp hci_write_inquiry_rsp_xmit_power_rp;
+
+#define HCI_OCF_READ_DEFAULT_ERRDATA_REPORTING 0x005A
+#define HCI_CMD_READ_DEFAULT_ERRDATA_REPORTING 0x0C5A
+/* No command parameter(s) */
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ uint8_t reporting; /* erroneous data reporting */
+} __attribute__ ((__packed__)) hci_read_default_errdata_reporting_rp;
+
+#define HCI_OCF_WRITE_DEFAULT_ERRDATA_REPORTING 0x005B
+#define HCI_CMD_WRITE_DEFAULT_ERRDATA_REPORTING 0x0C5B
+typedef struct {
+ uint8_t reporting; /* erroneous data reporting */
+} __attribute__ ((__packed__)) hci_write_default_errdata_reporting_cp;
+
+typedef hci_status_rp hci_write_default_errdata_reporting_rp;
+
+#define HCI_OCF_ENHANCED_FLUSH 0x005F
+#define HCI_CMD_ENHANCED_FLUSH 0x0C5F
+typedef struct {
+ uint16_t con_handle; /* connection handle */
+ uint8_t packet_type;
+} __attribute__ ((__packed__)) hci_enhanced_flush_cp;
+
+/* No response parameter(s) */
+
+#define HCI_OCF_SEND_KEYPRESS_NOTIFICATION 0x0060
+#define HCI_CMD_SEND_KEYPRESS_NOTIFICATION 0x0C60
+typedef struct {
+ bdaddr_t bdaddr; /* remote address */
+ uint8_t type; /* notification type */
+} __attribute__ ((__packed__)) hci_send_keypress_notification_cp;
+
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((__packed__)) hci_send_keypress_notification_rp;
+
/**************************************************************************
**************************************************************************
** OGF 0x04 Informational commands and return parameters
@@ -1401,7 +1636,7 @@ typedef hci_status_rp hci_write_afh_assessment_rp;
#define HCI_CMD_READ_LOCAL_VER 0x1001
/* No command parameter(s) */
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint8_t hci_version; /* HCI version */
uint16_t hci_revision; /* HCI revision */
uint8_t lmp_version; /* LMP version */
@@ -1414,14 +1649,14 @@ typedef struct {
/* No command parameter(s) */
typedef struct {
uint8_t status; /* 0x00 - success */
- uint8_t commands[64]; /* opcode bitmask */
+ uint8_t commands[HCI_COMMANDS_SIZE]; /* opcode bitmask */
} __attribute__ ((__packed__)) hci_read_local_commands_rp;
#define HCI_OCF_READ_LOCAL_FEATURES 0x0003
#define HCI_CMD_READ_LOCAL_FEATURES 0x1003
/* No command parameter(s) */
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint8_t features[HCI_FEATURES_SIZE]; /* LMP features bitmsk*/
} __attribute__ ((__packed__)) hci_read_local_features_rp;
@@ -1578,6 +1813,14 @@ typedef hci_status_rp hci_write_loopback_mode_rp;
/* No command parameter(s) */
typedef hci_status_rp hci_enable_unit_under_test_rp;
+#define HCI_OCF_WRITE_SIMPLE_PAIRING_DEBUG_MODE 0x0004
+#define HCI_CMD_WRITE_SIMPLE_PAIRING_DEBUG_MODE 0x1804
+typedef struct {
+ uint8_t mode; /* simple pairing debug mode */
+} __attribute__ ((__packed__)) hci_write_simple_pairing_debug_mode_cp;
+
+typedef hci_status_rp hci_write_simple_pairing_debug_mode_rp;
+
/**************************************************************************
**************************************************************************
** OGF 0x3e Bluetooth Logo Testing
@@ -1615,28 +1858,28 @@ typedef struct {
} __attribute__ ((__packed__)) hci_inquiry_result_ep;
typedef struct {
- bdaddr_t bdaddr; /* unit address */
+ bdaddr_t bdaddr; /* unit address */
uint8_t page_scan_rep_mode; /* page scan rep. mode */
uint8_t page_scan_period_mode; /* page scan period mode */
- uint8_t page_scan_mode; /* page scan mode */
+ uint8_t page_scan_mode; /* page scan mode */
uint8_t uclass[HCI_CLASS_SIZE]; /* unit class */
- uint16_t clock_offset; /* clock offset */
+ uint16_t clock_offset; /* clock offset */
} __attribute__ ((__packed__)) hci_inquiry_response;
#define HCI_EVENT_CON_COMPL 0x03
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint16_t con_handle; /* Connection handle */
- bdaddr_t bdaddr; /* remote unit address */
+ bdaddr_t bdaddr; /* remote unit address */
uint8_t link_type; /* Link type */
uint8_t encryption_mode; /* Encryption mode */
} __attribute__ ((__packed__)) hci_con_compl_ep;
#define HCI_EVENT_CON_REQ 0x04
typedef struct {
- bdaddr_t bdaddr; /* remote unit address */
+ bdaddr_t bdaddr; /* remote unit address */
uint8_t uclass[HCI_CLASS_SIZE]; /* remote unit class */
- uint8_t link_type; /* link type */
+ uint8_t link_type; /* link type */
} __attribute__ ((__packed__)) hci_con_req_ep;
#define HCI_EVENT_DISCON_COMPL 0x05
@@ -1654,16 +1897,16 @@ typedef struct {
#define HCI_EVENT_REMOTE_NAME_REQ_COMPL 0x07
typedef struct {
- uint8_t status; /* 0x00 - success */
- bdaddr_t bdaddr; /* remote unit address */
+ uint8_t status; /* 0x00 - success */
+ bdaddr_t bdaddr; /* remote unit address */
char name[HCI_UNIT_NAME_SIZE]; /* remote unit name */
} __attribute__ ((__packed__)) hci_remote_name_req_compl_ep;
#define HCI_EVENT_ENCRYPTION_CHANGE 0x08
typedef struct {
- uint8_t status; /* 0x00 - success */
- uint16_t con_handle; /* Connection handle */
- uint8_t encryption_enable; /* 0x00 - disable */
+ uint8_t status; /* 0x00 - success */
+ uint16_t con_handle; /* Connection handle */
+ uint8_t encryption_enable; /* 0x00 - disable */
} __attribute__ ((__packed__)) hci_encryption_change_ep;
#define HCI_EVENT_CHANGE_CON_LINK_KEY_COMPL 0x09
@@ -1681,14 +1924,14 @@ typedef struct {
#define HCI_EVENT_READ_REMOTE_FEATURES_COMPL 0x0b
typedef struct {
- uint8_t status; /* 0x00 - success */
- uint16_t con_handle; /* Connection handle */
+ uint8_t status; /* 0x00 - success */
+ uint16_t con_handle; /* Connection handle */
uint8_t features[HCI_FEATURES_SIZE]; /* LMP features bitmsk*/
} __attribute__ ((__packed__)) hci_read_remote_features_compl_ep;
#define HCI_EVENT_READ_REMOTE_VER_INFO_COMPL 0x0c
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint16_t con_handle; /* Connection handle */
uint8_t lmp_version; /* LMP version */
uint16_t manufacturer; /* Hardware manufacturer name */
@@ -1697,13 +1940,13 @@ typedef struct {
#define HCI_EVENT_QOS_SETUP_COMPL 0x0d
typedef struct {
- uint8_t status; /* 0x00 - success */
+ uint8_t status; /* 0x00 - success */
uint16_t con_handle; /* connection handle */
- uint8_t flags; /* reserved for future use */
+ uint8_t flags; /* reserved for future use */
uint8_t service_type; /* service type */
uint32_t token_rate; /* bytes per second */
uint32_t peak_bandwidth; /* bytes per second */
- uint32_t latency; /* microseconds */
+ uint32_t latency; /* microseconds */
uint32_t delay_variation; /* microseconds */
} __attribute__ ((__packed__)) hci_qos_setup_compl_ep;
@@ -1774,9 +2017,9 @@ typedef struct {
#define HCI_EVENT_LINK_KEY_NOTIFICATION 0x18
typedef struct {
- bdaddr_t bdaddr; /* remote unit address */
+ bdaddr_t bdaddr; /* remote unit address */
uint8_t key[HCI_KEY_SIZE]; /* link key */
- uint8_t key_type; /* type of the key */
+ uint8_t key_type; /* type of the key */
} __attribute__ ((__packed__)) hci_link_key_notification_ep;
#define HCI_EVENT_LOOPBACK_COMMAND 0x19
@@ -1815,13 +2058,13 @@ typedef struct {
/* Page Scan Mode Change Event is deprecated */
#define HCI_EVENT_PAGE_SCAN_MODE_CHANGE 0x1f
typedef struct {
- bdaddr_t bdaddr; /* destination address */
+ bdaddr_t bdaddr; /* destination address */
uint8_t page_scan_mode; /* page scan mode */
} __attribute__ ((__packed__)) hci_page_scan_mode_change_ep;
#define HCI_EVENT_PAGE_SCAN_REP_MODE_CHANGE 0x20
typedef struct {
- bdaddr_t bdaddr; /* destination address */
+ bdaddr_t bdaddr; /* destination address */
uint8_t page_scan_rep_mode; /* page scan repetition mode */
} __attribute__ ((__packed__)) hci_page_scan_rep_mode_change_ep;
@@ -1851,7 +2094,7 @@ typedef struct {
uint8_t uclass[HCI_CLASS_SIZE]; /* unit class */
uint16_t clock_offset; /* clock offset */
int8_t rssi; /* rssi */
-} __attribute__ ((__packed__)) hci_rssi_response_ep;
+} __attribute__ ((__packed__)) hci_rssi_response;
#define HCI_EVENT_READ_REMOTE_EXTENDED_FEATURES 0x23
typedef struct {
@@ -1885,6 +2128,98 @@ typedef struct {
uint16_t txlen; /* tx packet length */
} __attribute__ ((__packed__)) hci_sco_con_changed_ep;
+#define HCI_EVENT_SNIFF_SUBRATING 0x2e
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ uint16_t con_handle; /* connection handle */
+ uint16_t tx_latency; /* max transmit latency */
+ uint16_t rx_latency; /* max receive latency */
+ uint16_t remote_timeout; /* remote timeout */
+ uint16_t local_timeout; /* local timeout */
+} __attribute__ ((__packed__)) hci_sniff_subrating_ep;
+
+#define HCI_EVENT_EXTENDED_RESULT 0x2f
+typedef struct {
+ uint8_t num_responses; /* must be 0x01 */
+ bdaddr_t bdaddr; /* remote device address */
+ uint8_t page_scan_rep_mode;
+ uint8_t reserved;
+ uint8_t uclass[HCI_CLASS_SIZE];
+ uint16_t clock_offset;
+ int8_t rssi;
+ uint8_t response[240]; /* extended inquiry response */
+} __attribute__ ((__packed__)) hci_extended_result_ep;
+
+#define HCI_EVENT_ENCRYPTION_KEY_REFRESH 0x30
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ uint16_t con_handle; /* connection handle */
+} __attribute__ ((__packed__)) hci_encryption_key_refresh_ep;
+
+#define HCI_EVENT_IO_CAPABILITY_REQ 0x31
+typedef struct {
+ bdaddr_t bdaddr; /* remote device address */
+} __attribute__ ((__packed__)) hci_io_capability_req_ep;
+
+#define HCI_EVENT_IO_CAPABILITY_RSP 0x32
+typedef struct {
+ bdaddr_t bdaddr; /* remote device address */
+ uint8_t io_capability;
+ uint8_t oob_data_present;
+ uint8_t auth_requirement;
+} __attribute__ ((__packed__)) hci_io_capability_rsp_ep;
+
+#define HCI_EVENT_USER_CONFIRM_REQ 0x33
+typedef struct {
+ bdaddr_t bdaddr; /* remote device address */
+ uint32_t value; /* 000000 - 999999 */
+} __attribute__ ((__packed__)) hci_user_confirm_req_ep;
+
+#define HCI_EVENT_USER_PASSKEY_REQ 0x34
+typedef struct {
+ bdaddr_t bdaddr; /* remote device address */
+} __attribute__ ((__packed__)) hci_user_passkey_req_ep;
+
+#define HCI_EVENT_REMOTE_OOB_DATA_REQ 0x35
+typedef struct {
+ bdaddr_t bdaddr; /* remote device address */
+} __attribute__ ((__packed__)) hci_remote_oob_data_req_ep;
+
+#define HCI_EVENT_SIMPLE_PAIRING_COMPL 0x36
+typedef struct {
+ uint8_t status; /* 0x00 - success */
+ bdaddr_t bdaddr; /* remote device address */
+} __attribute__ ((__packed__)) hci_simple_pairing_compl_ep;
+
+#define HCI_EVENT_LINK_SUPERVISION_TO_CHANGED 0x38
+typedef struct {
+ uint16_t con_handle; /* connection handle */
+ uint16_t timeout; /* link supervision timeout */
+} __attribute__ ((__packed__)) hci_link_supervision_to_changed_ep;
+
+#define HCI_EVENT_ENHANCED_FLUSH_COMPL 0x39
+typedef struct {
+ uint16_t con_handle; /* connection handle */
+} __attribute__ ((__packed__)) hci_enhanced_flush_compl_ep;
+
+#define HCI_EVENT_USER_PASSKEY_NOTIFICATION 0x3b
+typedef struct {
+ bdaddr_t bdaddr; /* remote device address */
+ uint32_t value; /* 000000 - 999999 */
+} __attribute__ ((__packed__)) hci_user_passkey_notification_ep;
+
+#define HCI_EVENT_KEYPRESS_NOTIFICATION 0x3c
+typedef struct {
+ bdaddr_t bdaddr; /* remote device address */
+ uint8_t notification_type;
+} __attribute__ ((__packed__)) hci_keypress_notification_ep;
+
+#define HCI_EVENT_REMOTE_FEATURES_NOTIFICATION 0x3d
+typedef struct {
+ bdaddr_t bdaddr; /* remote device address */
+ uint8_t features[HCI_FEATURES_SIZE]; /* LMP features bitmsk*/
+} __attribute__ ((__packed__)) hci_remote_features_notification_ep;
+
#define HCI_EVENT_BT_LOGO 0xfe
#define HCI_EVENT_VENDOR 0xff
@@ -2000,7 +2335,6 @@ struct btreq {
#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_uclass btru.btri.btri_uclass
#define btr_stats btru.btrs
/* hci_unit & btr_flags */
@@ -2013,7 +2347,13 @@ struct btreq {
#define BTF_INIT_BDADDR (1<<5) /* waiting for bdaddr */
#define BTF_INIT_BUFFER_SIZE (1<<6) /* waiting for buffer size */
#define BTF_INIT_FEATURES (1<<7) /* waiting for features */
-#define BTF_INIT (BTF_INIT_BDADDR | BTF_INIT_BUFFER_SIZE | BTF_INIT_FEATURES)
+#define BTF_POWER_UP_NOOP (1<<8) /* should wait for No-op on power up */
+#define BTF_INIT_COMMANDS (1<<9) /* waiting for supported commands */
+
+#define BTF_INIT (BTF_INIT_BDADDR \
+ | BTF_INIT_BUFFER_SIZE \
+ | BTF_INIT_FEATURES \
+ | BTF_INIT_COMMANDS)
/**************************************************************************
**************************************************************************
@@ -2057,6 +2397,7 @@ struct hci_link {
uint16_t hl_refcnt; /* reference count */
uint16_t hl_mtu; /* signalling mtu for link */
uint16_t hl_flush; /* flush timeout */
+ uint16_t hl_clock; /* remote clock offset */
TAILQ_HEAD(,l2cap_pdu) hl_txq; /* queue of outgoing PDUs */
int hl_txqlen; /* number of fragments */
@@ -2093,19 +2434,35 @@ struct hci_link {
*/
struct hci_memo {
struct timeval time; /* time of last response */
- hci_inquiry_response response; /* inquiry response */
+ bdaddr_t bdaddr;
+ uint8_t page_scan_rep_mode;
+ uint8_t page_scan_mode;
+ uint16_t clock_offset;
LIST_ENTRY(hci_memo) next;
};
/*
+ * The Bluetooth HCI interface attachment structure
+ */
+struct hci_if {
+ int (*enable)(struct device *);
+ void (*disable)(struct device *);
+ void (*output_cmd)(struct device *, struct mbuf *);
+ void (*output_acl)(struct device *, struct mbuf *);
+ void (*output_sco)(struct device *, struct mbuf *);
+ void (*get_stats)(struct device *, struct bt_stats *, int);
+ int ipl; /* for locking */
+};
+
+/*
* The Bluetooth HCI device unit structure
*/
struct hci_unit {
- struct device *hci_softc; /* ptr to device softc */
+ struct device *hci_dev; /* bthci handle */
struct device *hci_bthub; /* bthub(4) handle */
+ const struct hci_if *hci_if; /* bthci driver interface */
/* device info */
- char *hci_devname; /* device name */
bdaddr_t hci_bdaddr; /* device address */
uint16_t hci_flags; /* see BTF_ above */
@@ -2116,6 +2473,8 @@ struct hci_unit {
uint16_t hci_link_policy; /* link policy */
uint16_t hci_lmp_mask; /* link policy capabilities */
+ 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 */
@@ -2126,24 +2485,11 @@ struct hci_unit {
TAILQ_HEAD(,hci_link) hci_links; /* list of ACL/SCO links */
LIST_HEAD(,hci_memo) hci_memos; /* cached memo list */
- /*
- * h/w driver callbacks
- *
- * the device driver must supply these.
- */
- int (*hci_enable) /* enable device */
- (struct hci_unit *);
- void (*hci_disable) /* disable device */
- (struct hci_unit *);
- void (*hci_start_cmd) /* initiate cmd output routine */
- (struct hci_unit *);
- void (*hci_start_acl) /* initiate acl output routine */
- (struct hci_unit *);
- void (*hci_start_sco) /* initiate sco output routine */
- (struct hci_unit *);
- int hci_ipl; /* to block queue operations */
-
/* input queues */
+#ifndef __OpenBSD__
+ void *hci_rxint; /* receive interrupt cookie */
+#endif
+ struct mutex hci_devlock; /* device queue lock */
struct ifqueue hci_eventq; /* Event queue */
struct ifqueue hci_aclrxq; /* ACL rx queue */
struct ifqueue hci_scorxq; /* SCO rx queue */
@@ -2153,13 +2499,8 @@ struct hci_unit {
/* output queues */
struct ifqueue hci_cmdwait; /* pending commands */
- struct ifqueue hci_cmdq; /* Command queue */
- struct ifqueue hci_acltxq; /* ACL tx queue */
- struct ifqueue hci_scotxq; /* SCO tx queue */
struct ifqueue hci_scodone; /* SCO done queue */
- struct bt_stats hci_stats; /* unit statistics */
-
TAILQ_ENTRY(hci_unit) hci_next;
};
@@ -2199,6 +2540,7 @@ struct hci_link *hci_link_lookup_handle(struct hci_unit *, uint16_t);
/* hci_misc.c */
int hci_route_lookup(bdaddr_t *, bdaddr_t *);
struct hci_memo *hci_memo_find(struct hci_unit *, bdaddr_t *);
+struct hci_memo *hci_memo_new(struct hci_unit *, bdaddr_t *);
void hci_memo_free(struct hci_memo *);
/* hci_socket.c */
@@ -2208,16 +2550,16 @@ int hci_ctloutput(int, struct socket *, int, int, struct mbuf **);
void hci_mtap(struct mbuf *, struct hci_unit *);
/* hci_unit.c */
-void hci_attach(struct hci_unit *);
+struct hci_unit *hci_attach(const struct hci_if *, struct device *, uint16_t);
void hci_detach(struct hci_unit *);
int hci_enable(struct hci_unit *);
void hci_disable(struct hci_unit *);
struct hci_unit *hci_unit_lookup(bdaddr_t *);
int hci_send_cmd(struct hci_unit *, uint16_t, void *, uint8_t);
-void hci_input_event(struct hci_unit *, struct mbuf *);
-void hci_input_acl(struct hci_unit *, struct mbuf *);
-void hci_input_sco(struct hci_unit *, struct mbuf *);
-void hci_complete_sco(struct hci_unit *, struct mbuf *);
+int hci_input_event(struct hci_unit *, struct mbuf *);
+int hci_input_acl(struct hci_unit *, struct mbuf *);
+int hci_input_sco(struct hci_unit *, struct mbuf *);
+int hci_complete_sco(struct hci_unit *, struct mbuf *);
void hci_output_cmd(struct hci_unit *, struct mbuf *);
void hci_output_acl(struct hci_unit *, struct mbuf *);
void hci_output_sco(struct hci_unit *, struct mbuf *);
@@ -2229,6 +2571,7 @@ void hci_intr(void *);
#define splraiseipl(ipl) splbio() /* XXX */
#define ENOLINK ENOENT /* XXX */
#define EPASSTHROUGH ENOTTY /* XXX */
+#define device_xname(dv) (dv)->dv_xname
#endif /* _KERNEL */
diff --git a/sys/netbt/hci_event.c b/sys/netbt/hci_event.c
index b4be8a5aff4..e512521cab7 100644
--- a/sys/netbt/hci_event.c
+++ b/sys/netbt/hci_event.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: hci_event.c,v 1.6 2007/10/01 16:39:30 krw Exp $ */
-/* $NetBSD: hci_event.c,v 1.6 2007/04/21 06:15:23 plunky Exp $ */
+/* $OpenBSD: hci_event.c,v 1.7 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: hci_event.c,v 1.14 2008/02/10 17:40:54 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@@ -31,8 +31,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
@@ -45,6 +43,7 @@
#include <netbt/sco.h>
static void hci_event_inquiry_result(struct hci_unit *, struct mbuf *);
+static void hci_event_rssi_result(struct hci_unit *, struct mbuf *);
static void hci_event_command_status(struct hci_unit *, struct mbuf *);
static void hci_event_command_compl(struct hci_unit *, struct mbuf *);
static void hci_event_con_compl(struct hci_unit *, struct mbuf *);
@@ -54,13 +53,16 @@ static void hci_event_num_compl_pkts(struct hci_unit *, struct mbuf *);
static void hci_event_auth_compl(struct hci_unit *, struct mbuf *);
static void hci_event_encryption_change(struct hci_unit *, struct mbuf *);
static void hci_event_change_con_link_key_compl(struct hci_unit *, struct mbuf *);
+static void hci_event_read_clock_offset_compl(struct hci_unit *, struct mbuf *);
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_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 *);
#ifdef BLUETOOTH_DEBUG
-int bluetooth_debug = 0;
+int bluetooth_debug;
static const char *hci_eventnames[] = {
/* 0x00 */ "NULL",
@@ -98,7 +100,33 @@ static const char *hci_eventnames[] = {
/* 0x20 */ "PAGE SCAN REP MODE CHANGE",
/* 0x21 */ "FLOW SPECIFICATION COMPLETE",
/* 0x22 */ "RSSI RESULT",
-/* 0x23 */ "READ REMOTE EXT FEATURES"
+/* 0x23 */ "READ REMOTE EXT FEATURES",
+/* 0x24 */ "UNKNOWN",
+/* 0x25 */ "UNKNOWN",
+/* 0x26 */ "UNKNOWN",
+/* 0x27 */ "UNKNOWN",
+/* 0x28 */ "UNKNOWN",
+/* 0x29 */ "UNKNOWN",
+/* 0x2a */ "UNKNOWN",
+/* 0x2b */ "UNKNOWN",
+/* 0x2c */ "SCO CON COMPLETE",
+/* 0x2d */ "SCO CON CHANGED",
+/* 0x2e */ "SNIFF SUBRATING",
+/* 0x2f */ "EXTENDED INQUIRY RESULT",
+/* 0x30 */ "ENCRYPTION KEY REFRESH",
+/* 0x31 */ "IO CAPABILITY REQUEST",
+/* 0x32 */ "IO CAPABILITY RESPONSE",
+/* 0x33 */ "USER CONFIRM REQUEST",
+/* 0x34 */ "USER PASSKEY REQUEST",
+/* 0x35 */ "REMOTE OOB DATA REQUEST",
+/* 0x36 */ "SIMPLE PAIRING COMPLETE",
+/* 0x37 */ "UNKNOWN",
+/* 0x38 */ "LINK SUPERVISION TIMEOUT CHANGED",
+/* 0x39 */ "ENHANCED FLUSH COMPLETE",
+/* 0x3a */ "UNKNOWN",
+/* 0x3b */ "USER PASSKEY NOTIFICATION",
+/* 0x3c */ "KEYPRESS NOTIFICATION",
+/* 0x3d */ "REMOTE HOST FEATURES NOTIFICATION",
};
static const char *
@@ -109,12 +137,6 @@ hci_eventstr(unsigned int event)
return hci_eventnames[event];
switch (event) {
- case HCI_EVENT_SCO_CON_COMPL: /* 0x2c */
- return "SCO CON COMPLETE";
-
- case HCI_EVENT_SCO_CON_CHANGED: /* 0x2d */
- return "SCO CON CHANGED";
-
case HCI_EVENT_BT_LOGO: /* 0xfe */
return "BT_LOGO";
@@ -122,7 +144,7 @@ hci_eventstr(unsigned int event)
return "VENDOR";
}
- return "UNRECOGNISED";
+ return "UNKNOWN";
}
#endif /* BLUETOOTH_DEBUG */
@@ -132,7 +154,6 @@ hci_eventstr(unsigned int event)
* We will free the mbuf at the end, no need for any sub
* functions to handle that. We kind of assume that the
* device sends us valid events.
- * XXX "kind of"? This needs to be fixed.
*/
void
hci_event(struct mbuf *m, struct hci_unit *unit)
@@ -147,7 +168,8 @@ hci_event(struct mbuf *m, struct hci_unit *unit)
KASSERT(hdr.type == HCI_EVENT_PKT);
- DPRINTFN(1, "(%s) event %s\n", unit->hci_devname, hci_eventstr(hdr.event));
+ DPRINTFN(1, "(%s) event %s\n",
+ device_xname(unit->hci_dev), hci_eventstr(hdr.event));
switch(hdr.event) {
case HCI_EVENT_COMMAND_STATUS:
@@ -166,6 +188,10 @@ hci_event(struct mbuf *m, struct hci_unit *unit)
hci_event_inquiry_result(unit, m);
break;
+ case HCI_EVENT_RSSI_RESULT:
+ hci_event_rssi_result(unit, m);
+ break;
+
case HCI_EVENT_CON_COMPL:
hci_event_con_compl(unit, m);
break;
@@ -190,39 +216,11 @@ hci_event(struct mbuf *m, struct hci_unit *unit)
hci_event_change_con_link_key_compl(unit, m);
break;
- case HCI_EVENT_SCO_CON_COMPL:
- case HCI_EVENT_INQUIRY_COMPL:
- case HCI_EVENT_REMOTE_NAME_REQ_COMPL:
- case HCI_EVENT_MASTER_LINK_KEY_COMPL:
- case HCI_EVENT_READ_REMOTE_FEATURES_COMPL:
- case HCI_EVENT_READ_REMOTE_VER_INFO_COMPL:
- case HCI_EVENT_QOS_SETUP_COMPL:
- case HCI_EVENT_HARDWARE_ERROR:
- case HCI_EVENT_FLUSH_OCCUR:
- case HCI_EVENT_ROLE_CHANGE:
- case HCI_EVENT_MODE_CHANGE:
- case HCI_EVENT_RETURN_LINK_KEYS:
- case HCI_EVENT_PIN_CODE_REQ:
- case HCI_EVENT_LINK_KEY_REQ:
- case HCI_EVENT_LINK_KEY_NOTIFICATION:
- case HCI_EVENT_LOOPBACK_COMMAND:
- case HCI_EVENT_DATA_BUFFER_OVERFLOW:
- case HCI_EVENT_MAX_SLOT_CHANGE:
case HCI_EVENT_READ_CLOCK_OFFSET_COMPL:
- case HCI_EVENT_CON_PKT_TYPE_CHANGED:
- case HCI_EVENT_QOS_VIOLATION:
- case HCI_EVENT_PAGE_SCAN_MODE_CHANGE:
- case HCI_EVENT_PAGE_SCAN_REP_MODE_CHANGE:
- case HCI_EVENT_FLOW_SPECIFICATION_COMPL:
- case HCI_EVENT_RSSI_RESULT:
- case HCI_EVENT_READ_REMOTE_EXTENDED_FEATURES:
- case HCI_EVENT_SCO_CON_CHANGED:
- case HCI_EVENT_BT_LOGO:
- case HCI_EVENT_VENDOR:
+ hci_event_read_clock_offset_compl(unit, m);
break;
default:
- UNKNOWN(hdr.event);
break;
}
@@ -246,11 +244,16 @@ hci_event_command_status(struct hci_unit *unit, struct mbuf *m)
m_adj(m, sizeof(ep));
DPRINTFN(1, "(%s) opcode (%03x|%04x) status = 0x%x num_cmd_pkts = %d\n",
- unit->hci_devname,
+ device_xname(unit->hci_dev),
HCI_OGF(letoh16(ep.opcode)), HCI_OCF(letoh16(ep.opcode)),
ep.status,
ep.num_cmd_pkts);
+ if (ep.status > 0)
+ printf("%s: CommandStatus opcode (%03x|%04x) failed (status=0x%02x)\n",
+ device_xname(unit->hci_dev), HCI_OGF(letoh16(ep.opcode)),
+ HCI_OCF(letoh16(ep.opcode)), ep.status);
+
unit->hci_num_cmd_pkts = ep.num_cmd_pkts;
/*
@@ -261,7 +264,7 @@ hci_event_command_status(struct hci_unit *unit, struct mbuf *m)
switch (ep.status) {
case 0x12: /* Invalid HCI command parameters */
DPRINTF("(%s) Invalid HCI command parameters\n",
- unit->hci_devname);
+ device_xname(unit->hci_dev));
while ((link = hci_link_lookup_state(unit,
HCI_LINK_ACL, HCI_LINK_WAIT_CONNECT)) != NULL)
hci_link_free(link, ECONNABORTED);
@@ -288,15 +291,26 @@ static void
hci_event_command_compl(struct hci_unit *unit, struct mbuf *m)
{
hci_command_compl_ep ep;
+ hci_status_rp rp;
KASSERT(m->m_pkthdr.len >= sizeof(ep));
m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
m_adj(m, sizeof(ep));
DPRINTFN(1, "(%s) opcode (%03x|%04x) num_cmd_pkts = %d\n",
- unit->hci_devname,
- HCI_OGF(letoh16(ep.opcode)), HCI_OCF(letoh16(ep.opcode)),
- ep.num_cmd_pkts);
+ device_xname(unit->hci_dev), HCI_OGF(letoh16(ep.opcode)),
+ HCI_OCF(letoh16(ep.opcode)), ep.num_cmd_pkts);
+
+ /*
+ * I am not sure if this is completely correct, it is not guaranteed
+ * that a command_complete packet will contain the status though most
+ * do seem to.
+ */
+ m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
+ if (rp.status > 0)
+ printf("%s: CommandComplete opcode (%03x|%04x) failed (status=0x%02x)\n",
+ device_xname(unit->hci_dev), HCI_OGF(letoh16(ep.opcode)),
+ HCI_OCF(letoh16(ep.opcode)), rp.status);
unit->hci_num_cmd_pkts = ep.num_cmd_pkts;
@@ -316,6 +330,14 @@ hci_event_command_compl(struct hci_unit *unit, struct mbuf *m)
hci_cmd_read_local_features(unit, m);
break;
+ case HCI_CMD_READ_LOCAL_VER:
+ hci_cmd_read_local_ver(unit, m);
+ break;
+
+ case HCI_CMD_READ_LOCAL_COMMANDS:
+ hci_cmd_read_local_commands(unit, m);
+ break;
+
case HCI_CMD_RESET:
hci_cmd_reset(unit, m);
break;
@@ -372,9 +394,9 @@ hci_event_num_compl_pkts(struct hci_unit *unit, struct mbuf *m)
} else {
/* XXX need to issue Read_Buffer_Size or Reset? */
printf("%s: unknown handle %d! "
- "(losing track of %d packet buffer%s)\n",
- unit->hci_devname, handle,
- num, (num == 1 ? "" : "s"));
+ "(losing track of %d packet buffer%s)\n",
+ device_xname(unit->hci_dev), handle,
+ num, (num == 1 ? "" : "s"));
}
}
@@ -415,42 +437,68 @@ static void
hci_event_inquiry_result(struct hci_unit *unit, struct mbuf *m)
{
hci_inquiry_result_ep ep;
+ hci_inquiry_response ir;
struct hci_memo *memo;
- bdaddr_t bdaddr;
KASSERT(m->m_pkthdr.len >= sizeof(ep));
m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
m_adj(m, sizeof(ep));
- DPRINTFN(1, "%d response%s\n", ep.num_responses,
- (ep.num_responses == 1 ? "" : "s"));
+ DPRINTFN(1, "(%s) %d response%s\n", device_xname(unit->hci_dev),
+ ep.num_responses, (ep.num_responses == 1 ? "" : "s"));
while(ep.num_responses--) {
- m_copydata(m, 0, sizeof(bdaddr_t), (caddr_t)&bdaddr);
+ KASSERT(m->m_pkthdr.len >= sizeof(ir));
+ m_copydata(m, 0, sizeof(ir), (caddr_t)&ir);
+ m_adj(m, sizeof(ir));
DPRINTFN(1, "bdaddr %02x:%02x:%02x:%02x:%02x:%02x\n",
- bdaddr.b[5], bdaddr.b[4], bdaddr.b[3],
- bdaddr.b[2], bdaddr.b[1], bdaddr.b[0]);
-
- memo = hci_memo_find(unit, &bdaddr);
- if (memo == NULL) {
- memo = malloc(sizeof(*memo), M_BLUETOOTH,
- M_NOWAIT | M_ZERO);
- if (memo == NULL) {
- DPRINTFN(0, "out of memo memory!\n");
- break;
- }
-
- LIST_INSERT_HEAD(&unit->hci_memos, memo, next);
+ ir.bdaddr.b[5], ir.bdaddr.b[4], ir.bdaddr.b[3],
+ ir.bdaddr.b[2], ir.bdaddr.b[1], ir.bdaddr.b[0]);
+
+ memo = hci_memo_new(unit, &ir.bdaddr);
+ if (memo != NULL) {
+ memo->page_scan_rep_mode = ir.page_scan_rep_mode;
+ memo->page_scan_mode = ir.page_scan_mode;
+ memo->clock_offset = ir.clock_offset;
}
+ }
+}
- microtime(&memo->time);
- m_copydata(m, 0, sizeof(hci_inquiry_response),
- (caddr_t)&memo->response);
- m_adj(m, sizeof(hci_inquiry_response));
+/*
+ * Inquiry Result with RSSI
+ *
+ * as above but different packet when RSSI result is enabled
+ */
+static void
+hci_event_rssi_result(struct hci_unit *unit, struct mbuf *m)
+{
+ hci_rssi_result_ep ep;
+ hci_rssi_response rr;
+ struct hci_memo *memo;
+
+ KASSERT(m->m_pkthdr.len >= sizeof(ep));
+ m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
+ m_adj(m, sizeof(ep));
+
+ DPRINTFN(1, "%d response%s\n", ep.num_responses,
+ (ep.num_responses == 1 ? "" : "s"));
+
+ while(ep.num_responses--) {
+ KASSERT(m->m_pkthdr.len >= sizeof(rr));
+ m_copydata(m, 0, sizeof(rr), (caddr_t)&rr);
+ m_adj(m, sizeof(rr));
- memo->response.clock_offset =
- letoh16(memo->response.clock_offset);
+ DPRINTFN(1, "bdaddr %02x:%02x:%02x:%02x:%02x:%02x\n",
+ rr.bdaddr.b[5], rr.bdaddr.b[4], rr.bdaddr.b[3],
+ rr.bdaddr.b[2], rr.bdaddr.b[1], rr.bdaddr.b[0]);
+
+ memo = hci_memo_new(unit, &rr.bdaddr);
+ if (memo != NULL) {
+ memo->page_scan_rep_mode = rr.page_scan_rep_mode;
+ memo->page_scan_mode = 0;
+ memo->clock_offset = rr.clock_offset;
+ }
}
}
@@ -475,7 +523,7 @@ hci_event_con_compl(struct hci_unit *unit, struct mbuf *m)
DPRINTFN(1, "(%s) %s connection complete for "
"%02x:%02x:%02x:%02x:%02x:%02x status %#x\n",
- unit->hci_devname,
+ device_xname(unit->hci_dev),
(ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO"),
ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3],
ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0],
@@ -535,7 +583,13 @@ hci_event_con_compl(struct hci_unit *unit, struct mbuf *m)
&cp, sizeof(cp));
if (err)
printf("%s: Warning, could not write link policy\n",
- unit->hci_devname);
+ device_xname(unit->hci_dev));
+
+ err = hci_send_cmd(unit, HCI_CMD_READ_CLOCK_OFFSET,
+ &cp.con_handle, sizeof(cp.con_handle));
+ if (err)
+ printf("%s: Warning, could not read clock offset\n",
+ device_xname(unit->hci_dev));
err = hci_acl_setmode(link);
if (err == EINPROGRESS)
@@ -565,7 +619,8 @@ hci_event_discon_compl(struct hci_unit *unit, struct mbuf *m)
ep.con_handle = letoh16(ep.con_handle);
- DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status);
+ DPRINTFN(1, "(%s) handle #%d, status=0x%x\n",
+ device_xname(unit->hci_dev), ep.con_handle, ep.status);
link = hci_link_lookup_handle(unit, HCI_CON_HANDLE(ep.con_handle));
if (link)
@@ -590,12 +645,13 @@ hci_event_con_req(struct hci_unit *unit, struct mbuf *m)
m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
m_adj(m, sizeof(ep));
- DPRINTFN(1, "bdaddr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
+ DPRINTFN(1, "(%s) bdaddr %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
"class %2.2x%2.2x%2.2x type %s\n",
- ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3],
- ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0],
- ep.uclass[0], ep.uclass[1], ep.uclass[2],
- ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO");
+ device_xname(unit->hci_dev),
+ ep.bdaddr.b[5], ep.bdaddr.b[4], ep.bdaddr.b[3],
+ ep.bdaddr.b[2], ep.bdaddr.b[1], ep.bdaddr.b[0],
+ ep.uclass[0], ep.uclass[1], ep.uclass[2],
+ ep.link_type == HCI_LINK_ACL ? "ACL" : "SCO");
if (ep.link_type == HCI_LINK_ACL)
link = hci_acl_newconn(unit, &ep.bdaddr);
@@ -639,7 +695,8 @@ hci_event_auth_compl(struct hci_unit *unit, struct mbuf *m)
ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
- DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status);
+ DPRINTFN(1, "(%s) handle #%d, status=0x%x\n",
+ device_xname(unit->hci_dev), ep.con_handle, ep.status);
link = hci_link_lookup_handle(unit, ep.con_handle);
if (link == NULL || link->hl_type != HCI_LINK_ACL)
@@ -681,8 +738,9 @@ hci_event_encryption_change(struct hci_unit *unit, struct mbuf *m)
ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
- DPRINTFN(1, "handle #%d, status=0x%x, encryption_enable=0x%x\n",
- ep.con_handle, ep.status, ep.encryption_enable);
+ DPRINTFN(1, "(%s) handle #%d, status=0x%x, encryption_enable=0x%x\n",
+ device_xname(unit->hci_dev), ep.con_handle, ep.status,
+ ep.encryption_enable);
link = hci_link_lookup_handle(unit, ep.con_handle);
if (link == NULL || link->hl_type != HCI_LINK_ACL)
@@ -725,7 +783,8 @@ hci_event_change_con_link_key_compl(struct hci_unit *unit, struct mbuf *m)
ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
- DPRINTFN(1, "handle #%d, status=0x%x\n", ep.con_handle, ep.status);
+ DPRINTFN(1, "(%s) handle #%d, status=0x%x\n",
+ device_xname(unit->hci_dev), ep.con_handle, ep.status);
link = hci_link_lookup_handle(unit, ep.con_handle);
if (link == NULL || link->hl_type != HCI_LINK_ACL)
@@ -748,13 +807,40 @@ hci_event_change_con_link_key_compl(struct hci_unit *unit, struct mbuf *m)
}
/*
+ * Read Clock Offset Complete
+ *
+ * We keep a note of the clock offset of remote devices when a
+ * link is made, in order to facilitate reconnections to the device
+ */
+static void
+hci_event_read_clock_offset_compl(struct hci_unit *unit, struct mbuf *m)
+{
+ hci_read_clock_offset_compl_ep ep;
+ struct hci_link *link;
+
+ KASSERT(m->m_pkthdr.len >= sizeof(ep));
+ m_copydata(m, 0, sizeof(ep), (caddr_t)&ep);
+ m_adj(m, sizeof(ep));
+
+ DPRINTFN(1, "handle #%d, offset=%u, status=0x%x\n",
+ letoh16(ep.con_handle), letoh16(ep.clock_offset), ep.status);
+
+ ep.con_handle = HCI_CON_HANDLE(letoh16(ep.con_handle));
+ link = hci_link_lookup_handle(unit, ep.con_handle);
+
+ if (ep.status != 0 || link == NULL)
+ return;
+
+ link->hl_clock = ep.clock_offset;
+}
+
+/*
* process results of read_bdaddr command_complete event
*/
static void
hci_cmd_read_bdaddr(struct hci_unit *unit, struct mbuf *m)
{
hci_read_bdaddr_rp rp;
- int s;
KASSERT(m->m_pkthdr.len >= sizeof(rp));
m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
@@ -768,9 +854,7 @@ hci_cmd_read_bdaddr(struct hci_unit *unit, struct mbuf *m)
bdaddr_copy(&unit->hci_bdaddr, &rp.bdaddr);
- s = splraiseipl(unit->hci_ipl);
unit->hci_flags &= ~BTF_INIT_BDADDR;
- splx(s);
wakeup(unit);
}
@@ -782,7 +866,6 @@ static void
hci_cmd_read_buffer_size(struct hci_unit *unit, struct mbuf *m)
{
hci_read_buffer_size_rp rp;
- int s;
KASSERT(m->m_pkthdr.len >= sizeof(rp));
m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
@@ -799,9 +882,7 @@ hci_cmd_read_buffer_size(struct hci_unit *unit, struct mbuf *m)
unit->hci_max_sco_size = rp.max_sco_size;
unit->hci_num_sco_pkts = letoh16(rp.num_sco_pkts);
- s = splraiseipl(unit->hci_ipl);
unit->hci_flags &= ~BTF_INIT_BUFFER_SIZE;
- splx(s);
wakeup(unit);
}
@@ -813,7 +894,6 @@ static void
hci_cmd_read_local_features(struct hci_unit *unit, struct mbuf *m)
{
hci_read_local_features_rp rp;
- int s;
KASSERT(m->m_pkthdr.len >= sizeof(rp));
m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
@@ -890,18 +970,69 @@ hci_cmd_read_local_features(struct hci_unit *unit, struct mbuf *m)
/* XXX what do 2MBPS/3MBPS/3SLOT eSCO mean? */
- s = splraiseipl(unit->hci_ipl);
unit->hci_flags &= ~BTF_INIT_FEATURES;
- splx(s);
wakeup(unit);
DPRINTFN(1, "%s: lmp_mask %4.4x, acl_mask %4.4x, sco_mask %4.4x\n",
- unit->hci_devname, unit->hci_lmp_mask,
+ device_xname(unit->hci_dev), unit->hci_lmp_mask,
unit->hci_acl_mask, unit->hci_sco_mask);
}
/*
+ * process results of read_local_ver command_complete event
+ *
+ * reading local supported commands is only supported from 1.2 spec
+ */
+static void
+hci_cmd_read_local_ver(struct hci_unit *unit, struct mbuf *m)
+{
+ hci_read_local_ver_rp rp;
+
+ KASSERT(m->m_pkthdr.len >= sizeof(rp));
+ m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
+ m_adj(m, sizeof(rp));
+
+ if (rp.status != 0)
+ return;
+
+ if ((unit->hci_flags & BTF_INIT_COMMANDS) == 0)
+ return;
+
+ if (rp.hci_version < HCI_SPEC_V12) {
+ unit->hci_flags &= ~BTF_INIT_COMMANDS;
+ wakeup(unit);
+ return;
+ }
+
+ hci_send_cmd(unit, HCI_CMD_READ_LOCAL_COMMANDS, NULL, 0);
+}
+
+/*
+ * process results of read_local_commands command_complete event
+ */
+static void
+hci_cmd_read_local_commands(struct hci_unit *unit, struct mbuf *m)
+{
+ hci_read_local_commands_rp rp;
+
+ KASSERT(m->m_pkthdr.len >= sizeof(rp));
+ m_copydata(m, 0, sizeof(rp), (caddr_t)&rp);
+ m_adj(m, sizeof(rp));
+
+ if (rp.status != 0)
+ return;
+
+ if ((unit->hci_flags & BTF_INIT_COMMANDS) == 0)
+ return;
+
+ unit->hci_flags &= ~BTF_INIT_COMMANDS;
+ memcpy(unit->hci_cmds, rp.commands, HCI_COMMANDS_SIZE);
+
+ wakeup(unit);
+}
+
+/*
* process results of reset command_complete event
*
* This has killed all the connections, so close down anything we have left,
@@ -945,4 +1076,7 @@ hci_cmd_reset(struct hci_unit *unit, struct mbuf *m)
if (hci_send_cmd(unit, HCI_CMD_READ_LOCAL_FEATURES, NULL, 0))
return;
+
+ if (hci_send_cmd(unit, HCI_CMD_READ_LOCAL_VER, NULL, 0))
+ return;
}
diff --git a/sys/netbt/hci_ioctl.c b/sys/netbt/hci_ioctl.c
index 44a6fbff94d..4ecba4faa40 100644
--- a/sys/netbt/hci_ioctl.c
+++ b/sys/netbt/hci_ioctl.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: hci_ioctl.c,v 1.1 2007/06/01 02:46:11 uwe Exp $ */
-/* $NetBSD: hci_ioctl.c,v 1.5 2007/01/04 19:07:03 elad Exp $ */
+/* $OpenBSD: hci_ioctl.c,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: hci_ioctl.c,v 1.7 2007/11/28 20:16:12 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@@ -31,8 +31,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/domain.h>
#include <sys/ioctl.h>
@@ -63,7 +61,7 @@ hci_dump(void)
TAILQ_FOREACH(unit, &hci_unit_list, hci_next) {
printf("UNIT %s: flags 0x%4.4x, "
"num_cmd=%d, num_acl=%d, num_sco=%d\n",
- unit->hci_devname, unit->hci_flags,
+ device_xname(unit->hci_dev), unit->hci_flags,
unit->hci_num_cmd_pkts,
unit->hci_num_acl_pkts,
unit->hci_num_sco_pkts);
@@ -135,7 +133,7 @@ hci_ioctl(unsigned long cmd, void *data, struct proc *p)
{
struct btreq *btr = data;
struct hci_unit *unit;
- int s, err = 0;
+ int err = 0;
DPRINTFN(1, "cmd %#lx\n", cmd);
@@ -175,7 +173,7 @@ hci_ioctl(unsigned long cmd, void *data, struct proc *p)
case SIOCZBTSTATS:
case SIOCSBTSCOMTU:
TAILQ_FOREACH(unit, &hci_unit_list, hci_next) {
- if (strncmp(unit->hci_devname, btr->btr_name,
+ if (strncmp(device_xname(unit->hci_dev), btr->btr_name,
HCI_DEVNAME_SIZE) == 0)
break;
}
@@ -205,7 +203,7 @@ hci_ioctl(unsigned long cmd, void *data, struct proc *p)
case SIOCGBTINFO: /* get unit info */
case SIOCGBTINFOA: /* get info by address */
memset(btr, 0, sizeof(struct btreq));
- strlcpy(btr->btr_name, unit->hci_devname, HCI_DEVNAME_SIZE);
+ strlcpy(btr->btr_name, device_xname(unit->hci_dev), HCI_DEVNAME_SIZE);
bdaddr_copy(&btr->btr_bdaddr, &unit->hci_bdaddr);
btr->btr_flags = unit->hci_flags;
@@ -231,9 +229,7 @@ hci_ioctl(unsigned long cmd, void *data, struct proc *p)
unit->hci_flags &= ~BTF_UP;
}
- s = splraiseipl(unit->hci_ipl);
unit->hci_flags |= (btr->btr_flags & BTF_INIT);
- splx(s);
if ((unit->hci_flags & BTF_UP) == 0
&& (btr->btr_flags & BTF_UP)) {
@@ -241,9 +237,7 @@ hci_ioctl(unsigned long cmd, void *data, struct proc *p)
if (err)
break;
- s = splraiseipl(unit->hci_ipl);
unit->hci_flags |= BTF_UP;
- splx(s);
}
btr->btr_flags = unit->hci_flags;
@@ -270,10 +264,7 @@ hci_ioctl(unsigned long cmd, void *data, struct proc *p)
break;
case SIOCGBTSTATS: /* get unit statistics */
- s = splraiseipl(unit->hci_ipl);
- memcpy(&btr->btr_stats, &unit->hci_stats,
- sizeof(struct bt_stats));
- splx(s);
+ (*unit->hci_if->get_stats)(unit->hci_dev, &btr->btr_stats, 0);
break;
case SIOCZBTSTATS: /* get & reset unit statistics */
@@ -281,12 +272,7 @@ hci_ioctl(unsigned long cmd, void *data, struct proc *p)
if (err)
break;
- s = splraiseipl(unit->hci_ipl);
- memcpy(&btr->btr_stats, &unit->hci_stats,
- sizeof(struct bt_stats));
- memset(&unit->hci_stats, 0, sizeof(struct bt_stats));
- splx(s);
-
+ (*unit->hci_if->get_stats)(unit->hci_dev, &btr->btr_stats, 1);
break;
case SIOCSBTSCOMTU: /* set sco_mtu value for unit */
diff --git a/sys/netbt/hci_link.c b/sys/netbt/hci_link.c
index 65efaf2f120..642d87af21d 100644
--- a/sys/netbt/hci_link.c
+++ b/sys/netbt/hci_link.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: hci_link.c,v 1.6 2007/09/17 01:33:33 krw Exp $ */
-/* $NetBSD: hci_link.c,v 1.11 2007/04/21 06:15:23 plunky Exp $ */
+/* $OpenBSD: hci_link.c,v 1.7 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: hci_link.c,v 1.16 2007/11/10 23:12:22 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@@ -31,8 +31,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
@@ -96,9 +94,9 @@ hci_acl_open(struct hci_unit *unit, bdaddr_t *bdaddr)
memo = hci_memo_find(unit, bdaddr);
if (memo != NULL) {
- cp.page_scan_rep_mode = memo->response.page_scan_rep_mode;
- cp.page_scan_mode = memo->response.page_scan_mode;
- cp.clock_offset = htole16(memo->response.clock_offset);
+ cp.page_scan_rep_mode = memo->page_scan_rep_mode;
+ cp.page_scan_mode = memo->page_scan_mode;
+ cp.clock_offset = memo->clock_offset;
}
if (unit->hci_link_policy & HCI_LINK_POLICY_ENABLE_ROLE_SWITCH)
@@ -257,8 +255,8 @@ hci_acl_setmode(struct hci_link *link)
&& !(link->hl_flags & HCI_LINK_AUTH)) {
hci_auth_req_cp cp;
- DPRINTF("requesting auth for handle #%d\n",
- link->hl_handle);
+ DPRINTF("(%s) requesting auth for handle #%d\n",
+ device_xname(link->hl_unit->hci_dev), link->hl_handle);
link->hl_state = HCI_LINK_WAIT_AUTH;
cp.con_handle = htole16(link->hl_handle);
@@ -274,8 +272,8 @@ hci_acl_setmode(struct hci_link *link)
/* XXX we should check features for encryption capability */
- DPRINTF("requesting encryption for handle #%d\n",
- link->hl_handle);
+ DPRINTF("(%s) requesting encryption for handle #%d\n",
+ device_xname(link->hl_unit->hci_dev), link->hl_handle);
link->hl_state = HCI_LINK_WAIT_ENCRYPT;
cp.con_handle = htole16(link->hl_handle);
@@ -293,8 +291,8 @@ hci_acl_setmode(struct hci_link *link)
/* always change link key for SECURE requests */
link->hl_flags &= ~HCI_LINK_SECURE;
- DPRINTF("changing link key for handle #%d\n",
- link->hl_handle);
+ DPRINTF("(%s) changing link key for handle #%d\n",
+ device_xname(link->hl_unit->hci_dev), link->hl_handle);
link->hl_state = HCI_LINK_WAIT_SECURE;
cp.con_handle = htole16(link->hl_handle);
@@ -320,11 +318,11 @@ hci_acl_linkmode(struct hci_link *link)
struct l2cap_channel *chan, *next;
int err, mode = 0;
- DPRINTF("handle #%d, auth %s, encrypt %s, secure %s\n",
- link->hl_handle,
- (link->hl_flags & HCI_LINK_AUTH ? "on" : "off"),
- (link->hl_flags & HCI_LINK_ENCRYPT ? "on" : "off"),
- (link->hl_flags & HCI_LINK_SECURE ? "on" : "off"));
+ DPRINTF("(%s) handle #%d, auth %s, encrypt %s, secure %s\n",
+ device_xname(link->hl_unit->hci_dev), link->hl_handle,
+ (link->hl_flags & HCI_LINK_AUTH ? "on" : "off"),
+ (link->hl_flags & HCI_LINK_ENCRYPT ? "on" : "off"),
+ (link->hl_flags & HCI_LINK_SECURE ? "on" : "off"));
if (link->hl_flags & HCI_LINK_AUTH)
mode |= L2CAP_LM_AUTH;
@@ -424,13 +422,15 @@ hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
#ifdef DIAGNOSTIC
if (hdr.type != HCI_ACL_DATA_PKT) {
- printf("%s: bad ACL packet type\n", unit->hci_devname);
+ printf("%s: bad ACL packet type\n",
+ device_xname(unit->hci_dev));
goto bad;
}
if (m->m_pkthdr.len != letoh16(hdr.length)) {
printf("%s: bad ACL packet length (%d != %d)\n",
- unit->hci_devname, m->m_pkthdr.len, letoh16(hdr.length));
+ device_xname(unit->hci_dev), m->m_pkthdr.len,
+ letoh16(hdr.length));
goto bad;
}
#endif
@@ -445,7 +445,7 @@ hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
hci_discon_cp cp;
DPRINTF("%s: dumping packet for unknown handle #%d\n",
- unit->hci_devname, handle);
+ device_xname(unit->hci_dev), handle);
/*
* There is no way to find out what this connection handle is
@@ -463,11 +463,11 @@ hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
case HCI_PACKET_START:
if (link->hl_rxp != NULL)
printf("%s: dropped incomplete ACL packet\n",
- unit->hci_devname);
+ device_xname(unit->hci_dev));
if (m->m_pkthdr.len < sizeof(l2cap_hdr_t)) {
printf("%s: short ACL packet\n",
- unit->hci_devname);
+ device_xname(unit->hci_dev));
goto bad;
}
@@ -479,7 +479,7 @@ hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
case HCI_PACKET_FRAGMENT:
if (link->hl_rxp == NULL) {
printf("%s: unexpected packet fragment\n",
- unit->hci_devname);
+ device_xname(unit->hci_dev));
goto bad;
}
@@ -492,7 +492,7 @@ hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
default:
printf("%s: unknown packet type\n",
- unit->hci_devname);
+ device_xname(unit->hci_dev));
goto bad;
}
@@ -552,7 +552,7 @@ hci_acl_send(struct mbuf *m, struct hci_link *link,
mlen = link->hl_unit->hci_max_acl_size;
DPRINTFN(5, "%s: handle #%d, plen = %d, max = %d\n",
- link->hl_unit->hci_devname, link->hl_handle, plen, mlen);
+ device_xname(link->hl_unit->hci_dev), link->hl_handle, plen, mlen);
while (plen > 0) {
if (plen > mlen) {
@@ -566,7 +566,8 @@ hci_acl_send(struct mbuf *m, struct hci_link *link,
if (num++ == 0)
m->m_flags |= M_PROTO1; /* tag first fragment */
- DPRINTFN(10, "chunk of %d (plen = %d) bytes\n", mlen, plen);
+ DPRINTFN(10, "(%s) chunk of %d (plen = %d) bytes\n",
+ device_xname(link->hl_unit->hci_dev), mlen, plen);
IF_ENQUEUE(&pdu->lp_data, m);
m = n;
plen -= mlen;
@@ -700,15 +701,16 @@ hci_acl_complete(struct hci_link *link, int num)
struct l2cap_pdu *pdu;
struct l2cap_channel *chan;
- DPRINTFN(5, "handle #%d (%d)\n", link->hl_handle, num);
+ DPRINTFN(5, "(%s) handle #%d (%d)\n",
+ device_xname(link->hl_unit->hci_dev), link->hl_handle, num);
while (num > 0) {
pdu = TAILQ_FIRST(&link->hl_txq);
if (pdu == NULL) {
printf("%s: %d packets completed on handle #%x "
- "but none pending!\n",
- link->hl_unit->hci_devname, num,
- link->hl_handle);
+ "but none pending!\n",
+ device_xname(link->hl_unit->hci_dev), num,
+ link->hl_handle);
return;
}
@@ -829,13 +831,14 @@ hci_sco_recv(struct mbuf *m, struct hci_unit *unit)
#ifdef DIAGNOSTIC
if (hdr.type != HCI_SCO_DATA_PKT) {
- printf("%s: bad SCO packet type\n", unit->hci_devname);
+ printf("%s: bad SCO packet type\n",
+ device_xname(unit->hci_dev));
goto bad;
}
if (m->m_pkthdr.len != hdr.length) {
printf("%s: bad SCO packet length (%d != %d)\n",
- unit->hci_devname, m->m_pkthdr.len, hdr.length);
+ device_xname(unit->hci_dev), m->m_pkthdr.len, hdr.length);
goto bad;
}
#endif
@@ -846,7 +849,7 @@ hci_sco_recv(struct mbuf *m, struct hci_unit *unit)
link = hci_link_lookup_handle(unit, handle);
if (link == NULL || link->hl_type == HCI_LINK_ACL) {
DPRINTF("%s: dumping packet for unknown handle #%d\n",
- unit->hci_devname, handle);
+ device_xname(unit->hci_dev), handle);
goto bad;
}
@@ -904,6 +907,9 @@ hci_link_alloc(struct hci_unit *unit)
link->hl_mtu = L2CAP_MTU_DEFAULT; /* L2CAP signal mtu */
link->hl_flush = L2CAP_FLUSH_TIMO_DEFAULT; /* flush timeout */
+ /* init SCO portion */
+ /* &link->hl_data is already zero-initialized. */
+
/* attach to unit */
TAILQ_INSERT_HEAD(&unit->hci_links, link, hl_next);
return link;
@@ -918,9 +924,9 @@ hci_link_free(struct hci_link *link, int err)
KASSERT(link != NULL);
- DPRINTF("#%d, type = %d, state = %d, refcnt = %d\n",
- link->hl_handle, link->hl_type,
- link->hl_state, link->hl_refcnt);
+ DPRINTF("(%s) #%d, type = %d, state = %d, refcnt = %d\n",
+ device_xname(link->hl_unit->hci_dev), link->hl_handle,
+ link->hl_type, link->hl_state, link->hl_refcnt);
/* ACL reference count */
if (link->hl_refcnt > 0) {
@@ -986,6 +992,18 @@ hci_link_free(struct hci_link *link, int err)
if (timeout_triggered(&link->hl_expire))
return;
+ /*
+ * If we made a note of clock offset, keep it in a memo
+ * to facilitate reconnections to this device
+ */
+ if (link->hl_clock != 0) {
+ struct hci_memo *memo;
+
+ memo = hci_memo_new(link->hl_unit, &link->hl_bdaddr);
+ if (memo != NULL)
+ memo->clock_offset = link->hl_clock;
+ }
+
TAILQ_REMOVE(&link->hl_unit->hci_links, link, hl_next);
free(link, M_BLUETOOTH);
}
diff --git a/sys/netbt/hci_misc.c b/sys/netbt/hci_misc.c
index dd5f3b10149..5cb144036a5 100644
--- a/sys/netbt/hci_misc.c
+++ b/sys/netbt/hci_misc.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: hci_misc.c,v 1.1 2007/05/30 03:42:53 uwe Exp $ */
-/* $NetBSD: hci_misc.c,v 1.1 2006/06/19 15:44:45 gdamore Exp $ */
+/* $OpenBSD: hci_misc.c,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: hci_misc.c,v 1.3 2007/09/16 19:59:30 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@@ -31,8 +31,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
@@ -129,7 +127,7 @@ hci_memo_find(struct hci_unit *unit, bdaddr_t *bdaddr)
continue;
}
- if (bdaddr_same(bdaddr, &memo->response.bdaddr)) {
+ if (bdaddr_same(bdaddr, &memo->bdaddr)) {
DPRINTF("memo %p found\n", memo);
return memo;
}
@@ -139,6 +137,41 @@ hci_memo_find(struct hci_unit *unit, bdaddr_t *bdaddr)
return NULL;
}
+/*
+ * Make a new memo on unit for bdaddr. If a memo exists, just
+ * update the timestamp.
+ */
+struct hci_memo *
+hci_memo_new(struct hci_unit *unit, bdaddr_t *bdaddr)
+{
+ struct hci_memo *memo;
+
+ memo = hci_memo_find(unit, bdaddr);
+ if (memo == NULL) {
+ memo = malloc(sizeof(struct hci_memo),
+ M_BLUETOOTH, M_NOWAIT | M_ZERO);
+
+ if (memo == NULL) {
+ DPRINTFN(0, "no memory for memo!\n");
+ return NULL;
+ }
+
+ DPRINTF("memo created for %02x:%02x:%02x:%02x:%02x:%02x\n",
+ bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
+ bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
+
+ bdaddr_copy(&memo->bdaddr, bdaddr);
+ LIST_INSERT_HEAD(&unit->hci_memos, memo, next);
+ }
+ else
+ DPRINTF("memo updated for %02x:%02x:%02x:%02x:%02x:%02x\n",
+ bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
+ bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
+
+ microtime(&memo->time);
+ return memo;
+}
+
void
hci_memo_free(struct hci_memo *memo)
{
diff --git a/sys/netbt/hci_socket.c b/sys/netbt/hci_socket.c
index 4933e461aa0..7e9c74ba3af 100644
--- a/sys/netbt/hci_socket.c
+++ b/sys/netbt/hci_socket.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: hci_socket.c,v 1.4 2007/09/17 01:33:33 krw Exp $ */
-/* $NetBSD: hci_socket.c,v 1.10 2007/03/31 18:17:13 plunky Exp $ */
+/* $OpenBSD: hci_socket.c,v 1.5 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: hci_socket.c,v 1.14 2008/02/10 17:40:54 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@@ -31,8 +31,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
/* load symbolic names */
#ifdef BLUETOOTH_DEBUG
#define PRUREQUESTS
@@ -82,104 +80,318 @@ LIST_HEAD(hci_pcb_list, hci_pcb) hci_pcb = LIST_HEAD_INITIALIZER(hci_pcb);
int hci_sendspace = HCI_CMD_PKT_SIZE;
int hci_recvspace = 4096;
+/* supported commands opcode table */
+static const struct {
+ uint16_t opcode;
+ uint8_t offs; /* 0 - 63 */
+ uint8_t mask; /* bit 0 - 7 */
+ int16_t length; /* -1 if privileged */
+} hci_cmds[] = {
+ { HCI_CMD_INQUIRY,
+ 0, 0x01, sizeof(hci_inquiry_cp) },
+ { HCI_CMD_INQUIRY_CANCEL,
+ 0, 0x02, -1 },
+ { HCI_CMD_PERIODIC_INQUIRY,
+ 0, 0x04, -1 },
+ { HCI_CMD_EXIT_PERIODIC_INQUIRY,
+ 0, 0x08, -1 },
+ { HCI_CMD_CREATE_CON,
+ 0, 0x10, -1 },
+ { HCI_CMD_DISCONNECT,
+ 0, 0x20, -1 },
+ { HCI_CMD_ADD_SCO_CON,
+ 0, 0x40, -1 },
+ { HCI_CMD_CREATE_CON_CANCEL,
+ 0, 0x80, -1 },
+ { HCI_CMD_ACCEPT_CON,
+ 1, 0x01, -1 },
+ { HCI_CMD_REJECT_CON,
+ 1, 0x02, -1 },
+ { HCI_CMD_LINK_KEY_REP,
+ 1, 0x04, -1 },
+ { HCI_CMD_LINK_KEY_NEG_REP,
+ 1, 0x08, -1 },
+ { HCI_CMD_PIN_CODE_REP,
+ 1, 0x10, -1 },
+ { HCI_CMD_PIN_CODE_NEG_REP,
+ 1, 0x20, -1 },
+ { HCI_CMD_CHANGE_CON_PACKET_TYPE,
+ 1, 0x40, -1 },
+ { HCI_CMD_AUTH_REQ,
+ 1, 0x80, -1 },
+ { HCI_CMD_SET_CON_ENCRYPTION,
+ 2, 0x01, -1 },
+ { HCI_CMD_CHANGE_CON_LINK_KEY,
+ 2, 0x02, -1 },
+ { HCI_CMD_MASTER_LINK_KEY,
+ 2, 0x04, -1 },
+ { HCI_CMD_REMOTE_NAME_REQ,
+ 2, 0x08, sizeof(hci_remote_name_req_cp) },
+ { HCI_CMD_REMOTE_NAME_REQ_CANCEL,
+ 2, 0x10, -1 },
+ { HCI_CMD_READ_REMOTE_FEATURES,
+ 2, 0x20, sizeof(hci_read_remote_features_cp) },
+ { HCI_CMD_READ_REMOTE_EXTENDED_FEATURES,
+ 2, 0x40, sizeof(hci_read_remote_extended_features_cp) },
+ { HCI_CMD_READ_REMOTE_VER_INFO,
+ 2, 0x80, sizeof(hci_read_remote_ver_info_cp) },
+ { HCI_CMD_READ_CLOCK_OFFSET,
+ 3, 0x01, sizeof(hci_read_clock_offset_cp) },
+ { HCI_CMD_READ_LMP_HANDLE,
+ 3, 0x02, sizeof(hci_read_lmp_handle_cp) },
+ { HCI_CMD_HOLD_MODE,
+ 4, 0x02, -1 },
+ { HCI_CMD_SNIFF_MODE,
+ 4, 0x04, -1 },
+ { HCI_CMD_EXIT_SNIFF_MODE,
+ 4, 0x08, -1 },
+ { HCI_CMD_PARK_MODE,
+ 4, 0x10, -1 },
+ { HCI_CMD_EXIT_PARK_MODE,
+ 4, 0x20, -1 },
+ { HCI_CMD_QOS_SETUP,
+ 4, 0x40, -1 },
+ { HCI_CMD_ROLE_DISCOVERY,
+ 4, 0x80, sizeof(hci_role_discovery_cp) },
+ { HCI_CMD_SWITCH_ROLE,
+ 5, 0x01, -1 },
+ { HCI_CMD_READ_LINK_POLICY_SETTINGS,
+ 5, 0x02, sizeof(hci_read_link_policy_settings_cp) },
+ { HCI_CMD_WRITE_LINK_POLICY_SETTINGS,
+ 5, 0x04, -1 },
+ { HCI_CMD_READ_DEFAULT_LINK_POLICY_SETTINGS,
+ 5, 0x08, 0 },
+ { HCI_CMD_WRITE_DEFAULT_LINK_POLICY_SETTINGS,
+ 5, 0x10, -1 },
+ { HCI_CMD_FLOW_SPECIFICATION,
+ 5, 0x20, -1 },
+ { HCI_CMD_SET_EVENT_MASK,
+ 5, 0x40, -1 },
+ { HCI_CMD_RESET,
+ 5, 0x80, -1 },
+ { HCI_CMD_SET_EVENT_FILTER,
+ 6, 0x01, -1 },
+ { HCI_CMD_FLUSH,
+ 6, 0x02, -1 },
+ { HCI_CMD_READ_PIN_TYPE,
+ 6, 0x04, 0 },
+ { HCI_CMD_WRITE_PIN_TYPE,
+ 6, 0x08, -1 },
+ { HCI_CMD_CREATE_NEW_UNIT_KEY,
+ 6, 0x10, -1 },
+ { HCI_CMD_READ_STORED_LINK_KEY,
+ 6, 0x20, -1 },
+ { HCI_CMD_WRITE_STORED_LINK_KEY,
+ 6, 0x40, -1 },
+ { HCI_CMD_DELETE_STORED_LINK_KEY,
+ 6, 0x80, -1 },
+ { HCI_CMD_WRITE_LOCAL_NAME,
+ 7, 0x01, -1 },
+ { HCI_CMD_READ_LOCAL_NAME,
+ 7, 0x02, 0 },
+ { HCI_CMD_READ_CON_ACCEPT_TIMEOUT,
+ 7, 0x04, 0 },
+ { HCI_CMD_WRITE_CON_ACCEPT_TIMEOUT,
+ 7, 0x08, -1 },
+ { HCI_CMD_READ_PAGE_TIMEOUT,
+ 7, 0x10, 0 },
+ { HCI_CMD_WRITE_PAGE_TIMEOUT,
+ 7, 0x20, -1 },
+ { HCI_CMD_READ_SCAN_ENABLE,
+ 7, 0x40, 0 },
+ { HCI_CMD_WRITE_SCAN_ENABLE,
+ 7, 0x80, -1 },
+ { HCI_CMD_READ_PAGE_SCAN_ACTIVITY,
+ 8, 0x01, 0 },
+ { HCI_CMD_WRITE_PAGE_SCAN_ACTIVITY,
+ 8, 0x02, -1 },
+ { HCI_CMD_READ_INQUIRY_SCAN_ACTIVITY,
+ 8, 0x04, 0 },
+ { HCI_CMD_WRITE_INQUIRY_SCAN_ACTIVITY,
+ 8, 0x08, -1 },
+ { HCI_CMD_READ_AUTH_ENABLE,
+ 8, 0x10, 0 },
+ { HCI_CMD_WRITE_AUTH_ENABLE,
+ 8, 0x20, -1 },
+ { HCI_CMD_READ_ENCRYPTION_MODE,
+ 8, 0x40, 0 },
+ { HCI_CMD_WRITE_ENCRYPTION_MODE,
+ 8, 0x80, -1 },
+ { HCI_CMD_READ_UNIT_CLASS,
+ 9, 0x01, 0 },
+ { HCI_CMD_WRITE_UNIT_CLASS,
+ 9, 0x02, -1 },
+ { HCI_CMD_READ_VOICE_SETTING,
+ 9, 0x04, 0 },
+ { HCI_CMD_WRITE_VOICE_SETTING,
+ 9, 0x08, -1 },
+ { HCI_CMD_READ_AUTO_FLUSH_TIMEOUT,
+ 9, 0x10, sizeof(hci_read_auto_flush_timeout_cp) },
+ { HCI_CMD_WRITE_AUTO_FLUSH_TIMEOUT,
+ 9, 0x20, -1 },
+ { HCI_CMD_READ_NUM_BROADCAST_RETRANS,
+ 9, 0x40, 0 },
+ { HCI_CMD_WRITE_NUM_BROADCAST_RETRANS,
+ 9, 0x80, -1 },
+ { HCI_CMD_READ_HOLD_MODE_ACTIVITY,
+ 10, 0x01, 0 },
+ { HCI_CMD_WRITE_HOLD_MODE_ACTIVITY,
+ 10, 0x02, -1 },
+ { HCI_CMD_READ_XMIT_LEVEL,
+ 10, 0x04, sizeof(hci_read_xmit_level_cp) },
+ { HCI_CMD_READ_SCO_FLOW_CONTROL,
+ 10, 0x08, 0 },
+ { HCI_CMD_WRITE_SCO_FLOW_CONTROL,
+ 10, 0x10, -1 },
+ { HCI_CMD_HC2H_FLOW_CONTROL,
+ 10, 0x20, -1 },
+ { HCI_CMD_HOST_BUFFER_SIZE,
+ 10, 0x40, -1 },
+ { HCI_CMD_HOST_NUM_COMPL_PKTS,
+ 10, 0x80, -1 },
+ { HCI_CMD_READ_LINK_SUPERVISION_TIMEOUT,
+ 11, 0x01, sizeof(hci_read_link_supervision_timeout_cp) },
+ { HCI_CMD_WRITE_LINK_SUPERVISION_TIMEOUT,
+ 11, 0x02, -1 },
+ { HCI_CMD_READ_NUM_SUPPORTED_IAC,
+ 11, 0x04, 0 },
+ { HCI_CMD_READ_IAC_LAP,
+ 11, 0x08, 0 },
+ { HCI_CMD_WRITE_IAC_LAP,
+ 11, 0x10, -1 },
+ { HCI_CMD_READ_PAGE_SCAN_PERIOD,
+ 11, 0x20, 0 },
+ { HCI_CMD_WRITE_PAGE_SCAN_PERIOD,
+ 11, 0x40, -1 },
+ { HCI_CMD_READ_PAGE_SCAN,
+ 11, 0x80, 0 },
+ { HCI_CMD_WRITE_PAGE_SCAN,
+ 12, 0x01, -1 },
+ { HCI_CMD_SET_AFH_CLASSIFICATION,
+ 12, 0x02, -1 },
+ { HCI_CMD_READ_INQUIRY_SCAN_TYPE,
+ 12, 0x10, 0 },
+ { HCI_CMD_WRITE_INQUIRY_SCAN_TYPE,
+ 12, 0x20, -1 },
+ { HCI_CMD_READ_INQUIRY_MODE,
+ 12, 0x40, 0 },
+ { HCI_CMD_WRITE_INQUIRY_MODE,
+ 12, 0x80, -1 },
+ { HCI_CMD_READ_PAGE_SCAN_TYPE,
+ 13, 0x01, 0 },
+ { HCI_CMD_WRITE_PAGE_SCAN_TYPE,
+ 13, 0x02, -1 },
+ { HCI_CMD_READ_AFH_ASSESSMENT,
+ 13, 0x04, 0 },
+ { HCI_CMD_WRITE_AFH_ASSESSMENT,
+ 13, 0x08, -1 },
+ { HCI_CMD_READ_LOCAL_VER,
+ 14, 0x08, 0 },
+ { HCI_CMD_READ_LOCAL_COMMANDS,
+ 14, 0x10, 0 },
+ { HCI_CMD_READ_LOCAL_FEATURES,
+ 14, 0x20, 0 },
+ { HCI_CMD_READ_LOCAL_EXTENDED_FEATURES,
+ 14, 0x40, sizeof(hci_read_local_extended_features_cp) },
+ { HCI_CMD_READ_BUFFER_SIZE,
+ 14, 0x80, 0 },
+ { HCI_CMD_READ_COUNTRY_CODE,
+ 15, 0x01, 0 },
+ { HCI_CMD_READ_BDADDR,
+ 15, 0x02, 0 },
+ { HCI_CMD_READ_FAILED_CONTACT_CNTR,
+ 15, 0x04, sizeof(hci_read_failed_contact_cntr_cp) },
+ { HCI_CMD_RESET_FAILED_CONTACT_CNTR,
+ 15, 0x08, -1 },
+ { HCI_CMD_READ_LINK_QUALITY,
+ 15, 0x10, sizeof(hci_read_link_quality_cp) },
+ { HCI_CMD_READ_RSSI,
+ 15, 0x20, sizeof(hci_read_rssi_cp) },
+ { HCI_CMD_READ_AFH_CHANNEL_MAP,
+ 15, 0x40, sizeof(hci_read_afh_channel_map_cp) },
+ { HCI_CMD_READ_CLOCK,
+ 15, 0x80, sizeof(hci_read_clock_cp) },
+ { HCI_CMD_READ_LOOPBACK_MODE,
+ 16, 0x01, 0 },
+ { HCI_CMD_WRITE_LOOPBACK_MODE,
+ 16, 0x02, -1 },
+ { HCI_CMD_ENABLE_UNIT_UNDER_TEST,
+ 16, 0x04, -1 },
+ { HCI_CMD_SETUP_SCO_CON,
+ 16, 0x08, -1 },
+ { HCI_CMD_ACCEPT_SCO_CON_REQ,
+ 16, 0x10, -1 },
+ { HCI_CMD_REJECT_SCO_CON_REQ,
+ 16, 0x20, -1 },
+ { HCI_CMD_READ_EXTENDED_INQUIRY_RSP,
+ 17, 0x01, 0 },
+ { HCI_CMD_WRITE_EXTENDED_INQUIRY_RSP,
+ 17, 0x02, -1 },
+ { HCI_CMD_REFRESH_ENCRYPTION_KEY,
+ 17, 0x04, -1 },
+ { HCI_CMD_SNIFF_SUBRATING,
+ 17, 0x10, -1 },
+ { HCI_CMD_READ_SIMPLE_PAIRING_MODE,
+ 17, 0x20, 0 },
+ { HCI_CMD_WRITE_SIMPLE_PAIRING_MODE,
+ 17, 0x40, -1 },
+ { HCI_CMD_READ_LOCAL_OOB_DATA,
+ 17, 0x80, -1 },
+ { HCI_CMD_READ_INQUIRY_RSP_XMIT_POWER,
+ 18, 0x01, 0 },
+ { HCI_CMD_WRITE_INQUIRY_RSP_XMIT_POWER,
+ 18, 0x02, -1 },
+ { HCI_CMD_READ_DEFAULT_ERRDATA_REPORTING,
+ 18, 0x04, 0 },
+ { HCI_CMD_WRITE_DEFAULT_ERRDATA_REPORTING,
+ 18, 0x08, -1 },
+ { HCI_CMD_IO_CAPABILITY_REP,
+ 18, 0x80, -1 },
+ { HCI_CMD_USER_CONFIRM_REP,
+ 19, 0x01, -1 },
+ { HCI_CMD_USER_CONFIRM_NEG_REP,
+ 19, 0x02, -1 },
+ { HCI_CMD_USER_PASSKEY_REP,
+ 19, 0x04, -1 },
+ { HCI_CMD_USER_PASSKEY_NEG_REP,
+ 19, 0x08, -1 },
+ { HCI_CMD_OOB_DATA_REP,
+ 19, 0x10, -1 },
+ { HCI_CMD_WRITE_SIMPLE_PAIRING_DEBUG_MODE,
+ 19, 0x20, -1 },
+ { HCI_CMD_ENHANCED_FLUSH,
+ 19, 0x40, -1 },
+ { HCI_CMD_OOB_DATA_NEG_REP,
+ 19, 0x80, -1 },
+ { HCI_CMD_SEND_KEYPRESS_NOTIFICATION,
+ 20, 0x40, -1 },
+ { HCI_CMD_IO_CAPABILITY_NEG_REP,
+ 20, 0x80, -1 },
+};
+
/*
* Security filter routines for unprivileged users.
* Allow all but a few critical events, and only permit read commands.
+ * If a unit is given, verify the command is supported.
*/
static int
-hci_security_check_opcode(uint16_t opcode)
+hci_security_check_opcode(struct hci_unit *unit, uint16_t opcode)
{
+ int i;
+
+ for (i = 0 ; i < sizeof(hci_cmds) / sizeof(hci_cmds[0]); i++) {
+ if (opcode != hci_cmds[i].opcode)
+ continue;
- switch (opcode) {
- /* Link control */
- case HCI_CMD_INQUIRY:
- return sizeof(hci_inquiry_cp);
- case HCI_CMD_REMOTE_NAME_REQ:
- return sizeof(hci_remote_name_req_cp);
- case HCI_CMD_READ_REMOTE_FEATURES:
- return sizeof(hci_read_remote_features_cp);
- case HCI_CMD_READ_REMOTE_EXTENDED_FEATURES:
- return sizeof(hci_read_remote_extended_features_cp);
- case HCI_CMD_READ_REMOTE_VER_INFO:
- return sizeof(hci_read_remote_ver_info_cp);
- case HCI_CMD_READ_CLOCK_OFFSET:
- return sizeof(hci_read_clock_offset_cp);
- case HCI_CMD_READ_LMP_HANDLE:
- return sizeof(hci_read_lmp_handle_cp);
-
- /* Link policy */
- case HCI_CMD_ROLE_DISCOVERY:
- return sizeof(hci_role_discovery_cp);
- case HCI_CMD_READ_LINK_POLICY_SETTINGS:
- return sizeof(hci_read_link_policy_settings_cp);
- case HCI_CMD_READ_DEFAULT_LINK_POLICY_SETTINGS:
- return 0; /* No command parameters */
-
- /* Host controller and baseband */
- case HCI_CMD_READ_PIN_TYPE:
- case HCI_CMD_READ_LOCAL_NAME:
- case HCI_CMD_READ_CON_ACCEPT_TIMEOUT:
- case HCI_CMD_READ_PAGE_TIMEOUT:
- case HCI_CMD_READ_SCAN_ENABLE:
- case HCI_CMD_READ_PAGE_SCAN_ACTIVITY:
- case HCI_CMD_READ_INQUIRY_SCAN_ACTIVITY:
- case HCI_CMD_READ_AUTH_ENABLE:
- case HCI_CMD_READ_ENCRYPTION_MODE:
- case HCI_CMD_READ_UNIT_CLASS:
- case HCI_CMD_READ_VOICE_SETTING:
- return 0; /* No command parameters */
- case HCI_CMD_READ_AUTO_FLUSH_TIMEOUT:
- return sizeof(hci_read_auto_flush_timeout_cp);
- case HCI_CMD_READ_NUM_BROADCAST_RETRANS:
- case HCI_CMD_READ_HOLD_MODE_ACTIVITY:
- return 0; /* No command parameters */
- case HCI_CMD_READ_XMIT_LEVEL:
- return sizeof(hci_read_xmit_level_cp);
- case HCI_CMD_READ_SCO_FLOW_CONTROL:
- return 0; /* No command parameters */
- case HCI_CMD_READ_LINK_SUPERVISION_TIMEOUT:
- return sizeof(hci_read_link_supervision_timeout_cp);
- case HCI_CMD_READ_NUM_SUPPORTED_IAC:
- case HCI_CMD_READ_IAC_LAP:
- case HCI_CMD_READ_PAGE_SCAN_PERIOD:
- case HCI_CMD_READ_PAGE_SCAN:
- case HCI_CMD_READ_INQUIRY_SCAN_TYPE:
- case HCI_CMD_READ_INQUIRY_MODE:
- case HCI_CMD_READ_PAGE_SCAN_TYPE:
- case HCI_CMD_READ_AFH_ASSESSMENT:
- return 0; /* No command parameters */
-
- /* Informational */
- case HCI_CMD_READ_LOCAL_VER:
- case HCI_CMD_READ_LOCAL_COMMANDS:
- case HCI_CMD_READ_LOCAL_FEATURES:
- return 0; /* No command parameters */
- case HCI_CMD_READ_LOCAL_EXTENDED_FEATURES:
- return sizeof(hci_read_local_extended_features_cp);
- case HCI_CMD_READ_BUFFER_SIZE:
- case HCI_CMD_READ_COUNTRY_CODE:
- case HCI_CMD_READ_BDADDR:
- return 0; /* No command parameters */
-
- /* Status */
- case HCI_CMD_READ_FAILED_CONTACT_CNTR:
- return sizeof(hci_read_failed_contact_cntr_cp);
- case HCI_CMD_READ_LINK_QUALITY:
- return sizeof(hci_read_link_quality_cp);
- case HCI_CMD_READ_RSSI:
- return sizeof(hci_read_rssi_cp);
- case HCI_CMD_READ_AFH_CHANNEL_MAP:
- return sizeof(hci_read_afh_channel_map_cp);
- case HCI_CMD_READ_CLOCK:
- return sizeof(hci_read_clock_cp);
-
- /* Testing */
- case HCI_CMD_READ_LOOPBACK_MODE:
- return 0; /* No command parameters */
+ if (unit == NULL
+ || (unit->hci_cmds[hci_cmds[i].offs] & hci_cmds[i].mask))
+ return hci_cmds[i].length;
+
+ break;
}
- return -1; /* disallowed */
+ return -1;
}
static int
@@ -189,6 +401,8 @@ hci_security_check_event(uint8_t event)
switch (event) {
case HCI_EVENT_RETURN_LINK_KEYS:
case HCI_EVENT_LINK_KEY_NOTIFICATION:
+ case HCI_EVENT_USER_CONFIRM_REQ:
+ case HCI_EVENT_USER_PASSKEY_NOTIFICATION:
case HCI_EVENT_VENDOR:
return -1; /* disallowed */
}
@@ -256,6 +470,7 @@ hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
goto bad;
}
m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
+ hdr.opcode = letoh16(hdr.opcode);
/* only allows CMD packets to be sent */
if (hdr.type != HCI_CMD_PKT) {
@@ -269,13 +484,6 @@ hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
goto bad;
}
- /* security checks for unprivileged users */
- if ((pcb->hp_flags & HCI_PRIVILEGED) == 0
- && hci_security_check_opcode(letoh16(hdr.opcode)) != hdr.length) {
- err = EPERM;
- goto bad;
- }
-
/* finds destination */
unit = hci_unit_lookup(addr);
if (unit == NULL) {
@@ -283,6 +491,13 @@ hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
goto bad;
}
+ /* security checks for unprivileged users */
+ if ((pcb->hp_flags & HCI_PRIVILEGED) == 0
+ && hci_security_check_opcode(unit, hdr.opcode) != hdr.length) {
+ err = EPERM;
+ goto bad;
+ }
+
/* makes a copy for precious to keep */
m0 = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
if (m0 == NULL) {
@@ -292,8 +507,8 @@ hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
sbappendrecord(&pcb->hp_socket->so_snd, m0);
M_SETCTX(m, pcb->hp_socket); /* enable drop callback */
- DPRINTFN(2, "(%s) opcode (%03x|%04x)\n", unit->hci_devname,
- HCI_OGF(letoh16(hdr.opcode)), HCI_OCF(letoh16(hdr.opcode)));
+ DPRINTFN(2, "(%s) opcode (%03x|%04x)\n", device_xname(unit->hci_dev),
+ HCI_OGF(hdr.opcode), HCI_OCF(hdr.opcode));
/* Sendss it */
if (unit->hci_num_cmd_pkts == 0)
@@ -305,7 +520,7 @@ hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
bad:
DPRINTF("packet (%d bytes) not sent (error %d)\n",
- m->m_pkthdr.len, err);
+ m->m_pkthdr.len, err);
if (m) m_freem(m);
return err;
}
@@ -668,7 +883,7 @@ hci_mtap(struct mbuf *m, struct hci_unit *unit)
opcode = letoh16(mtod(m, hci_cmd_hdr_t *)->opcode);
if ((pcb->hp_flags & HCI_PRIVILEGED) == 0
- && hci_security_check_opcode(opcode) == -1)
+ && hci_security_check_opcode(NULL, opcode) == -1)
continue;
break;
diff --git a/sys/netbt/hci_unit.c b/sys/netbt/hci_unit.c
index 21aca86e196..df0e52c01b9 100644
--- a/sys/netbt/hci_unit.c
+++ b/sys/netbt/hci_unit.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: hci_unit.c,v 1.7 2007/06/24 20:55:27 uwe Exp $ */
-/* $NetBSD: hci_unit.c,v 1.4 2007/03/30 20:47:03 plunky Exp $ */
+/* $OpenBSD: hci_unit.c,v 1.8 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: hci_unit.c,v 1.9 2007/12/30 18:26:42 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@@ -31,8 +31,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/device.h>
@@ -56,55 +54,95 @@ struct hci_unit_list hci_unit_list = TAILQ_HEAD_INITIALIZER(hci_unit_list);
int hci_eventq_max = 20;
int hci_aclrxq_max = 50;
int hci_scorxq_max = 50;
+int hci_cmdwait_max = 50;
+int hci_scodone_max = 50;
+
+/*
+ * This is the default minimum command set supported by older
+ * devices. Anything conforming to 1.2 spec or later will get
+ * updated during init.
+ */
+static const uint8_t hci_cmds_v10[HCI_COMMANDS_SIZE] = {
+ 0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x7f, 0x32, 0x03, 0xb8, 0xfe,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
/*
* bluetooth unit functions
*/
-void
-hci_attach(struct hci_unit *unit)
+struct hci_unit *
+hci_attach(const struct hci_if *hci_if, struct device *dev, uint16_t flags)
{
- KASSERT(unit->hci_softc != NULL);
- KASSERT(unit->hci_devname != NULL);
- KASSERT(unit->hci_enable != NULL);
- KASSERT(unit->hci_disable != NULL);
- KASSERT(unit->hci_start_cmd != NULL);
- KASSERT(unit->hci_start_acl != NULL);
- KASSERT(unit->hci_start_sco != NULL);
+ struct hci_unit *unit;
+ int s;
+
+ KASSERT(dev != NULL);
+ KASSERT(hci_if->enable != NULL);
+ KASSERT(hci_if->disable != NULL);
+ KASSERT(hci_if->output_cmd != NULL);
+ KASSERT(hci_if->output_acl != NULL);
+ KASSERT(hci_if->output_sco != NULL);
+ KASSERT(hci_if->get_stats != NULL);
+
+ unit = malloc(sizeof(struct hci_unit), M_BLUETOOTH, M_ZERO | M_WAITOK);
+ KASSERT(unit != NULL);
+
+ unit->hci_dev = dev;
+ unit->hci_if = hci_if;
+ unit->hci_flags = flags;
+
+ mtx_init(&unit->hci_devlock, hci_if->ipl);
unit->hci_eventq.ifq_maxlen = hci_eventq_max;
unit->hci_aclrxq.ifq_maxlen = hci_aclrxq_max;
unit->hci_scorxq.ifq_maxlen = hci_scorxq_max;
+ unit->hci_cmdwait.ifq_maxlen = hci_cmdwait_max;
+ unit->hci_scodone.ifq_maxlen = hci_scodone_max;
TAILQ_INIT(&unit->hci_links);
LIST_INIT(&unit->hci_memos);
+ s = splsoftnet();
TAILQ_INSERT_TAIL(&hci_unit_list, unit, hci_next);
+ splx(s);
+
+ return unit;
}
void
hci_detach(struct hci_unit *unit)
{
+ int s;
+
+ s = splsoftnet();
hci_disable(unit);
TAILQ_REMOVE(&hci_unit_list, unit, hci_next);
+ splx(s);
+
+ free(unit, M_BLUETOOTH);
}
int
hci_enable(struct hci_unit *unit)
{
- int s, err;
+ int err;
/*
* Bluetooth spec says that a device can accept one
* command on power up until they send a Command Status
* or Command Complete event with more information, but
* it seems that some devices cant and prefer to send a
- * No-op Command Status packet when they are ready, so
- * we set this here and allow the driver (bt3c) to zero
- * it.
+ * No-op Command Status packet when they are ready.
*/
- unit->hci_num_cmd_pkts = 1;
+ unit->hci_num_cmd_pkts = (unit->hci_flags & BTF_POWER_UP_NOOP) ? 0 : 1;
unit->hci_num_acl_pkts = 0;
unit->hci_num_sco_pkts = 0;
@@ -115,12 +153,20 @@ hci_enable(struct hci_unit *unit)
unit->hci_acl_mask = HCI_PKT_DM1 | HCI_PKT_DH1;
unit->hci_packet_type = unit->hci_acl_mask;
- s = splraiseipl(unit->hci_ipl);
- err = (*unit->hci_enable)(unit);
- splx(s);
+ memcpy(unit->hci_cmds, hci_cmds_v10, HCI_COMMANDS_SIZE);
+
+#ifndef __OpenBSD__
+ unit->hci_rxint = softint_establish(SOFTINT_NET, &hci_intr, unit);
+ if (unit->hci_rxint == NULL)
+ return EIO;
+#endif
+
+ err = (*unit->hci_if->enable)(unit->hci_dev);
if (err)
goto bad1;
+ unit->hci_flags |= BTF_RUNNING;
+
/*
* Reset the device, this will trigger initialisation
* and wake us up.
@@ -145,17 +191,20 @@ hci_enable(struct hci_unit *unit)
/*
* Attach Bluetooth Device Hub
*/
- unit->hci_bthub = config_found(unit->hci_softc,
+ unit->hci_bthub = config_found(unit->hci_dev,
&unit->hci_bdaddr, NULL);
return 0;
bad2:
- s = splraiseipl(unit->hci_ipl);
- (*unit->hci_disable)(unit);
- splx(s);
-
+ (*unit->hci_if->disable)(unit->hci_dev);
+ unit->hci_flags &= ~BTF_RUNNING;
bad1:
+#ifndef __OpenBSD__
+ softint_disestablish(unit->hci_rxint);
+ unit->hci_rxint = NULL;
+#endif
+
return err;
}
@@ -164,16 +213,22 @@ hci_disable(struct hci_unit *unit)
{
struct hci_link *link, *next;
struct hci_memo *memo;
- int s, acl;
+ int acl;
if (unit->hci_bthub) {
config_detach(unit->hci_bthub, DETACH_FORCE);
unit->hci_bthub = NULL;
}
- s = splraiseipl(unit->hci_ipl);
- (*unit->hci_disable)(unit);
- splx(s);
+#ifndef __OpenBSD__
+ if (unit->hci_rxint) {
+ softint_disestablish(unit->hci_rxint);
+ unit->hci_rxint = NULL;
+ }
+#endif
+
+ (*unit->hci_if->disable)(unit->hci_dev);
+ unit->hci_flags &= ~BTF_RUNNING;
/*
* close down any links, take care to close SCO first since
@@ -191,6 +246,8 @@ hci_disable(struct hci_unit *unit)
while ((memo = LIST_FIRST(&unit->hci_memos)) != NULL)
hci_memo_free(memo);
+ /* (no need to hold hci_devlock, the driver is disabled) */
+
IF_PURGE(&unit->hci_eventq);
unit->hci_eventqlen = 0;
@@ -200,10 +257,7 @@ hci_disable(struct hci_unit *unit)
IF_PURGE(&unit->hci_scorxq);
unit->hci_scorxqlen = 0;
- IF_PURGE(&unit->hci_cmdq);
IF_PURGE(&unit->hci_cmdwait);
- IF_PURGE(&unit->hci_acltxq);
- IF_PURGE(&unit->hci_scotxq);
IF_PURGE(&unit->hci_scodone);
}
@@ -243,7 +297,7 @@ hci_send_cmd(struct hci_unit *unit, uint16_t opcode, void *buf, uint8_t len)
p->opcode = htole16(opcode);
p->length = len;
m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
- M_SETCTX(m, NULL);
+ M_SETCTX(m, NULL); /* XXX is this needed? */
if (len) {
KASSERT(buf != NULL);
@@ -255,7 +309,7 @@ hci_send_cmd(struct hci_unit *unit, uint16_t opcode, void *buf, uint8_t len)
}
}
- DPRINTFN(2, "(%s) opcode (%3.3x|%4.4x)\n", unit->hci_devname,
+ DPRINTFN(2, "(%s) opcode (%3.3x|%4.4x)\n", device_xname(unit->hci_dev),
HCI_OGF(opcode), HCI_OCF(opcode));
/* and send it on */
@@ -278,19 +332,19 @@ hci_intr(void *arg)
{
struct hci_unit *unit = arg;
struct mbuf *m;
- int s;
another:
- s = splraiseipl(unit->hci_ipl);
+ mtx_enter(&unit->hci_devlock);
if (unit->hci_eventqlen > 0) {
IF_DEQUEUE(&unit->hci_eventq, m);
unit->hci_eventqlen--;
+ mtx_leave(&unit->hci_devlock);
+
KASSERT(m != NULL);
- splx(s);
DPRINTFN(10, "(%s) recv event, len = %d\n",
- unit->hci_devname, m->m_pkthdr.len);
+ device_xname(unit->hci_dev), m->m_pkthdr.len);
m->m_flags |= M_LINK0; /* mark incoming packet */
hci_mtap(m, unit);
@@ -302,11 +356,12 @@ another:
if (unit->hci_scorxqlen > 0) {
IF_DEQUEUE(&unit->hci_scorxq, m);
unit->hci_scorxqlen--;
+ mtx_leave(&unit->hci_devlock);
+
KASSERT(m != NULL);
- splx(s);
DPRINTFN(10, "(%s) recv SCO, len = %d\n",
- unit->hci_devname, m->m_pkthdr.len);
+ device_xname(unit->hci_dev), m->m_pkthdr.len);
m->m_flags |= M_LINK0; /* mark incoming packet */
hci_mtap(m, unit);
@@ -318,11 +373,12 @@ another:
if (unit->hci_aclrxqlen > 0) {
IF_DEQUEUE(&unit->hci_aclrxq, m);
unit->hci_aclrxqlen--;
+ mtx_leave(&unit->hci_devlock);
+
KASSERT(m != NULL);
- splx(s);
DPRINTFN(10, "(%s) recv ACL, len = %d\n",
- unit->hci_devname, m->m_pkthdr.len);
+ device_xname(unit->hci_dev), m->m_pkthdr.len);
m->m_flags |= M_LINK0; /* mark incoming packet */
hci_mtap(m, unit);
@@ -334,10 +390,11 @@ another:
IF_DEQUEUE(&unit->hci_scodone, m);
if (m != NULL) {
struct hci_link *link;
- splx(s);
+
+ mtx_leave(&unit->hci_devlock);
DPRINTFN(11, "(%s) complete SCO\n",
- unit->hci_devname);
+ device_xname(unit->hci_dev));
TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
if (link == M_GETCTX(m, struct hci_link *)) {
@@ -352,7 +409,7 @@ another:
goto another;
}
- splx(s);
+ mtx_leave(&unit->hci_devlock);
DPRINTFN(10, "done\n");
}
@@ -361,62 +418,86 @@ another:
*
* IO routines
*
- * input & complete routines will be called from device driver
- * (at unit->hci_ipl)
+ * input & complete routines will be called from device drivers,
+ * possibly in interrupt context. We return success or failure to
+ * enable proper accounting but we own the mbuf.
*/
-void
+int
hci_input_event(struct hci_unit *unit, struct mbuf *m)
{
+ int rv;
+
+ mtx_enter(&unit->hci_devlock);
+
if (unit->hci_eventqlen > hci_eventq_max) {
- DPRINTF("(%s) dropped event packet.\n", unit->hci_devname);
- unit->hci_stats.err_rx++;
+ DPRINTF("(%s) dropped event packet.\n", device_xname(unit->hci_dev));
m_freem(m);
+ rv = 0;
} else {
unit->hci_eventqlen++;
IF_ENQUEUE(&unit->hci_eventq, m);
schednetisr(NETISR_BT);
+ rv = 1;
}
+
+ mtx_leave(&unit->hci_devlock);
+ return rv;
}
-void
+int
hci_input_acl(struct hci_unit *unit, struct mbuf *m)
{
+ int rv;
+
+ mtx_enter(&unit->hci_devlock);
+
if (unit->hci_aclrxqlen > hci_aclrxq_max) {
- DPRINTF("(%s) dropped ACL packet.\n", unit->hci_devname);
- unit->hci_stats.err_rx++;
+ DPRINTF("(%s) dropped ACL packet.\n", device_xname(unit->hci_dev));
m_freem(m);
+ rv = 0;
} else {
unit->hci_aclrxqlen++;
IF_ENQUEUE(&unit->hci_aclrxq, m);
schednetisr(NETISR_BT);
+ rv = 1;
}
+
+ mtx_leave(&unit->hci_devlock);
+ return rv;
}
-void
+int
hci_input_sco(struct hci_unit *unit, struct mbuf *m)
{
+ int rv;
+
+ mtx_enter(&unit->hci_devlock);
+
if (unit->hci_scorxqlen > hci_scorxq_max) {
- DPRINTF("(%s) dropped SCO packet.\n", unit->hci_devname);
- unit->hci_stats.err_rx++;
+ DPRINTF("(%s) dropped SCO packet.\n", device_xname(unit->hci_dev));
m_freem(m);
+ rv = 0;
} else {
unit->hci_scorxqlen++;
IF_ENQUEUE(&unit->hci_scorxq, m);
schednetisr(NETISR_BT);
+ rv = 1;
}
+
+ mtx_leave(&unit->hci_devlock);
+ return rv;
}
void
hci_output_cmd(struct hci_unit *unit, struct mbuf *m)
{
void *arg;
- int s;
hci_mtap(m, unit);
- DPRINTFN(10, "(%s) num_cmd_pkts=%d\n", unit->hci_devname,
- unit->hci_num_cmd_pkts);
+ DPRINTFN(10, "(%s) num_cmd_pkts=%d\n",
+ device_xname(unit->hci_dev), unit->hci_num_cmd_pkts);
unit->hci_num_cmd_pkts--;
@@ -428,57 +509,52 @@ hci_output_cmd(struct hci_unit *unit, struct mbuf *m)
if (arg != NULL)
hci_drop(arg);
- s = splraiseipl(unit->hci_ipl);
- IF_ENQUEUE(&unit->hci_cmdq, m);
- if ((unit->hci_flags & BTF_XMIT_CMD) == 0)
- (*unit->hci_start_cmd)(unit);
-
- splx(s);
+ (*unit->hci_if->output_cmd)(unit->hci_dev, m);
}
void
hci_output_acl(struct hci_unit *unit, struct mbuf *m)
{
- int s;
hci_mtap(m, unit);
- DPRINTFN(10, "(%s) num_acl_pkts=%d\n", unit->hci_devname,
- unit->hci_num_acl_pkts);
+ DPRINTFN(10, "(%s) num_acl_pkts=%d\n",
+ device_xname(unit->hci_dev), unit->hci_num_acl_pkts);
unit->hci_num_acl_pkts--;
-
- s = splraiseipl(unit->hci_ipl);
- IF_ENQUEUE(&unit->hci_acltxq, m);
- if ((unit->hci_flags & BTF_XMIT_ACL) == 0)
- (*unit->hci_start_acl)(unit);
-
- splx(s);
+ (*unit->hci_if->output_acl)(unit->hci_dev, m);
}
void
hci_output_sco(struct hci_unit *unit, struct mbuf *m)
{
- int s;
hci_mtap(m, unit);
- DPRINTFN(10, "(%s) num_sco_pkts=%d\n", unit->hci_devname,
- unit->hci_num_sco_pkts);
+ DPRINTFN(10, "(%s) num_sco_pkts=%d\n",
+ device_xname(unit->hci_dev), unit->hci_num_sco_pkts);
unit->hci_num_sco_pkts--;
-
- s = splraiseipl(unit->hci_ipl);
- IF_ENQUEUE(&unit->hci_scotxq, m);
- if ((unit->hci_flags & BTF_XMIT_SCO) == 0)
- (*unit->hci_start_sco)(unit);
-
- splx(s);
+ (*unit->hci_if->output_sco)(unit->hci_dev, m);
}
-void
+int
hci_complete_sco(struct hci_unit *unit, struct mbuf *m)
{
+
+#ifndef __OpenBSD__
+ if (unit->hci_rxint == NULL) {
+ DPRINTFN(10, "(%s) complete SCO!\n", device_xname(unit->hci_dev));
+ m_freem(m);
+ return 0;
+ }
+#endif
+
+ mtx_enter(&unit->hci_devlock);
+
IF_ENQUEUE(&unit->hci_scodone, m);
schednetisr(NETISR_BT);
+
+ mtx_leave(&unit->hci_devlock);
+ return 1;
}
diff --git a/sys/netbt/l2cap.h b/sys/netbt/l2cap.h
index 227a3527341..3500e38311a 100644
--- a/sys/netbt/l2cap.h
+++ b/sys/netbt/l2cap.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: l2cap.h,v 1.4 2007/06/01 02:46:11 uwe Exp $ */
-/* $NetBSD: l2cap.h,v 1.5 2007/04/21 06:15:23 plunky Exp $ */
+/* $OpenBSD: l2cap.h,v 1.5 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: l2cap.h,v 1.6 2007/11/03 17:20:17 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@@ -55,7 +55,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: l2cap.h,v 1.4 2007/06/01 02:46:11 uwe Exp $
+ * $Id: l2cap.h,v 1.5 2008/02/24 21:34:48 uwe Exp $
* $FreeBSD: src/sys/netgraph/bluetooth/include/l2cap.h,v 1.4 2005/08/31 18:13:23 emax Exp $
*/
diff --git a/sys/netbt/l2cap_lower.c b/sys/netbt/l2cap_lower.c
index ba0c9f4a4bf..f2d6b86c37d 100644
--- a/sys/netbt/l2cap_lower.c
+++ b/sys/netbt/l2cap_lower.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: l2cap_lower.c,v 1.1 2007/05/30 03:42:53 uwe Exp $ */
-/* $NetBSD: l2cap_lower.c,v 1.6 2007/04/21 06:15:23 plunky Exp $ */
+/* $OpenBSD: l2cap_lower.c,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: l2cap_lower.c,v 1.7 2007/11/10 23:12:23 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@@ -31,8 +31,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
@@ -119,7 +117,7 @@ l2cap_recv_frame(struct mbuf *m, struct hci_link *link)
hdr.dcid = letoh16(hdr.dcid);
DPRINTFN(5, "(%s) received packet (%d bytes)\n",
- link->hl_unit->hci_devname, hdr.length);
+ device_xname(link->hl_unit->hci_dev), hdr.length);
if (hdr.length != m->m_pkthdr.len)
goto failed;
@@ -142,7 +140,7 @@ l2cap_recv_frame(struct mbuf *m, struct hci_link *link)
}
DPRINTF("(%s) dropping %d L2CAP data bytes for unknown CID #%d\n",
- link->hl_unit->hci_devname, hdr.length, hdr.dcid);
+ device_xname(link->hl_unit->hci_dev), hdr.length, hdr.dcid);
failed:
m_freem(m);
diff --git a/sys/netbt/l2cap_misc.c b/sys/netbt/l2cap_misc.c
index 583fe70be15..73f65804b0c 100644
--- a/sys/netbt/l2cap_misc.c
+++ b/sys/netbt/l2cap_misc.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: l2cap_misc.c,v 1.2 2007/06/01 02:46:11 uwe Exp $ */
-/* $NetBSD: l2cap_misc.c,v 1.3 2007/04/21 06:15:23 plunky Exp $ */
+/* $OpenBSD: l2cap_misc.c,v 1.3 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: l2cap_misc.c,v 1.5 2007/11/03 17:20:17 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@@ -31,8 +31,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
@@ -87,10 +85,11 @@ l2cap_setmode(struct l2cap_channel *chan)
KASSERT(chan != NULL);
KASSERT(chan->lc_link != NULL);
- DPRINTF("CID #%d, auth %s, encrypt %s, secure %s\n", chan->lc_lcid,
- (chan->lc_mode & L2CAP_LM_AUTH ? "yes" : "no"),
- (chan->lc_mode & L2CAP_LM_ENCRYPT ? "yes" : "no"),
- (chan->lc_mode & L2CAP_LM_SECURE ? "yes" : "no"));
+ DPRINTF("(%s) CID #%d, auth %s, encrypt %s, secure %s\n",
+ device_xname(chan->lc_link->hl_unit->hci_dev), chan->lc_lcid,
+ (chan->lc_mode & L2CAP_LM_AUTH ? "yes" : "no"),
+ (chan->lc_mode & L2CAP_LM_ENCRYPT ? "yes" : "no"),
+ (chan->lc_mode & L2CAP_LM_SECURE ? "yes" : "no"));
if (chan->lc_mode & L2CAP_LM_AUTH)
chan->lc_link->hl_flags |= HCI_LINK_AUTH_REQ;
diff --git a/sys/netbt/l2cap_signal.c b/sys/netbt/l2cap_signal.c
index ea4de934ded..a5874b14baa 100644
--- a/sys/netbt/l2cap_signal.c
+++ b/sys/netbt/l2cap_signal.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: l2cap_signal.c,v 1.2 2007/07/22 21:05:00 gwk Exp $ */
-/* $NetBSD: l2cap_signal.c,v 1.8 2007/05/16 18:34:49 plunky Exp $ */
+/* $OpenBSD: l2cap_signal.c,v 1.3 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: l2cap_signal.c,v 1.9 2007/11/10 23:12:23 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@@ -31,8 +31,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
@@ -83,7 +81,7 @@ l2cap_recv_signal(struct mbuf *m, struct hci_link *link)
goto reject;
DPRINTFN(2, "(%s) code %d, ident %d, len %d\n",
- link->hl_unit->hci_devname,
+ device_xname(link->hl_unit->hci_dev),
cmd.code, cmd.ident, cmd.length);
switch (cmd.code) {
@@ -405,7 +403,7 @@ l2cap_recv_connect_rsp(struct mbuf *m, struct hci_link *link)
}
/*
- * Process Received Config Reqest.
+ * Process Received Config Request.
*/
static void
l2cap_recv_config_req(struct mbuf *m, struct hci_link *link)
@@ -527,13 +525,13 @@ l2cap_recv_config_req(struct mbuf *m, struct hci_link *link)
if (opt.type & L2CAP_OPT_HINT_BIT)
break;
- /* unknown options supercede all else */
+ /* unknown options supersede all else */
if (rp.result != L2CAP_UNKNOWN_OPTION) {
rp.result = L2CAP_UNKNOWN_OPTION;
len = sizeof(rp);
}
- /* ignore if it don't fit */
+ /* ignore if it doesn't fit */
if (len + sizeof(opt) > sizeof(buf))
break;
@@ -902,7 +900,7 @@ l2cap_send_signal(struct hci_link *link, uint8_t code, uint8_t ident,
if (sizeof(l2cap_cmd_hdr_t) + length > link->hl_mtu)
printf("(%s) exceeding L2CAP Signal MTU for link!\n",
- link->hl_unit->hci_devname);
+ device_xname(link->hl_unit->hci_dev));
#endif
m = m_gethdr(M_DONTWAIT, MT_DATA);
@@ -938,7 +936,7 @@ l2cap_send_signal(struct hci_link *link, uint8_t code, uint8_t ident,
m->m_len = MIN(length, MHLEN);
DPRINTFN(2, "(%s) code %d, ident %d, len %d\n",
- link->hl_unit->hci_devname, code, ident, length);
+ device_xname(link->hl_unit->hci_dev), code, ident, length);
return hci_acl_send(m, link, NULL);
}
diff --git a/sys/netbt/rfcomm.h b/sys/netbt/rfcomm.h
index 5af53ac4063..2980c3ca762 100644
--- a/sys/netbt/rfcomm.h
+++ b/sys/netbt/rfcomm.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: rfcomm.h,v 1.1 2007/06/01 02:46:11 uwe Exp $ */
-/* $NetBSD: rfcomm.h,v 1.3 2007/04/21 06:15:23 plunky Exp $ */
+/* $OpenBSD: rfcomm.h,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: rfcomm.h,v 1.6 2007/11/20 20:25:58 plunky Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -56,7 +56,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: rfcomm.h,v 1.1 2007/06/01 02:46:11 uwe Exp $
+ * $Id: rfcomm.h,v 1.2 2008/02/24 21:34:48 uwe Exp $
* $FreeBSD: src/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h,v 1.4 2005/01/11 01:39:53 emax Exp $
*/
@@ -78,6 +78,7 @@
#define RFCOMM_CREDITS_MAX 255 /* in any single packet */
#define RFCOMM_CREDITS_DEFAULT 7 /* default initial value */
+#define RFCOMM_CHANNEL_ANY 0
#define RFCOMM_CHANNEL_MIN 1
#define RFCOMM_CHANNEL_MAX 30
diff --git a/sys/netbt/rfcomm_dlc.c b/sys/netbt/rfcomm_dlc.c
index 0cdcaf299be..2d7a7b40374 100644
--- a/sys/netbt/rfcomm_dlc.c
+++ b/sys/netbt/rfcomm_dlc.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: rfcomm_dlc.c,v 1.1 2007/06/01 02:46:12 uwe Exp $ */
-/* $NetBSD: rfcomm_dlc.c,v 1.3 2007/04/21 06:15:23 plunky Exp $ */
+/* $OpenBSD: rfcomm_dlc.c,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: rfcomm_dlc.c,v 1.4 2007/11/03 17:20:17 plunky Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -32,8 +32,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
diff --git a/sys/netbt/rfcomm_session.c b/sys/netbt/rfcomm_session.c
index 0852c9f0996..b05c9257975 100644
--- a/sys/netbt/rfcomm_session.c
+++ b/sys/netbt/rfcomm_session.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: rfcomm_session.c,v 1.2 2007/09/17 01:33:33 krw Exp $ */
-/* $NetBSD: rfcomm_session.c,v 1.9 2007/04/21 06:15:23 plunky Exp $ */
+/* $OpenBSD: rfcomm_session.c,v 1.3 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: rfcomm_session.c,v 1.12 2008/01/31 19:30:23 plunky Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -32,8 +32,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
diff --git a/sys/netbt/rfcomm_socket.c b/sys/netbt/rfcomm_socket.c
index 6484bb8cb32..72cb1e42c6c 100644
--- a/sys/netbt/rfcomm_socket.c
+++ b/sys/netbt/rfcomm_socket.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: rfcomm_socket.c,v 1.1 2007/06/01 02:46:12 uwe Exp $ */
-/* $NetBSD: rfcomm_socket.c,v 1.7 2007/04/21 06:15:23 plunky Exp $ */
+/* $OpenBSD: rfcomm_socket.c,v 1.2 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: rfcomm_socket.c,v 1.8 2007/10/15 18:04:34 plunky Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -32,8 +32,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
/* load symbolic names */
#ifdef BLUETOOTH_DEBUG
#define PRUREQUESTS
@@ -131,18 +129,20 @@ rfcomm_usrreq(struct socket *up, int req, struct mbuf *m,
* Since we have nothing to add, we attach the DLC
* structure directly to our PCB pointer.
*/
- err = rfcomm_attach((struct rfcomm_dlc **)&up->so_pcb,
- &rfcomm_proto, up);
+ err = soreserve(up, rfcomm_sendspace, rfcomm_recvspace);
if (err)
return err;
- err = soreserve(up, rfcomm_sendspace, rfcomm_recvspace);
+ err = rfcomm_attach((struct rfcomm_dlc **)&up->so_pcb,
+ &rfcomm_proto, up);
if (err)
return err;
err = rfcomm_rcvd(up->so_pcb, sbspace(&up->so_rcv));
- if (err)
+ if (err) {
+ rfcomm_detach((struct rfcomm_dlc **)&up->so_pcb);
return err;
+ }
return 0;
}
diff --git a/sys/netbt/rfcomm_upper.c b/sys/netbt/rfcomm_upper.c
index da606b2741b..741b229d671 100644
--- a/sys/netbt/rfcomm_upper.c
+++ b/sys/netbt/rfcomm_upper.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: rfcomm_upper.c,v 1.3 2007/10/01 16:39:30 krw Exp $ */
-/* $NetBSD: rfcomm_upper.c,v 1.6 2007/04/21 06:15:23 plunky Exp $ */
+/* $OpenBSD: rfcomm_upper.c,v 1.4 2008/02/24 21:34:48 uwe Exp $ */
+/* $NetBSD: rfcomm_upper.c,v 1.10 2007/11/20 20:25:57 plunky Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@@ -32,8 +32,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
@@ -302,20 +300,23 @@ rfcomm_detach(struct rfcomm_dlc **handle)
*
* This DLC is a listener. We look for an existing listening session
* with a matching address to attach to or else create a new one on
- * the listeners list.
+ * the listeners list. If the ANY channel is given, allocate the first
+ * available for the session.
*/
int
rfcomm_listen(struct rfcomm_dlc *dlc)
{
- struct rfcomm_session *rs, *any, *best;
+ struct rfcomm_session *rs;
+ struct rfcomm_dlc *used;
struct sockaddr_bt addr;
- int err;
+ int err, channel;
if (dlc->rd_state != RFCOMM_DLC_CLOSED)
return EISCONN;
- if (dlc->rd_laddr.bt_channel < RFCOMM_CHANNEL_MIN
- || dlc->rd_laddr.bt_channel > RFCOMM_CHANNEL_MAX)
+ if (dlc->rd_laddr.bt_channel != RFCOMM_CHANNEL_ANY
+ && (dlc->rd_laddr.bt_channel < RFCOMM_CHANNEL_MIN
+ || dlc->rd_laddr.bt_channel > RFCOMM_CHANNEL_MAX))
return EADDRNOTAVAIL;
if (dlc->rd_laddr.bt_psm == L2CAP_PSM_ANY)
@@ -325,7 +326,6 @@ rfcomm_listen(struct rfcomm_dlc *dlc)
|| L2CAP_PSM_INVALID(dlc->rd_laddr.bt_psm)))
return EADDRNOTAVAIL;
- any = best = NULL;
LIST_FOREACH(rs, &rfcomm_session_listen, rs_next) {
l2cap_sockaddr(rs->rs_l2cap, &addr);
@@ -333,13 +333,9 @@ rfcomm_listen(struct rfcomm_dlc *dlc)
continue;
if (bdaddr_same(&dlc->rd_laddr.bt_bdaddr, &addr.bt_bdaddr))
- best = rs;
-
- if (bdaddr_any(&addr.bt_bdaddr))
- any = rs;
+ break;
}
- rs = best ? best : any;
if (rs == NULL) {
rs = rfcomm_session_alloc(&rfcomm_session_listen,
&dlc->rd_laddr);
@@ -355,6 +351,24 @@ rfcomm_listen(struct rfcomm_dlc *dlc)
}
}
+ if (dlc->rd_laddr.bt_channel == RFCOMM_CHANNEL_ANY) {
+ channel = RFCOMM_CHANNEL_MIN;
+ used = LIST_FIRST(&rs->rs_dlcs);
+
+ while (used != NULL) {
+ if (used->rd_laddr.bt_channel == channel) {
+ if (channel++ == RFCOMM_CHANNEL_MAX)
+ return EADDRNOTAVAIL;
+
+ used = LIST_FIRST(&rs->rs_dlcs);
+ } else {
+ used = LIST_NEXT(used, rd_next);
+ }
+ }
+
+ dlc->rd_laddr.bt_channel = channel;
+ }
+
dlc->rd_session = rs;
dlc->rd_state = RFCOMM_DLC_LISTEN;
LIST_INSERT_HEAD(&rs->rs_dlcs, dlc, rd_next);