Sync Bluetooth stack with NetBSD.
authorHasso Tepper <hasso@dragonflybsd.org>
Tue, 18 Mar 2008 13:41:42 +0000 (13:41 +0000)
committerHasso Tepper <hasso@dragonflybsd.org>
Tue, 18 Mar 2008 13:41:42 +0000 (13:41 +0000)
Obtained-from: NetBSD via OpenBSD

25 files changed:
sys/dev/usbmisc/ubt/ubt.c
sys/netbt/bluetooth.h
sys/netbt/bt_input.c
sys/netbt/bt_proto.c
sys/netbt/hci.h
sys/netbt/hci_event.c
sys/netbt/hci_ioctl.c
sys/netbt/hci_link.c
sys/netbt/hci_misc.c
sys/netbt/hci_socket.c
sys/netbt/hci_unit.c
sys/netbt/l2cap.h
sys/netbt/l2cap_lower.c
sys/netbt/l2cap_misc.c
sys/netbt/l2cap_signal.c
sys/netbt/l2cap_socket.c
sys/netbt/l2cap_upper.c
sys/netbt/rfcomm.h
sys/netbt/rfcomm_dlc.c
sys/netbt/rfcomm_session.c
sys/netbt/rfcomm_socket.c
sys/netbt/rfcomm_upper.c
sys/netbt/sco.h
sys/netbt/sco_socket.c
sys/netbt/sco_upper.c

index 03d1d2a..de1da4b 100644 (file)
@@ -1,5 +1,6 @@
-/* $OpenBSD: ubt.c,v 1.9 2007/10/11 18:33:14 deraadt Exp $ */
-/* $DragonFly: src/sys/dev/usbmisc/ubt/ubt.c,v 1.2 2008/02/03 06:27:48 hasso Exp $ */
+/* $DragonFly: src/sys/dev/usbmisc/ubt/ubt.c,v 1.3 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/dev/usb/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.
@@ -165,6 +166,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;
@@ -172,6 +174,8 @@ struct ubt_softc {
        /* Commands (control) */
        usbd_xfer_handle         sc_cmd_xfer;
        u_char                  *sc_cmd_buf;
+       int                      sc_cmd_busy;   /* write active */
+       struct ifqueue           sc_cmd_queue;  /* output queue */
 
        /* Events (interrupt) */
        int                      sc_evt_addr;   /* endpoint address */
@@ -191,6 +195,8 @@ struct ubt_softc {
        usbd_pipe_handle         sc_aclwr_pipe; /* write pipe */
        usbd_xfer_handle         sc_aclwr_xfer; /* write xfer */
        u_char                  *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 */
@@ -211,9 +217,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;
@@ -225,18 +234,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);
@@ -252,6 +264,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);
+
 static device_probe_t ubt_match;
 static device_attach_t ubt_attach;
 static device_detach_t ubt_detach;
@@ -279,6 +293,15 @@ MODULE_DEPEND(ubt, bthub, 1, 1, 1);
 #endif
 MODULE_DEPEND(ubt, usb, 1, 1, 1);
 
+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,
+};
+
 static int ubt_set_isoc_config(struct ubt_softc *);
 static int ubt_sysctl_config(SYSCTL_HANDLER_ARGS);
 static void ubt_abortdealloc(struct ubt_softc *);
@@ -292,15 +315,13 @@ static void ubt_abortdealloc(struct ubt_softc *);
  * to the ubt_ignore list.
  */
 static const struct usb_devno ubt_ignore[] = {
-       { USB_DEVICE(0x0a5c, 0x2000) }, /* Braodcom BCM2033 */
-       { USB_DEVICE(0x0a5c, 0x2033) }, /* Broadcom BCM2033 (no fw) */
+       { USB_DEVICE(0x0a5c, 0x2033) }, /* Broadcom BCM2033 */
        { 0, 0 }                        /* end of list */
 };
 
 static int
 ubt_match(device_t self)
 {
-
        struct usb_attach_arg *uaa = device_get_ivars(self);
        usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
 
@@ -328,7 +349,7 @@ ubt_attach(device_t self)
        uint8_t count, i;
 
        DPRINTFN(50, "ubt_attach: sc=%p\n", sc);
-       
+
        sc->sc_udev = uaa->device;
        sc->sc_dev = self;
 
@@ -349,7 +370,6 @@ ubt_attach(device_t self)
         *      2) Bulk IN endpoint to receive ACL data
         *      3) Bulk OUT endpoint to send ACL data
         */
