The ubtbcmfw(4) driver fails to compile, as noted by PR kern/34219.

While it can be made to compile, the paradigm is not quite right because
it attempts to contact the filesystem during autoconfig which sometimes
causes a panic. Even if that was fixed, there is another potential problem
in that the driver tries/sleeps/tries/sleeps and the sleep could
theoretically sleep past the rc.d/btconfig stage and the controller
would remain unconfigured.

So, I have prepared a different method for loading the firmware to
Broadcom BCM2033 chip based devices. A package 'sysutils/bcmfw' will load
the firmware files via a ugen(4) device interface.

This update removes the ubtbcmfw(4) driver and adds a table to the ubt(4)
driver so that it will not attach to Broadcom BCM2033 based devices before
the firmware was loaded.

This fixes kern/34219
This commit is contained in:
plunky 2006-08-19 16:35:02 +00:00
parent a30325d38e
commit 95d2b886d7
9 changed files with 25 additions and 385 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.921 2006/08/14 22:26:59 bjh21 Exp $
# $NetBSD: mi,v 1.922 2006/08/19 16:35:02 plunky Exp $
./etc/mtree/set.man man-sys-root
./usr/share/info/am-utils.info man-amd-info info
./usr/share/info/as.info man-computil-info bfd,info
@ -1361,7 +1361,7 @@
./usr/share/man/cat4/ubsa.0 man-sys-catman .cat
./usr/share/man/cat4/ubsec.0 man-sys-catman .cat
./usr/share/man/cat4/ubt.0 man-sys-catman .cat
./usr/share/man/cat4/ubtbcmfw.0 man-sys-catman .cat
./usr/share/man/cat4/ubtbcmfw.0 man-obsolete obsolete
./usr/share/man/cat4/ucom.0 man-sys-catman .cat
./usr/share/man/cat4/ucycom.0 man-sys-catman .cat
./usr/share/man/cat4/udav.0 man-sys-catman .cat
@ -3729,7 +3729,7 @@
./usr/share/man/man4/ubsa.4 man-sys-man .man
./usr/share/man/man4/ubsec.4 man-sys-man .man
./usr/share/man/man4/ubt.4 man-sys-man .man
./usr/share/man/man4/ubtbcmfw.4 man-sys-man .man
./usr/share/man/man4/ubtbcmfw.4 man-obsolete obsolete
./usr/share/man/man4/ucom.4 man-sys-man .man
./usr/share/man/man4/ucycom.4 man-sys-man .man
./usr/share/man/man4/udav.4 man-sys-man .man

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.399 2006/08/13 09:28:23 wiz Exp $
# $NetBSD: Makefile,v 1.400 2006/08/19 16:35:02 plunky Exp $
# @(#)Makefile 8.1 (Berkeley) 6/18/93
MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 adc.4 adt7467c.4 adv.4 \
@ -49,7 +49,7 @@ MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 adc.4 adt7467c.4 adv.4 \
wsmouse.4 wsmux.4 xbox.4 xge.4 yds.4 ym.4 zero.4 zstty.4
# USB devices
MAN+= uaudio.4 ubsa.4 ubt.4 ubtbcmfw.4 ucom.4 ucycom.4 \
MAN+= uaudio.4 ubsa.4 ubt.4 ucom.4 ucycom.4 \
udsbr.4 uftdi.4 ugen.4 ugensa.4 uhid.4 \
uhidev.4 uipaq.4 uirda.4 ukbd.4 ukyopon.4 ulpt.4 \
umass.4 umct.4 umidi.4 umodem.4 ums.4 uplcom.4 urio.4 usb.4 \

View File

@ -1,4 +1,4 @@
.\" $NetBSD: ubt.4,v 1.1 2006/06/19 15:44:36 gdamore Exp $
.\" $NetBSD: ubt.4,v 1.2 2006/08/19 16:35:02 plunky Exp $
.\"
.\" Copyright (c) 2006 Itronix Inc.
.\" All rights reserved.
@ -77,7 +77,6 @@ Three voice channels with 16-bit encoding
.Sh SEE ALSO
.Xr bluetooth 4 ,
.Xr uhub 4 ,
.Xr ubtbcmfw 4 ,
.Xr sysctl 8
.Sh HISTORY
This

