diff options
author | Uwe Stuehler <uwe@cvs.openbsd.org> | 2008-02-24 21:34:49 +0000 |
---|---|---|
committer | Uwe Stuehler <uwe@cvs.openbsd.org> | 2008-02-24 21:34:49 +0000 |
commit | 0f57bfa559ae850def03153006105883b91d362e (patch) | |
tree | a7fb0a4d79aacf2db2bdf4eef6f744e5a9ecbf61 /sys | |
parent | 98450358fa8b17b64cdf2ba62762e40965362f3c (diff) |
Sync sys/netbt with NetBSD
ok deraadt@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/sdmmc/sbt.c | 199 | ||||
-rw-r--r-- | sys/dev/usb/ubt.c | 298 | ||||
-rw-r--r-- | sys/netbt/bluetooth.h | 10 | ||||
-rw-r--r-- | sys/netbt/hci.h | 521 | ||||
-rw-r--r-- | sys/netbt/hci_event.c | 328 | ||||
-rw-r--r-- | sys/netbt/hci_ioctl.c | 30 | ||||
-rw-r--r-- | sys/netbt/hci_link.c | 92 | ||||
-rw-r--r-- | sys/netbt/hci_misc.c | 43 | ||||
-rw-r--r-- | sys/netbt/hci_socket.c | 421 | ||||
-rw-r--r-- | sys/netbt/hci_unit.c | 250 | ||||
-rw-r--r-- | sys/netbt/l2cap.h | 6 | ||||
-rw-r--r-- | sys/netbt/l2cap_lower.c | 10 | ||||
-rw-r--r-- | sys/netbt/l2cap_misc.c | 15 | ||||
-rw-r--r-- | sys/netbt/l2cap_signal.c | 18 | ||||
-rw-r--r-- | sys/netbt/rfcomm.h | 7 | ||||
-rw-r--r-- | sys/netbt/rfcomm_dlc.c | 6 | ||||
-rw-r--r-- | sys/netbt/rfcomm_session.c | 6 | ||||
-rw-r--r-- | sys/netbt/rfcomm_socket.c | 16 | ||||
-rw-r--r-- | sys/netbt/rfcomm_upper.c | 44 |
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); |