-        
        err = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
        if (err) {
                kprintf("%s: Could not get interface 0 handle %s (%d)\n",
@@ -415,11 +435,10 @@ ubt_attach(device_t self)
         * via a sysctl variable. We select config 0 to start, which
         * means that no SCO data will be available.
         */
-        
        err = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
        if (err) {
                kprintf("%s: Could not get interface 1 handle %s (%d)\n",
-                               device_get_nameunit(sc->sc_dev), usbd_errstr(err), err);
+                   device_get_nameunit(sc->sc_dev), usbd_errstr(err), err);
 
                return ENXIO;
        }
@@ -435,7 +454,6 @@ ubt_attach(device_t self)
        sc->sc_alt_config = usbd_get_no_alts(cd, 1);
 
        /* set initial config */
-       
        err = ubt_set_isoc_config(sc);
        if (err) {
                kprintf("%s: ISOC config failed\n",
@@ -444,23 +462,12 @@ ubt_attach(device_t self)
                return ENXIO;
        }
 
-       /* Attach HCI host's software */
-       
-       /* Fill HCI part of struct with data */
-       sc->sc_unit.hci_softc = self;
-       sc->sc_unit.hci_devname = device_get_nameunit(sc->sc_dev);
-       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;
-       
-       /* Attach to HCI software stack */
-       
-       hci_attach(&sc->sc_unit);
+       /* Attach HCI */
+       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;
 
        sysctl_ctx_init(&sc->sysctl_ctx);
@@ -506,8 +513,10 @@ ubt_detach(device_t self)
                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.
@@ -516,11 +525,9 @@ ubt_detach(device_t self)
         * call ubt_abortdealloc(), but lets be sure since doing it twice
         * wont cause an error.
         */
-
        ubt_abortdealloc(sc);
 
        /* wait for all processes to finish */
-       
        if (sc->sc_refcnt-- > 0)
                usb_detach_wait(sc->sc_dev);
 
@@ -654,7 +661,7 @@ ubt_sysctl_config(SYSCTL_HANDLER_ARGS)
                return EINVAL;
 
        /* This may not change when the unit is enabled */
-       if (sc->sc_unit.hci_flags & BTF_RUNNING)
+       if (sc->sc_enabled)
                return EBUSY;
 
        sc->sc_config = t;
@@ -667,6 +674,7 @@ ubt_abortdealloc(struct ubt_softc *sc)
        int i;
 
        DPRINTFN(1, "sc=%p\n", sc);
+
        crit_enter();
        /* Abort all pipes */
        if (sc->sc_evt_pipe != NULL) {
@@ -748,6 +756,12 @@ ubt_abortdealloc(struct ubt_softc *sc)
                m_freem(sc->sc_scowr_mbuf);
                sc->sc_scowr_mbuf = NULL;
        }
+
+       /* Empty mbuf queues */
+       IF_DRAIN(&sc->sc_cmd_queue);
+       IF_DRAIN(&sc->sc_aclwr_queue);
+       IF_DRAIN(&sc->sc_scowr_queue);
+
        crit_exit();    
 }
 
@@ -758,19 +772,20 @@ 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 = device_get_softc(unit->hci_softc);
+       struct ubt_softc *sc = device_get_softc(self);
        usbd_status err;
        int i, error;
 
        DPRINTFN(1, "%s: sc=%p\n", __func__, sc);
 
-       if (unit->hci_flags & BTF_RUNNING)
+       if (sc->sc_enabled)
                return 0;
 
+       crit_enter();
+
        /* Events */
-       
        sc->sc_evt_buf = kmalloc(UBT_BUFSIZ_EVENT, M_USBDEV, M_NOWAIT);
        if (sc->sc_evt_buf == NULL) {
                error = ENOMEM;
@@ -793,7 +808,6 @@ ubt_enable(struct hci_unit *unit)
        }
 
        /* Commands */
-       
        sc->sc_cmd_xfer = usbd_alloc_xfer(sc->sc_udev);
        if (sc->sc_cmd_xfer == NULL) {
                kprintf("can't allocate cmd_xfer\n");
@@ -806,9 +820,9 @@ 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,
                                USBD_EXCLUSIVE_USE, &sc->sc_aclrd_pipe);
        if (err != USBD_NORMAL_COMPLETION) {
@@ -832,7 +846,6 @@ ubt_enable(struct hci_unit *unit)
        ubt_recv_acl_start(sc);
 
        /* ACL write */
-       
        err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclwr_addr,
                                USBD_EXCLUSIVE_USE, &sc->sc_aclwr_pipe);
        if (err != USBD_NORMAL_COMPLETION) {
@@ -852,9 +865,9 @@ ubt_enable(struct hci_unit *unit)
                error = ENOMEM;
                goto bad;
        }
+       sc->sc_aclwr_busy = 0;
 
        /* SCO read */
-       
        if (sc->sc_scord_size > 0) {
                err = usbd_open_pipe(sc->sc_iface1, sc->sc_scord_addr,
                                        USBD_EXCLUSIVE_USE, &sc->sc_scord_pipe);
@@ -882,7 +895,6 @@ ubt_enable(struct hci_unit *unit)
        }
 
        /* SCO write */
-       
        if (sc->sc_scowr_size > 0) {
                err = usbd_open_pipe(sc->sc_iface1, sc->sc_scowr_addr,
                                        USBD_EXCLUSIVE_USE, &sc->sc_scowr_pipe);
@@ -906,38 +918,53 @@ 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;
+       crit_exit();
        return 0;
 
 bad:
-       kprintf("ubt_enable: something going wrong... :( \n");
        ubt_abortdealloc(sc);
+       crit_exit();
        return error;
 }
 
 void
-ubt_disable(struct hci_unit *unit)
+ubt_disable(struct device *self)
 {
-       struct ubt_softc *sc = device_get_softc(unit->hci_softc);
+       struct ubt_softc *sc = device_get_softc(self);
        
        DPRINTFN(1, "sc=%p\n", sc);
 
-       if ((unit->hci_flags & BTF_RUNNING) == 0)
+       if (sc->sc_enabled == 0)
                return;
 
        ubt_abortdealloc(sc);
+       sc->sc_enabled = 0;
+}
+
+void
+ubt_xmit_cmd(struct device *self, struct mbuf *m)
+{
+       struct ubt_softc *sc = device_get_softc(self);
+
+       KKASSERT(sc->sc_enabled);
+
+       crit_enter();
+       IF_ENQUEUE(&sc->sc_cmd_queue, m);
 
-       unit->hci_flags &= ~BTF_RUNNING;
+       if (sc->sc_cmd_busy == 0)
+               ubt_xmit_cmd_start(sc);
+
+       crit_exit();
 }
 
 void
-ubt_xmit_cmd_start(struct hci_unit *unit)
+ubt_xmit_cmd_start(struct ubt_softc *sc)
 {
-       struct ubt_softc *sc = device_get_softc(unit->hci_softc);
        usb_device_request_t req;
        usbd_status status;
        struct mbuf *m;
@@ -946,17 +973,17 @@ ubt_xmit_cmd_start(struct hci_unit *unit)
        if (sc->sc_dying)
                return;
 
-
-
-       if (IF_QEMPTY(&unit->hci_cmdq)) 
+       if (IF_QEMPTY(&sc->sc_cmd_queue))
                return;
-       IF_DEQUEUE(&unit->hci_cmdq, m);
+
+       IF_DEQUEUE(&sc->sc_cmd_queue, m);
+       KKASSERT(m != NULL);
        DPRINTFN(15, " %s: xmit CMD packet (%d bytes)\n",
-                       unit->hci_devname, m->m_pkthdr.len);
+           device_get_nameunit(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);
@@ -968,7 +995,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,
@@ -984,7 +1011,7 @@ ubt_xmit_cmd_start(struct hci_unit *unit)
                DPRINTF("usbd_transfer status=%s (%d)\n",
                        usbd_errstr(status), status);
                sc->sc_refcnt--;
-               unit->hci_flags &= ~BTF_XMIT_CMD;
+               sc->sc_cmd_busy = 0;
        }
        
 }
@@ -993,14 +1020,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 = device_get_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);
+           device_get_nameunit(sc->sc_dev), 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);
@@ -1016,22 +1042,36 @@ ubt_xmit_cmd_complete(usbd_xfer_handle xfer,
        if (status != USBD_NORMAL_COMPLETION) {
                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);
+       sc->sc_stats.cmd_tx++;
+       sc->sc_stats.byte_tx += count;
 
-       unit->hci_stats.cmd_tx++;
-       unit->hci_stats.byte_tx += count;
+       ubt_xmit_cmd_start(sc);
+}
+
+void
+ubt_xmit_acl(struct device *self, struct mbuf *m)
+{
+       struct ubt_softc *sc = device_get_softc(self);
 
-       ubt_xmit_cmd_start(unit);
+       KKASSERT(sc->sc_enabled);
+
+       crit_enter();
+       IF_ENQUEUE(&sc->sc_aclwr_queue, m);
+
+       if (sc->sc_aclwr_busy == 0)
+               ubt_xmit_acl_start(sc);
+
+       crit_exit();
 }
 
 void
-ubt_xmit_acl_start(struct hci_unit *unit)
+ubt_xmit_acl_start(struct ubt_softc *sc)
 {
-       struct ubt_softc *sc = device_get_softc(unit->hci_softc);
        struct mbuf *m;
        usbd_status status;
        int len;
@@ -1040,21 +1080,22 @@ ubt_xmit_acl_start(struct hci_unit *unit)
                return;
 
 
-       if (IF_QEMPTY(&unit->hci_acltxq)) 
+       if (IF_QEMPTY(&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);
+       KKASSERT(m != NULL);
 
        DPRINTFN(15, "%s: xmit ACL packet (%d bytes)\n",
-                       unit->hci_devname, m->m_pkthdr.len);
+           device_get_nameunit(sc->sc_dev), 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);
+                   device_get_nameunit(sc->sc_dev), len, UBT_BUFSIZ_ACL);
 
                len = UBT_BUFSIZ_ACL;
        }