View File

@ -1,70 +0,0 @@
.\" $NetBSD: ubtbcmfw.4,v 1.1 2006/06/19 15:44:36 gdamore Exp $
.\"
.\" Copyright (c) 2006 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
.\" contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd January 14, 2006
.Dt UBTBCMFW 4
.Os
.Sh NAME
.Nm ubtbcmfw
.Nd USB Broadcom BCM2033 Firmware Loader
.Sh SYNOPSIS
.Cd "ubtbcmfw* at uhub? port ? configuration ? interface ?"
.Sh DESCRIPTION
The
.Nm
driver provides a way to load firmware for the Broadcom BCM2033
USB Bluetooth dongle.
.Pp
The firmware files that you receive with the device,
.Nm "BCM2033-MD.hex"
and
.Nm "BCM2033-FW.bin"
should be copied to a directory called
.Nm
in the search path of the
.Xr firmload 9
kernel subsytem. The firmware will be loaded automatically as needed.
.Sh SEE ALSO
.Xr bluetooth 4 ,
.Xr firmload 9 ,
.Xr uhub 4 ,
.Xr ubt 4
.Sh HISTORY
The
.Nm
firmware loader was written by
.An "Lennart Augustsson" .
.Sh BUGS
Does not yet use the
.Xr firmload 9
interface.

View File

@ -1,4 +1,4 @@
# $NetBSD: DEVNAMES,v 1.209 2006/08/14 22:05:45 bjh21 Exp $
# $NetBSD: DEVNAMES,v 1.210 2006/08/19 16:35:02 plunky Exp $
#
# This file contains all used device names and defined attributes in
# alphabetical order. New devices added to the system somewhere should first
@ -1285,7 +1285,6 @@ uba MI
ubsa MI
ubsec MI
ubt MI
ubtbcmfw MI
ucb hpcmips
ucbif hpcmips
ucbio hpcmips

View File

@ -27,7 +27,6 @@ ohcivar.h API for ohci.c
uaudio.c USB audio class driver
uaudioreg.h and definitions for it
ubt.c USB Bluetooth driver
ubtbcmfw.c Firmware loader for Broadcom BCM2033 Bluetooth devices
ucom.c TTY emulation for two bulk pipes
ucomvar.h TTY emulation interface
uftdi.c USB FTDI serial driver

View File

@ -1,4 +1,4 @@
# $NetBSD: files.usb,v 1.68 2006/07/24 14:24:50 gdt Exp $
# $NetBSD: files.usb,v 1.69 2006/08/19 16:35:03 plunky Exp $
#
# Config file and device description for machine-independent USB code.
# Included by ports that need it. Ports that use it must provide
@ -125,11 +125,6 @@ device ubt: bluetooth
attach ubt at uhub
file dev/usb/ubt.c ubt
# BCM2033 firmware download
device ubtbcmfw
attach ubtbcmfw at uhub
file dev/usb/ubtbcmfw.c ubtbcmfw needs-flag
# Misc
# Diamond Multimedia Rio 500

View File