@@ -1062,12 +1103,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,
@@ -1083,7 +1124,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;
        }
        
 }
@@ -1092,13 +1133,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 = device_get_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);
+           device_get_nameunit(sc->sc_dev), 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);
@@ -1112,7 +1152,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);
@@ -1120,14 +1160,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 = device_get_softc(self);
+
+       KKASSERT(sc->sc_enabled);
+
+       crit_enter();
+       IF_ENQUEUE(&sc->sc_scowr_queue, m);
+
+       if (sc->sc_scowr_busy == 0)
+               ubt_xmit_sco_start(sc);
+
+       crit_exit();
+}
+
+void
+ubt_xmit_sco_start(struct ubt_softc *sc)
 {
-       struct ubt_softc *sc = device_get_softc(unit->hci_softc);
        int i;
 
        if (sc->sc_dying || sc->sc_scowr_size == 0)
@@ -1168,7 +1223,7 @@ ubt_xmit_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
        while (space > 0) {
                if (m == NULL) {
                        crit_enter();
-                       IF_DEQUEUE(&sc->sc_unit.hci_scotxq, m);
+                       IF_DEQUEUE(&sc->sc_scowr_queue, m);
                        crit_exit();
                        if (m == NULL)
                                break;
@@ -1189,8 +1244,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;
                }
        }
@@ -1203,8 +1260,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;
 
        /*
@@ -1247,7 +1304,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;
                }
 
@@ -1267,7 +1324,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);
@@ -1275,7 +1332,7 @@ ubt_xmit_sco_complete(usbd_xfer_handle xfer,
                        return;
        }
 
-       ubt_xmit_sco_start(&sc->sc_unit);
+       ubt_xmit_sco_start(sc);
 }
 
 /*
@@ -1319,19 +1376,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
@@ -1403,7 +1457,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);
@@ -1414,16 +1468,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++;
                }
        }
 
@@ -1496,7 +1548,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);
@@ -1513,7 +1565,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,
@@ -1550,7 +1602,7 @@ ubt_recv_sco_complete(usbd_xfer_handle xfer,
                                        kprintf("%s: out of memory (xfer halted)\n",
                                                device_get_nameunit(sc->sc_dev));
 
-                                       sc->sc_unit.hci_stats.err_rx++;
+                                       sc->sc_stats.err_rx++;
                                        return;         /* lost sync */
                                }
 
@@ -1583,8 +1635,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;
                                }
                        }
@@ -1601,3 +1655,17 @@ 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 = device_get_softc(self);
+
+       crit_enter();
+       memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
+
+       if (flush)
+               memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
+
+       crit_exit();
+}
index e27e766..42d8beb 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/bluetooth.h,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/bluetooth.h,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -141,9 +141,9 @@ extern int bluetooth_debug;
 # define UNKNOWN(value)                        \
                kprintf("%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 */
 
 #define sbspace(sb) \
index 7a24f09..8f89310 100644 (file)
@@ -1,5 +1,5 @@
+/* $DragonFly: src/sys/netbt/bt_input.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
 /* $OpenBSD: bt_input.c,v 1.5 2007/06/24 20:55:27 uwe Exp $ */
-/* $DragonFly: src/sys/netbt/bt_input.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
 
 /*
  * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
index 3c61d9a..1ae6308 100644 (file)
@@ -1,5 +1,5 @@
+/* $DragonFly: src/sys/netbt/bt_proto.c,v 1.3 2008/03/18 13:41:42 hasso Exp $ */
 /* $OpenBSD: bt_proto.c,v 1.4 2007/06/24 20:55:27 uwe Exp $ */
-/* $DragonFly: src/sys/netbt/bt_proto.c,v 1.2 2008/02/01 14:18:58 hasso Exp $ */
 
 /*
  * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
index 0dbc400..5885400 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/hci.h,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/hci.h,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
+ * $Id: hci.h,v 1.22 2008/02/10 17:40:54 plunky 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 +78,8 @@
 
 #include <netbt/bluetooth.h>
 
+#include <sys/lock.h>
+
 /**************************************************************************
  **************************************************************************
  **                   Common defines and types (HCI)
 #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 --------------------*/
 #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 +488,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 +544,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 +567,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 +606,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 +628,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 +638,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 +722,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 +872,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 +955,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 +993,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 +1041,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 +1056,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 +1068,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 +1084,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 +1140,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 +1158,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 +1188,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 +1210,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 +1282,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 +1404,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 +1427,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 +1516,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 +1637,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 +1650,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 +1814,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 +1859,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 +1898,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 +1925,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 +1941,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 +2018,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 +2059,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 +2095,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 +2129,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 +2336,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 +2348,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 +2398,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,21 +2435,36 @@ 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);
+};
+
 /*
  * The Bluetooth HCI device unit structure
  */
 struct hci_unit {
-       device_t        hci_softc;              /* ptr to device softc */
+       struct device   *hci_dev;               /* bthci handle */
 #if 0 /* not yet */
-       device_t        hci_bthub;              /* bthub(4) handle */
+       device_t         hci_bthub;             /* bthub(4) handle */
 #endif
+       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 */
 
@@ -2118,6 +2475,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 */
@@ -2128,24 +2487,9 @@ 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 */
+       void                    *hci_rxint;     /* receive interrupt cookie */
+       struct lock              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 */
@@ -2155,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;
 };
 
@@ -2201,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 */
@@ -2210,16 +2550,16 @@ int hci_ctloutput(struct socket *so, struct sockopt *sopt);
 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 *);
index 5b0981f..4fc2779 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/hci_event.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/hci_event.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -32,8 +32,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
@@ -48,6 +46,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 *);
@@ -57,9 +56,12 @@ 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
@@ -101,7 +103,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 *
@@ -112,12 +140,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";
 
@@ -125,7 +147,7 @@ hci_eventstr(unsigned int event)
                return "VENDOR";
        }
 
-       return "UNRECOGNISED";
+       return "UNKNOWN";
 }
 #endif /* BLUETOOTH_DEBUG */
 
@@ -135,7 +157,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)
@@ -150,7 +171,8 @@ hci_event(struct mbuf *m, struct hci_unit *unit)
 
        KKASSERT(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_get_nameunit(unit->hci_dev), hci_eventstr(hdr.event));
 
        switch(hdr.event) {
        case HCI_EVENT_COMMAND_STATUS:
@@ -169,6 +191,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;
@@ -193,39 +219,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;
        }
 
@@ -249,11 +247,17 @@ 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_get_nameunit(unit->hci_dev),
                HCI_OGF(letoh16(ep.opcode)), HCI_OCF(letoh16(ep.opcode)),
                ep.status,
                ep.num_cmd_pkts);
 
+       if (ep.status > 0)
+               kprintf("%s: CommandStatus opcode (%03x|%04x) failed "
+                   "(status=0x%02x)\n", device_get_nameunit(unit->hci_dev),
+                   HCI_OGF(letoh16(ep.opcode)),
+                   HCI_OCF(letoh16(ep.opcode)), ep.status);
+
        unit->hci_num_cmd_pkts = ep.num_cmd_pkts;
 
        /*
@@ -264,7 +268,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_get_nameunit(unit->hci_dev));
                        while ((link = hci_link_lookup_state(unit,
                            HCI_LINK_ACL, HCI_LINK_WAIT_CONNECT)) != NULL)
                                hci_link_free(link, ECONNABORTED);
@@ -291,16 +295,28 @@ static void
 hci_event_command_compl(struct hci_unit *unit, struct mbuf *m)
 {
        hci_command_compl_ep ep;
+       hci_status_rp rp;
 
        KKASSERT(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,
+               device_get_nameunit(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)
+               kprintf("%s: CommandComplete opcode (%03x|%04x) failed (status=0x%02x)\n",
+                   device_get_nameunit(unit->hci_dev), HCI_OGF(letoh16(ep.opcode)),
+                   HCI_OCF(letoh16(ep.opcode)), rp.status);
+
        unit->hci_num_cmd_pkts = ep.num_cmd_pkts;
 
        /*
@@ -319,6 +335,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;
@@ -375,9 +399,9 @@ hci_event_num_compl_pkts(struct hci_unit *unit, struct mbuf *m)
                } else {
                        /* XXX need to issue Read_Buffer_Size or Reset? */
                        kprintf("%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_get_nameunit(unit->hci_dev), handle,
+                           num, (num == 1 ? "" : "s"));
                }
        }
 
@@ -418,42 +442,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;
 
        KKASSERT(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_get_nameunit(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);
+               KKASSERT(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 = kmalloc(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;
                }
+       }
+}
+
+/*
+ * 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;
 
-               microtime(&memo->time);
-               m_copydata(m, 0, sizeof(hci_inquiry_response),
-                       (caddr_t)&memo->response);
-               m_adj(m, sizeof(hci_inquiry_response));
+       KKASSERT(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--) {
+               KKASSERT(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;
+               }
        }
 }
 
@@ -478,7 +528,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_get_nameunit(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],
@@ -538,8 +588,14 @@ hci_event_con_compl(struct hci_unit *unit, struct mbuf *m)
                                                &cp, sizeof(cp));
                if (err)
                        kprintf("%s: Warning, could not write link policy\n",
-                               unit->hci_devname);
+                           device_get_nameunit(unit->hci_dev));
 
+               err = hci_send_cmd(unit, HCI_CMD_READ_CLOCK_OFFSET,
+                                   &cp.con_handle, sizeof(cp.con_handle));
+               if (err)
+                       kprintf("%s: Warning, could not read clock offset\n",
+                           device_get_nameunit(unit->hci_dev));
                err = hci_acl_setmode(link);
                if (err == EINPROGRESS)
                        return;
@@ -568,7 +624,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_get_nameunit(unit->hci_dev), ep.con_handle, ep.status);
 
        link = hci_link_lookup_handle(unit, HCI_CON_HANDLE(ep.con_handle));
        if (link)
@@ -593,12 +650,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_get_nameunit(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);
@@ -642,7 +700,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_get_nameunit(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)
@@ -684,8 +743,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_get_nameunit(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)
@@ -728,7 +788,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_get_nameunit(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)
@@ -750,6 +811,34 @@ hci_event_change_con_link_key_compl(struct hci_unit *unit, struct mbuf *m)
        hci_acl_linkmode(link);
 }
 
+/*
+ * 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;
+
+       KKASSERT(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
  */
@@ -770,9 +859,7 @@ hci_cmd_read_bdaddr(struct hci_unit *unit, struct mbuf *m)
 
        bdaddr_copy(&unit->hci_bdaddr, &rp.bdaddr);
 
-       crit_enter();
        unit->hci_flags &= ~BTF_INIT_BDADDR;
-       crit_exit();
 
        wakeup(unit);
 }
@@ -800,9 +887,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);
 
-       crit_enter();
        unit->hci_flags &= ~BTF_INIT_BUFFER_SIZE;
-       crit_exit();
 
        wakeup(unit);
 }
@@ -890,17 +975,68 @@ hci_cmd_read_local_features(struct hci_unit *unit, struct mbuf *m)
 
        /* XXX what do 2MBPS/3MBPS/3SLOT eSCO mean? */
 
-       crit_enter();
        unit->hci_flags &= ~BTF_INIT_FEATURES;
-       crit_exit();
 
        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_get_nameunit(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;
+
+       KKASSERT(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;
+
+       KKASSERT(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
  *
@@ -945,4 +1081,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;
 }
index b1d0751..cd1e168 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/hci_ioctl.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/hci_ioctl.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -64,7 +64,7 @@ hci_dump(void)
        TAILQ_FOREACH(unit, &hci_unit_list, hci_next) {
                kprintf("UNIT %s: flags 0x%4.4x, "
                        "num_cmd=%d, num_acl=%d, num_sco=%d\n",
-                       unit->hci_devname, unit->hci_flags,
+                       device_get_nameunit(unit->hci_dev), unit->hci_flags,
                        unit->hci_num_cmd_pkts,
                        unit->hci_num_acl_pkts,
                        unit->hci_num_sco_pkts);
@@ -177,8 +177,8 @@ 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,
-                           HCI_DEVNAME_SIZE) == 0)
+                       if (strncmp(device_get_nameunit(unit->hci_dev),
+                           btr->btr_name, HCI_DEVNAME_SIZE) == 0)
                                break;
                }
 
@@ -207,7 +207,8 @@ 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_get_nameunit(unit->hci_dev),
+                   HCI_DEVNAME_SIZE);
                bdaddr_copy(&btr->btr_bdaddr, &unit->hci_bdaddr);
 
                btr->btr_flags = unit->hci_flags;
@@ -233,9 +234,7 @@ hci_ioctl(unsigned long cmd, void *data, struct proc *p)
                        unit->hci_flags &= ~BTF_UP;
                }
 
-               crit_enter();
                unit->hci_flags |= (btr->btr_flags & BTF_INIT);
-               crit_exit();
 
                if ((unit->hci_flags & BTF_UP) == 0
                    && (btr->btr_flags & BTF_UP)) {
@@ -243,9 +242,7 @@ hci_ioctl(unsigned long cmd, void *data, struct proc *p)
                        if (err)
                                break;
 
-                       crit_enter();
                        unit->hci_flags |= BTF_UP;
-                       crit_exit();
                }
 
                btr->btr_flags = unit->hci_flags;
@@ -272,10 +269,7 @@ hci_ioctl(unsigned long cmd, void *data, struct proc *p)
                break;
 
        case SIOCGBTSTATS:      /* get unit statistics */
-               crit_enter();
-               memcpy(&btr->btr_stats, &unit->hci_stats,
-                       sizeof(struct bt_stats));
-               crit_exit();
+               (*unit->hci_if->get_stats)(unit->hci_dev, &btr->btr_stats, 0);
                break;
 
        case SIOCZBTSTATS:      /* get & reset unit statistics */
@@ -283,12 +277,7 @@ hci_ioctl(unsigned long cmd, void *data, struct proc *p)
                if (err)
                        break;
 
-               crit_enter();
-               memcpy(&btr->btr_stats, &unit->hci_stats,
-                       sizeof(struct bt_stats));
-               memset(&unit->hci_stats, 0, sizeof(struct bt_stats));
-               crit_exit();
-
+               (*unit->hci_if->get_stats)(unit->hci_dev, &btr->btr_stats, 1);
                break;
 
        case SIOCSBTSCOMTU:     /* set sco_mtu value for unit */