@ -1,4 +1,4 @@
/* $NetBSD: ubt.c,v 1.14 2006/06/19 15:44:45 gdamore Exp $ */
/* $NetBSD: ubt.c,v 1.15 2006/08/19 16:35:03 plunky Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@ -74,7 +74,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ubt.c,v 1.14 2006/06/19 15:44:45 gdamore Exp $");
__KERNEL_RCSID(0, "$NetBSD: ubt.c,v 1.15 2006/08/19 16:35:03 plunky Exp $");
#include <sys/param.h>
#include <sys/device.h>
@ -280,6 +280,18 @@ static int ubt_set_isoc_config(struct ubt_softc *);
static int ubt_sysctl_config(SYSCTLFN_PROTO);
static void ubt_abortdealloc(struct ubt_softc *);
/*
* If a device should be ignored then add
*
* { VendorID, ProductID }
*
* to this list.
*/
static const struct usb_devno ubt_ignore[] = {
{ USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM2033NF },
{ 0, 0 } /* end of list */
};
USB_MATCH(ubt)
{
USB_MATCH_START(ubt, uaa);
@ -290,6 +302,9 @@ USB_MATCH(ubt)
if (uaa->iface == NULL)
return UMATCH_NONE;
if (usb_lookup(ubt_ignore, uaa->vendor, uaa->product))
return UMATCH_NONE;
id = usbd_get_interface_descriptor(uaa->iface);
if (id != NULL
&& id->bInterfaceClass == UICLASS_WIRELESS

View File

@ -1,297 +0,0 @@
/* $NetBSD: ubtbcmfw.c,v 1.13 2006/07/21 16:48:53 ad Exp $ */
/*
* Copyright (c) 2002 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Lennart Augustsson <lennart@augustsson.net>.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ubtbcmfw.c,v 1.13 2006/07/21 16:48:53 ad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/conf.h>
#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/proc.h>
#include <sys/fcntl.h>
#include <sys/sysctl.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
/*
* Download firmware to BCM2033.
*/
#define CONFIG_NO 1
#define IFACE_IDX 0 /* Control interface */
/* Fixed endpoints */
#define INTR_IN_EP 0x81
#define BULK_OUT_EP 0x02
Static char ubtbcmfw_fwpath[128] = "/usr/libdata/firmware/bcm2033";
#define MINI_DRIVER "BCM2033-MD.hex"
#define FIRMWARE "BCM2033-FW.bin"
struct ubtbcmfw_softc {
USBBASEDEVICE sc_dev; /* base device */
};
Static int
ubtbcmfw_load_file(usbd_device_handle dev, usbd_pipe_handle out,
const char *filename);
Static usbd_status
ubtbcmfw_write(usbd_device_handle dev, usbd_pipe_handle out,
char *buf, uint count);
Static usbd_status
ubtbcmfw_read(usbd_device_handle dev, usbd_pipe_handle in,
char *buf, uint *count);
USB_DECLARE_DRIVER(ubtbcmfw);
USB_MATCH(ubtbcmfw)
{
USB_MATCH_START(ubtbcmfw, uaa);
if (uaa->iface != NULL)
return (UMATCH_NONE);
/* Match the boot device. */
if (uaa->vendor == USB_VENDOR_BROADCOM &&
uaa->product == USB_PRODUCT_BROADCOM_BCM2033NF)
return (UMATCH_VENDOR_PRODUCT);
return (UMATCH_NONE);
}
USB_ATTACH(ubtbcmfw)
{
USB_ATTACH_START(ubtbcmfw, sc, uaa);
usbd_device_handle dev = uaa->device;
usbd_interface_handle iface;
usbd_status err;
char *devinfop;
char name[256];
char buf[16];
usbd_pipe_handle intr_in_pipe;
usbd_pipe_handle bulk_out_pipe;
uint n;
devinfop = usbd_devinfo_alloc(dev, 0);
USB_ATTACH_SETUP;
printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfop);
usbd_devinfo_free(devinfop);
err = usbd_set_config_no(dev, CONFIG_NO, 1);
if (err) {
printf("%s: setting config no failed\n",
USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
err = usbd_device2interface_handle(dev, IFACE_IDX, &iface);
if (err) {
printf("%s: getting interface handle failed\n",
USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
/* Will be used as a bulk pipe. */
err = usbd_open_pipe(iface, INTR_IN_EP, 0, &intr_in_pipe);
if (err) {
printf("%s: open bulk in failed\n", USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
err = usbd_open_pipe(iface, BULK_OUT_EP, 0, &bulk_out_pipe);
if (err) {
printf("%s: open bulk in failed\n", USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
printf("%s: downloading firmware\n", USBDEVNAME(sc->sc_dev));
snprintf(name, sizeof name, "%s/%s", ubtbcmfw_fwpath, MINI_DRIVER);
err = ubtbcmfw_load_file(dev, bulk_out_pipe, name);
if (err) {
printf("%s: loading mini-driver failed\n",
USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
usbd_delay_ms(dev, 1);
err = ubtbcmfw_write(dev, bulk_out_pipe, "#", 1);
if (err) {
printf("%s: write # failed\n", USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
buf[0] = 0;
n = 10;
err = ubtbcmfw_read(dev, intr_in_pipe, buf, &n);
if (err) {
printf("%s: read # failed\n", USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
if (buf[0] != '#') {
printf("%s: memory select failed\n", USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
snprintf(name, sizeof name, "%s/%s", ubtbcmfw_fwpath, FIRMWARE);
err = ubtbcmfw_load_file(dev, bulk_out_pipe, name);
if (err) {
printf("%s: loading firmware failed\n",
USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
n = 10;
err = ubtbcmfw_read(dev, intr_in_pipe, buf, &n);
if (err) {
printf("%s: read . failed\n", USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
if (buf[0] != '.') {
printf("%s: firmware load failed\n", USBDEVNAME(sc->sc_dev));
USB_ATTACH_ERROR_RETURN;
}
usbd_close_pipe(intr_in_pipe);
usbd_close_pipe(bulk_out_pipe);
printf("%s: firmware download complete\n",
USBDEVNAME(sc->sc_dev));
usbd_delay_ms(dev, 500);
USB_ATTACH_SUCCESS_RETURN;
}
USB_DETACH(ubtbcmfw)
{
/*USB_DETACH_START(ubtbcmfw, sc);*/
return (0);
}
int
ubtbcmfw_activate(device_ptr_t self, enum devact act)
{
return 0;
}
Static int
ubtbcmfw_load_file(usbd_device_handle dev, usbd_pipe_handle out,
const char *filename)
{
struct lwp *l = curlwp;
struct nameidata nd;
struct vnode *vp;
size_t resid, offs, size;
int error;
char buf[1024];
struct timeval delta;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, curlwp);
/* Loop until we are well passed boot */
for (;;) {
error = vn_open(&nd, FREAD, 0);
if (!error)
break;
timersub(&boottime, &time, &delta);
if (delta.tv_sec > 60)
break;
printf("ubtbcmfw_load_file: waiting for firmware file\n");
if (tsleep(buf, PZERO, "ubtbcmfw", hz * 5) != EWOULDBLOCK)
break;
}
if (error)
return (error);
vp = nd.ni_vp;
VOP_UNLOCK(vp, 0);
if (nd.ni_vp->v_type != VREG) {
error = EACCES;
goto out;
}
for (offs = 0; ; offs += size) {
size = sizeof buf;
error = vn_rdwr(UIO_READ, vp, buf, size, offs, UIO_SYSSPACE,
IO_NODELOCKED | IO_SYNC, l->l_cred, &resid, NULL);
size -= resid;
if (error || size == 0)
break;
if (ubtbcmfw_write(dev, out, buf, size)) {
error = EIO;
break;
}
}
out:
vn_close(vp, FREAD, l->l_cred, p);
return error;
}
Static usbd_status
ubtbcmfw_write(usbd_device_handle dev, usbd_pipe_handle out,
char *buf, uint count)
{
usbd_xfer_handle xfer;
usbd_status err;
uint n;
xfer = usbd_alloc_xfer(dev);
if (xfer == NULL)
return (USBD_NOMEM);
n = count;
err = usbd_bulk_transfer(xfer, out, 0, USBD_DEFAULT_TIMEOUT,
buf, &n, "ubtfwr");
usbd_free_xfer(xfer);
return (err);
}
Static usbd_status
ubtbcmfw_read(usbd_device_handle dev, usbd_pipe_handle in,
char *buf, uint *count)
{
usbd_xfer_handle xfer;
usbd_status err;
xfer = usbd_alloc_xfer(dev);
if (xfer == NULL)
return (USBD_NOMEM);
err = usbd_bulk_transfer(xfer, in, USBD_SHORT_XFER_OK,
USBD_DEFAULT_TIMEOUT, buf, count, "ubtfrd");
usbd_free_xfer(xfer);
return (err);
}