index d462bc4..d6c739d 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/hci_link.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/hci_link.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -32,8 +32,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
@@ -102,9 +100,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)
@@ -264,8 +262,9 @@ 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_get_nameunit(link->hl_unit->hci_dev),
+                   link->hl_handle);
 
                link->hl_state = HCI_LINK_WAIT_AUTH;
                cp.con_handle = htole16(link->hl_handle);
@@ -281,8 +280,9 @@ 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_get_nameunit(link->hl_unit->hci_dev),
+                   link->hl_handle);
 
                link->hl_state = HCI_LINK_WAIT_ENCRYPT;
                cp.con_handle = htole16(link->hl_handle);
@@ -300,8 +300,9 @@ 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_get_nameunit(link->hl_unit->hci_dev),
+                   link->hl_handle);
 
                link->hl_state = HCI_LINK_WAIT_SECURE;
                cp.con_handle = htole16(link->hl_handle);
@@ -327,11 +328,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_get_nameunit(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;
@@ -431,13 +432,15 @@ hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
 
 #ifdef DIAGNOSTIC
        if (hdr.type != HCI_ACL_DATA_PKT) {
-               kprintf("%s: bad ACL packet type\n", unit->hci_devname);
+               kprintf("%s: bad ACL packet type\n",
+                   device_get_nameunit(unit->hci_dev));
                goto bad;
        }
 
        if (m->m_pkthdr.len != letoh16(hdr.length)) {
                kprintf("%s: bad ACL packet length (%d != %d)\n",
-                       unit->hci_devname, m->m_pkthdr.len, letoh16(hdr.length));
+                   device_get_nameunit(unit->hci_dev), m->m_pkthdr.len,
+                   letoh16(hdr.length));
                goto bad;
        }
 #endif
@@ -452,7 +455,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_get_nameunit(unit->hci_dev), handle);
 
                /*
                 * There is no way to find out what this connection handle is
@@ -470,11 +473,11 @@ hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
        case HCI_PACKET_START:
                if (link->hl_rxp != NULL)
                        kprintf("%s: dropped incomplete ACL packet\n",
-                               unit->hci_devname);
+                           device_get_nameunit(unit->hci_dev));
 
                if (m->m_pkthdr.len < sizeof(l2cap_hdr_t)) {
                        kprintf("%s: short ACL packet\n",
-                               unit->hci_devname);
+                           device_get_nameunit(unit->hci_dev));
 
                        goto bad;
                }
@@ -486,7 +489,7 @@ hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
        case HCI_PACKET_FRAGMENT:
                if (link->hl_rxp == NULL) {
                        kprintf("%s: unexpected packet fragment\n",
-                               unit->hci_devname);
+                           device_get_nameunit(unit->hci_dev));
 
                        goto bad;
                }
@@ -499,7 +502,7 @@ hci_acl_recv(struct mbuf *m, struct hci_unit *unit)
 
        default:
                kprintf("%s: unknown packet type\n",
-                       unit->hci_devname);
+                   device_get_nameunit(unit->hci_dev));
 
                goto bad;
        }
@@ -559,7 +562,8 @@ 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_get_nameunit(link->hl_unit->hci_dev),
+           link->hl_handle, plen, mlen);
 
        while (plen > 0) {
                if (plen > mlen) {
@@ -573,7 +577,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_get_nameunit(link->hl_unit->hci_dev), mlen, plen);
                IF_ENQUEUE(&pdu->lp_data, m);
                m = n;
                plen -= mlen;
@@ -707,15 +712,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_get_nameunit(link->hl_unit->hci_dev), link->hl_handle, num);
 
        while (num > 0) {
                pdu = TAILQ_FIRST(&link->hl_txq);
                if (pdu == NULL) {
                        kprintf("%s: %d packets completed on handle #%x "
                                "but none pending!\n",
-                               link->hl_unit->hci_devname, num,
-                               link->hl_handle);
+                               device_get_nameunit(link->hl_unit->hci_dev),
+                               num, link->hl_handle);
                        return;
                }
 
@@ -836,13 +842,15 @@ hci_sco_recv(struct mbuf *m, struct hci_unit *unit)
 
 #ifdef DIAGNOSTIC
        if (hdr.type != HCI_SCO_DATA_PKT) {
-               kprintf("%s: bad SCO packet type\n", unit->hci_devname);
+               kprintf("%s: bad SCO packet type\n",
+                   device_get_nameunit(unit->hci_dev));
                goto bad;
        }
 
        if (m->m_pkthdr.len != hdr.length) {
                kprintf("%s: bad SCO packet length (%d != %d)\n",
-                   unit->hci_devname, m->m_pkthdr.len, hdr.length);
+                   device_get_nameunit(unit->hci_dev), m->m_pkthdr.len,
+                   hdr.length);
                goto bad;
        }
 #endif
@@ -853,7 +861,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_get_nameunit(unit->hci_dev), handle);
 
                goto bad;
        }
@@ -912,6 +920,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);
        crit_exit();    
@@ -927,9 +938,9 @@ hci_link_free(struct hci_link *link, int err)
 
        KKASSERT(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_get_nameunit(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 +997,7 @@ hci_link_free(struct hci_link *link, int err)
        crit_enter();   
        IF_DRAIN(&link->hl_data);
        crit_exit();
+
        /*
         * Halt the timeout - if its already running we cannot free the
         * link structure but the timeout function will call us back in
@@ -996,6 +1008,18 @@ hci_link_free(struct hci_link *link, int err)
        if (callout_active(&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;
+       }
+
        crit_enter();
        TAILQ_REMOVE(&link->hl_unit->hci_links, link, hl_next);
        crit_exit();    
index 7a11155..29af609 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/hci_misc.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/hci_misc.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -32,8 +32,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
@@ -130,7 +128,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;
                }
@@ -140,6 +138,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 = kmalloc(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)
 {
index 2e5ccfe..0e28dec 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/hci_socket.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/hci_socket.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -32,8 +32,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
 /* load symbolic names */
 #ifdef BLUETOOTH_DEBUG
 #define PRUREQUESTS
@@ -109,104 +107,318 @@ static int hci_ssend (struct socket *so, int flags, struct mbuf *m,
                                  struct sockaddr *addr, struct mbuf *control,
                                  struct thread *td);
 
+/* 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
@@ -216,6 +428,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 */
        }
@@ -283,6 +497,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) {
@@ -296,13 +511,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) {
@@ -310,6 +518,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, MB_DONTWAIT);
        if (m0 == NULL) {
@@ -319,20 +534,21 @@ hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
        sbappendrecord(&pcb->hp_socket->so_snd.sb, 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_get_nameunit(unit->hci_dev),
+               HCI_OGF(hdr.opcode), HCI_OCF(hdr.opcode));
 
        /* Sendss it */
-       if (unit->hci_num_cmd_pkts == 0) {
+       if (unit->hci_num_cmd_pkts == 0)
                IF_ENQUEUE(&unit->hci_cmdwait, m);
-       else
+       else
                hci_output_cmd(unit, m);
 
        return 0;
 
 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;
 }
@@ -704,7 +920,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;
 
index 0a63fb1..0fced4d 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/hci_unit.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/hci_unit.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -32,8 +32,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
 #include <sys/param.h>
 #include <sys/conf.h>
 #include <sys/device.h>
@@ -59,38 +57,77 @@ 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)
 {
-       KKASSERT(unit->hci_softc != NULL);
-       KKASSERT(unit->hci_devname != NULL);
-       KKASSERT(unit->hci_enable != NULL);
-       KKASSERT(unit->hci_disable != NULL);
-       KKASSERT(unit->hci_start_cmd != NULL);
-       KKASSERT(unit->hci_start_acl != NULL);
-       KKASSERT(unit->hci_start_sco != NULL);
+       struct hci_unit *unit;
+
+       KKASSERT(dev != NULL);
+       KKASSERT(hci_if->enable != NULL);
+       KKASSERT(hci_if->disable != NULL);
+       KKASSERT(hci_if->output_cmd != NULL);
+       KKASSERT(hci_if->output_acl != NULL);
+       KKASSERT(hci_if->output_sco != NULL);
+       KKASSERT(hci_if->get_stats != NULL);
+
+       unit = kmalloc(sizeof(struct hci_unit), M_BLUETOOTH, M_ZERO | M_WAITOK);
+       KKASSERT(unit != NULL);
+
+       unit->hci_dev = dev;
+       unit->hci_if = hci_if;
+       unit->hci_flags = flags;
+
+       lockinit(&unit->hci_devlock, "HCI device lock", 0, 0);
 
        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);
 
+       crit_enter();
        TAILQ_INSERT_TAIL(&hci_unit_list, unit, hci_next);
+       crit_exit();
+
+       return unit;
 }
 
 void
 hci_detach(struct hci_unit *unit)
 {
+       crit_enter();
        hci_disable(unit);
 
        TAILQ_REMOVE(&hci_unit_list, unit, hci_next);
+       crit_exit();
+
+       kfree(unit, M_BLUETOOTH);
 }
 
 int
@@ -103,11 +140,9 @@ hci_enable(struct hci_unit *unit)
         * 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;
 
@@ -117,11 +152,14 @@ hci_enable(struct hci_unit *unit)
         */
        unit->hci_acl_mask = HCI_PKT_DM1 | HCI_PKT_DH1;
        unit->hci_packet_type = unit->hci_acl_mask;
-       
-       err = (*unit->hci_enable)(unit);
+
+       memcpy(unit->hci_cmds, hci_cmds_v10, HCI_COMMANDS_SIZE);
+       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.
@@ -170,7 +208,8 @@ hci_enable(struct hci_unit *unit)
        return 0;
 
 bad2:
-       (*unit->hci_disable)(unit);
+       (*unit->hci_if->disable)(unit->hci_dev);
+       unit->hci_flags &= ~BTF_RUNNING;
 
 bad1:
        return err;
@@ -190,7 +229,8 @@ hci_disable(struct hci_unit *unit)
        }
 #endif
 
-       (*unit->hci_disable)(unit);
+       (*unit->hci_if->disable)(unit->hci_dev);
+       unit->hci_flags &= ~BTF_RUNNING;
 
        /*
         * close down any links, take care to close SCO first since
@@ -208,6 +248,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_DRAIN(&unit->hci_eventq);
        unit->hci_eventqlen = 0;
 
@@ -217,10 +259,7 @@ hci_disable(struct hci_unit *unit)
        IF_DRAIN(&unit->hci_scorxq);
        unit->hci_scorxqlen = 0;
 
-       IF_DRAIN(&unit->hci_cmdq);
        IF_DRAIN(&unit->hci_cmdwait);
-       IF_DRAIN(&unit->hci_acltxq);
-       IF_DRAIN(&unit->hci_scotxq);
        IF_DRAIN(&unit->hci_scodone);
 }
 
@@ -246,7 +285,6 @@ hci_unit_lookup(bdaddr_t *addr)
 int
 hci_send_cmd(struct hci_unit *unit, uint16_t opcode, void *buf, uint8_t len)
 {
-
        struct mbuf *m;
        hci_cmd_hdr_t *p;
 
@@ -261,7 +299,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) {
                KKASSERT(buf != NULL);
@@ -273,13 +311,14 @@ 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_get_nameunit(unit->hci_dev),
                HCI_OGF(opcode), HCI_OCF(opcode));
 
        /* and send it on */
-       if (unit->hci_num_cmd_pkts == 0) {
+       if (unit->hci_num_cmd_pkts == 0)
                IF_ENQUEUE(&unit->hci_cmdwait, m);
-       else
+       else
                hci_output_cmd(unit, m);
 
        return 0;
@@ -298,16 +337,17 @@ hci_intr(void *arg)
        struct mbuf *m;
 
 another:
-       crit_enter();
+       lockmgr(&unit->hci_devlock, LK_EXCLUSIVE);
 
        if (unit->hci_eventqlen > 0) {
                IF_DEQUEUE(&unit->hci_eventq, m);
                unit->hci_eventqlen--;
-               crit_exit();
+               lockmgr(&unit->hci_devlock, LK_RELEASE);
+
                KKASSERT(m != NULL);
 
                DPRINTFN(10, "(%s) recv event, len = %d\n",
-                               unit->hci_devname, m->m_pkthdr.len);
+                   device_get_nameunit(unit->hci_dev), m->m_pkthdr.len);
 
                m->m_flags |= IFF_LINK0;        /* mark incoming packet */
                hci_mtap(m, unit);
@@ -319,11 +359,11 @@ another:
        if (unit->hci_scorxqlen > 0) {
                IF_DEQUEUE(&unit->hci_scorxq, m);
                unit->hci_scorxqlen--;
-               crit_exit();
+               lockmgr(&unit->hci_devlock, LK_RELEASE);
                KKASSERT(m != NULL);
 
                DPRINTFN(10, "(%s) recv SCO, len = %d\n",
-                               unit->hci_devname, m->m_pkthdr.len);
+                   device_get_nameunit(unit->hci_dev), m->m_pkthdr.len);
 
                m->m_flags |= IFF_LINK0;        /* mark incoming packet */
                hci_mtap(m, unit);
@@ -335,11 +375,12 @@ another:
        if (unit->hci_aclrxqlen > 0) {
                IF_DEQUEUE(&unit->hci_aclrxq, m);
                unit->hci_aclrxqlen--;
-               crit_exit();
+               lockmgr(&unit->hci_devlock, LK_RELEASE);
+
                KKASSERT(m != NULL);
                
                DPRINTFN(10, "(%s) recv ACL, len = %d\n",
-                               unit->hci_devname, m->m_pkthdr.len);
+                   device_get_nameunit(unit->hci_dev), m->m_pkthdr.len);
 
                m->m_flags |= IFF_LINK0;        /* mark incoming packet */
                hci_mtap(m, unit);
@@ -351,10 +392,10 @@ another:
        IF_DEQUEUE(&unit->hci_scodone, m);
        if (m != NULL) {
                struct hci_link *link;
-               crit_exit();
+               lockmgr(&unit->hci_devlock, LK_RELEASE);
 
                DPRINTFN(11, "(%s) complete SCO\n",
-                               unit->hci_devname);
+                   device_get_nameunit(unit->hci_dev));
 
                TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
                        if (link == M_GETCTX(m, struct hci_link *)) {
@@ -369,7 +410,7 @@ another:
                goto another;
        }
 
-       crit_exit();
+       lockmgr(&unit->hci_devlock, LK_RELEASE);
 
        DPRINTFN(10, "done\n");
 }
@@ -378,56 +419,76 @@ 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;
+
+       lockmgr(&unit->hci_devlock, LK_EXCLUSIVE);
+
        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_get_nameunit(unit->hci_dev));
                m_freem(m);
+               rv = 0;
        } else {
                unit->hci_eventqlen++;
-               crit_enter();
                IF_ENQUEUE(&unit->hci_eventq, m);
-               crit_exit();
                netisr_queue(NETISR_BLUETOOTH, m);
+               rv = 1;
        }
+       lockmgr(&unit->hci_devlock, LK_RELEASE);
+
+       return rv;
 }
 
-void
+int
 hci_input_acl(struct hci_unit *unit, struct mbuf *m)
 {
+       int rv;
+
+       lockmgr(&unit->hci_devlock, LK_EXCLUSIVE);
        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_get_nameunit(unit->hci_dev));
                m_freem(m);
+               rv = 0;
        } else {
                unit->hci_aclrxqlen++;
-               crit_enter();
                IF_ENQUEUE(&unit->hci_aclrxq, m);
-               crit_exit();
-               netisr_queue(NETISR_BLUETOOTH,m);
+               netisr_queue(NETISR_BLUETOOTH, m);
+               rv = 1;
        }
+       lockmgr(&unit->hci_devlock, LK_RELEASE);
+
+       return rv;
 }
 
-void
+int
 hci_input_sco(struct hci_unit *unit, struct mbuf *m)
 {
+       int rv;
+
+       lockmgr(&unit->hci_devlock, LK_EXCLUSIVE);
        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_get_nameunit(unit->hci_dev));
                m_freem(m);
+               rv = 0;
        } else {
                unit->hci_scorxqlen++;
-               crit_enter();
                IF_ENQUEUE(&unit->hci_scorxq, m);
-               crit_exit();
-               netisr_queue(NETISR_BLUETOOTH,m);
+               netisr_queue(NETISR_BLUETOOTH, m);
+               rv = 1;
        }
+       lockmgr(&unit->hci_devlock, LK_RELEASE);
+
+       return rv;
 }
 
 void
@@ -437,8 +498,8 @@ hci_output_cmd(struct hci_unit *unit, struct mbuf *m)
 
        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_get_nameunit(unit->hci_dev), unit->hci_num_cmd_pkts);
 
        unit->hci_num_cmd_pkts--;
 
@@ -450,11 +511,7 @@ hci_output_cmd(struct hci_unit *unit, struct mbuf *m)
        if (arg != NULL)
                hci_drop(arg);
 
-       crit_enter();
-       IF_ENQUEUE(&unit->hci_cmdq, m);
-       crit_exit();
-       if ((unit->hci_flags & BTF_XMIT_CMD) == 0)
-               (*unit->hci_start_cmd)(unit);
+       (*unit->hci_if->output_cmd)(unit->hci_dev, m);
 }
 
 void
@@ -462,43 +519,34 @@ hci_output_acl(struct hci_unit *unit, struct mbuf *m)
 {
        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_get_nameunit(unit->hci_dev), unit->hci_num_acl_pkts);
 
        unit->hci_num_acl_pkts--;
 
-       crit_enter();
-       IF_ENQUEUE(&unit->hci_acltxq, m);
-       crit_exit();
-
-       if ((unit->hci_flags & BTF_XMIT_ACL) == 0)
-               (*unit->hci_start_acl)(unit);
+       (*unit->hci_if->output_acl)(unit->hci_dev, m);
 }
 
 void
 hci_output_sco(struct hci_unit *unit, struct mbuf *m)
 {
-
        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_get_nameunit(unit->hci_dev), unit->hci_num_sco_pkts);
 
        unit->hci_num_sco_pkts--;
 
-       crit_enter();
-       IF_ENQUEUE(&unit->hci_scotxq, m);
-       crit_exit();
-       if ((unit->hci_flags & BTF_XMIT_SCO) == 0)
-               (*unit->hci_start_sco)(unit);
-
+       (*unit->hci_if->output_sco)(unit->hci_dev, m);
 }
 
-void
+int
 hci_complete_sco(struct hci_unit *unit, struct mbuf *m)
 {
+       lockmgr(&unit->hci_devlock, LK_EXCLUSIVE);
        IF_ENQUEUE(&unit->hci_scodone, m);
-       crit_enter();
        netisr_queue(NETISR_BLUETOOTH,m);
-       crit_exit();
+       lockmgr(&unit->hci_devlock, LK_RELEASE);
+
+       return 1;
 }
index 4391f12..55147f0 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/l2cap.h,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/l2cap.h,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -56,6 +56,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
+ * $Id: l2cap.h,v 1.6 2007/11/03 17:20:17 plunky Exp $
  * $FreeBSD: src/sys/netgraph/bluetooth/include/l2cap.h,v 1.4 2005/08/31 18:13:23 emax Exp $
  */
 
index 09f4c9f..99d14a9 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/l2cap_lower.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/l2cap_lower.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -32,8 +32,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
@@ -121,7 +119,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_get_nameunit(link->hl_unit->hci_dev), hdr.length);
 
        if (hdr.length != m->m_pkthdr.len)
                goto failed;
@@ -144,7 +142,8 @@ 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_get_nameunit(link->hl_unit->hci_dev), hdr.length,
+               hdr.dcid);
 
 failed:
        m_freem(m);
index cb77b1c..63b768c 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/l2cap_misc.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/l2cap_misc.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -32,8 +32,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/mbuf.h>
@@ -86,10 +84,11 @@ l2cap_setmode(struct l2cap_channel *chan)
        KKASSERT(chan != NULL);
        KKASSERT(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_get_nameunit(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;
index 75b2137..4e02721 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/l2cap_signal.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/l2cap_signal.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -32,8 +32,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
 #include <stdarg.h>
 
 #include <sys/param.h>
@@ -87,7 +85,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_get_nameunit(link->hl_unit->hci_dev),
                        cmd.code, cmd.ident, cmd.length);
 
                switch (cmd.code) {
@@ -409,7 +407,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)
@@ -526,18 +524,63 @@ l2cap_recv_config_req(struct mbuf *m, struct hci_link *link)
                        break;
 
                case L2CAP_OPT_QOS:
+                       if (rp.result == L2CAP_UNKNOWN_OPTION)
+                               break;
+
+                       if (opt.length != L2CAP_OPT_QOS_SIZE)
+                               goto reject;
+
+                       m_copydata(m, 0, L2CAP_OPT_QOS_SIZE, (caddr_t)&val);
+                       if (val.qos.service_type == L2CAP_QOS_NO_TRAFFIC ||
+                           val.qos.service_type == L2CAP_QOS_BEST_EFFORT)
+                               /*
+                                * In accordance with the spec, we choose to
+                                * ignore the fields an provide no response.
+                                */
+                               break;
+
+                       if (len + sizeof(opt) + L2CAP_OPT_QOS_SIZE > sizeof(buf))
+                               goto reject;
+
+                       if (val.qos.service_type != L2CAP_QOS_GUARANTEED) {
+                               /*
+                                * Instead of sending an "unacceptable
+                                * parameters" response, treat this as an
+                                * unknown option and include the option
+                                * value in the response.
+                                */
+                               rp.result = L2CAP_UNKNOWN_OPTION;
+                       } else {
+                               /*
+                                * According to the spec, we must return
+                                * specific values for wild card parameters.
+                                * I don't know what to return without lying,
+                                * so return "unacceptable parameters" and
+                                * specify the preferred service type as
+                                * "Best Effort".
+                                */
+                               rp.result = L2CAP_UNACCEPTABLE_PARAMS;
+                               val.qos.service_type = L2CAP_QOS_BEST_EFFORT;
+                       }
+
+                       memcpy(buf + len, &opt, sizeof(opt));
+                       len += sizeof(opt);
+                       memcpy(buf + len, &val, L2CAP_OPT_QOS_SIZE);
+                       len += L2CAP_OPT_QOS_SIZE;
+                       break;
+
                default:
                        /* ignore hints */
                        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;
 
@@ -906,7 +949,7 @@ l2cap_send_signal(struct hci_link *link, uint8_t code, uint8_t ident,
 
        if (sizeof(l2cap_cmd_hdr_t) + length > link->hl_mtu)
                kprintf("(%s) exceeding L2CAP Signal MTU for link!\n",
-                       link->hl_unit->hci_devname);
+                   device_get_nameunit(link->hl_unit->hci_dev));
 #endif
 
        m = m_gethdr(MB_DONTWAIT, MT_DATA);
@@ -942,7 +985,8 @@ 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_get_nameunit(link->hl_unit->hci_dev), code, ident,
+               length);
 
        return hci_acl_send(m, link, NULL);
 }
index c37c5b5..d1f56fc 100644 (file)
@@ -1,6 +1,6 @@
+/* $DragonFly: src/sys/netbt/l2cap_socket.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
 /* $OpenBSD: l2cap_socket.c,v 1.1 2007/06/01 02:46:11 uwe Exp $ */
 /* $NetBSD: l2cap_socket.c,v 1.7 2007/04/21 06:15:23 plunky Exp $ */
-/* $DragonFly: src/sys/netbt/l2cap_socket.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
 
 /*-
  * Copyright (c) 2005 Iain Hibbert.
index 1c874a3..5d80b50 100644 (file)
@@ -1,6 +1,6 @@
+/* $DragonFly: src/sys/netbt/l2cap_upper.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
 /* $OpenBSD: l2cap_upper.c,v 1.2 2007/10/01 16:39:30 krw Exp $ */
 /* $NetBSD: l2cap_upper.c,v 1.8 2007/04/29 20:23:36 msaitoh Exp $ */
-/* $DragonFly: src/sys/netbt/l2cap_upper.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
 
 /*-
  * Copyright (c) 2005 Iain Hibbert.
index 5bb505e..5413461 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/rfcomm.h,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/rfcomm.h,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -57,7 +57,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: rfcomm.h,v 1.1.1.1 2007/11/20 11:56:11 griffin Exp $
+ * $Id: rfcomm.h,v 1.6 2007/11/20 20:25:58 plunky Exp $
  * $FreeBSD: src/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h,v 1.4 2005/01/11 01:39:53 emax Exp $
  */
 
@@ -79,6 +79,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
 
index 987463a..ad4ef4f 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/rfcomm_dlc.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/rfcomm_dlc.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -33,8 +33,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/mbuf.h>
index eb004d2..5f891b3 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/rfcomm_session.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/rfcomm_session.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -33,8 +33,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/mbuf.h>
index 43ddfa4..ff119c0 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/rfcomm_socket.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/rfcomm_socket.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -33,8 +33,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
 /* load symbolic names */
 #ifdef BLUETOOTH_DEBUG
 #define PRUREQUESTS
@@ -293,18 +291,20 @@ rfcomm_sattach (struct socket *so, int proto,
         * Since we have nothing to add, we attach the DLC
         * structure directly to our PCB pointer.
         */
-       err = rfcomm_attach((struct rfcomm_dlc **)&so->so_pcb,
-           &rfcomm_proto, so);
+       err = soreserve(so, rfcomm_sendspace, rfcomm_recvspace, NULL);
        if (err)
                return err;
 
-       err = soreserve(so, rfcomm_sendspace, rfcomm_recvspace,NULL);
+       err = rfcomm_attach((struct rfcomm_dlc **)&so->so_pcb,
+           &rfcomm_proto, so);
        if (err)
                return err;
 
        err = rfcomm_rcvd(so->so_pcb, sbspace(&so->so_rcv));
-       if (err)
+       if (err) {
+               rfcomm_detach((struct rfcomm_dlc **)&so->so_pcb);
                return err;
+       }
 
        return 0;
 }
index dceeac6..62a5eef 100644 (file)
@@ -1,6 +1,6 @@
-/* $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 $ */
-/* $DragonFly: src/sys/netbt/rfcomm_upper.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
+/* $DragonFly: src/sys/netbt/rfcomm_upper.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
+/* $OpenBSD: src/sys/netbt/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.
@@ -33,8 +33,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
-
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/mbuf.h>
@@ -305,20 +303,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)
@@ -328,7 +329,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);
 
@@ -336,13 +336,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);
@@ -358,6 +354,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);
index 71be475..c6d7343 100644 (file)
@@ -1,6 +1,6 @@
+/* $DragonFly: src/sys/netbt/sco.h,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
 /* $OpenBSD: sco.h,v 1.2 2007/06/01 02:46:12 uwe Exp $ */
 /* $NetBSD: sco.h,v 1.2 2006/07/26 10:20:56 tron Exp $ */
-/* $DragonFly: src/sys/netbt/sco.h,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
 
 /*-
  * Copyright (c) 2006 Itronix Inc.
index f738eba..e1b5639 100644 (file)
@@ -1,6 +1,6 @@
+/* $DragonFly: src/sys/netbt/sco_socket.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
 /* $OpenBSD: sco_socket.c,v 1.1 2007/06/01 02:46:12 uwe Exp $ */
 /* $NetBSD: sco_socket.c,v 1.9 2007/04/21 06:15:23 plunky Exp $ */
-/* $DragonFly: src/sys/netbt/sco_socket.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
 
 /*-
  * Copyright (c) 2006 Itronix Inc.
@@ -109,8 +109,8 @@ sco_ctloutput(struct socket *so, struct sockopt *sopt)
                        m = NULL;
                        err = ENOPROTOOPT;
                }
-/*             *opt = m;*/
-#warning Griffin - Theare is possible memory leeks...
+               /* *opt = m; */
+               /* XXX There are possible memory leaks (Griffin) */
                err = sooptcopyout(sopt, mtod(m, void *), m->m_len);
                break;
 
index 3c865d8..74778d3 100644 (file)
@@ -1,6 +1,6 @@
+/* $DragonFly: src/sys/netbt/sco_upper.c,v 1.2 2008/03/18 13:41:42 hasso Exp $ */
 /* $OpenBSD: sco_upper.c,v 1.2 2007/10/01 16:39:30 krw Exp $ */
 /* $NetBSD: sco_upper.c,v 1.6 2007/03/30 20:47:03 plunky Exp $ */
-/* $DragonFly: src/sys/netbt/sco_upper.c,v 1.1 2007/12/30 20:02:56 hasso Exp $ */
 
 /*-
  * Copyright (c) 2006 Itronix Inc.