The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/ubtbcmfw.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: ubtbcmfw.c,v 1.7 2003/12/01 01:09:24 atatat Exp $      */
    2 
    3 /*
    4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by  Lennart Augustsson <lennart@augustsson.net>.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: ubtbcmfw.c,v 1.7 2003/12/01 01:09:24 atatat Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/device.h>
   46 #include <sys/conf.h>
   47 #include <sys/namei.h>
   48 #include <sys/vnode.h>
   49 #include <sys/proc.h>
   50 #include <sys/fcntl.h>
   51 #include <sys/sysctl.h>
   52 
   53 #include <dev/usb/usb.h>
   54 #include <dev/usb/usbdi.h>
   55 #include <dev/usb/usbdi_util.h>
   56 #include <dev/usb/usbdevs.h>
   57 
   58 /*
   59  * Download firmware to BCM2033.
   60  */
   61 
   62 #define CONFIG_NO       1
   63 #define IFACE_IDX       0       /* Control interface */
   64 /* Fixed endpoints */
   65 #define INTR_IN_EP      0x81
   66 #define BULK_OUT_EP     0x02
   67 
   68 Static char ubtbcmfw_fwpath[128] = "/usr/libdata/firmware/bcm2033";
   69 
   70 #define MINI_DRIVER "BCM2033-MD.hex"
   71 #define FIRMWARE    "BCM2033-FW.bin"
   72 
   73 struct ubtbcmfw_softc {
   74         USBBASEDEVICE           sc_dev;         /* base device */
   75 };
   76 
   77 Static int
   78 ubtbcmfw_load_file(usbd_device_handle dev, usbd_pipe_handle out,
   79                    const char *filename);
   80 Static usbd_status
   81 ubtbcmfw_write(usbd_device_handle dev, usbd_pipe_handle out,
   82                char *buf, uint count);
   83 Static usbd_status
   84 ubtbcmfw_read(usbd_device_handle dev, usbd_pipe_handle in,
   85               char *buf, uint *count);
   86 
   87 USB_DECLARE_DRIVER(ubtbcmfw);
   88 
   89 USB_MATCH(ubtbcmfw)
   90 {
   91         USB_MATCH_START(ubtbcmfw, uaa);
   92 
   93         if (uaa->iface != NULL)
   94                 return (UMATCH_NONE);
   95 
   96         /* Match the boot device. */
   97         if (uaa->vendor == USB_VENDOR_BROADCOM &&
   98             uaa->product == USB_PRODUCT_BROADCOM_BCM2033NF)
   99                 return (UMATCH_VENDOR_PRODUCT);
  100 
  101         return (UMATCH_NONE);
  102 }
  103 
  104 USB_ATTACH(ubtbcmfw)
  105 {
  106         USB_ATTACH_START(ubtbcmfw, sc, uaa);
  107         usbd_device_handle dev = uaa->device;
  108         usbd_interface_handle iface;
  109         usbd_status err;
  110         char devinfo[1024];
  111         char name[256];
  112         char buf[16];
  113         usbd_pipe_handle intr_in_pipe;
  114         usbd_pipe_handle bulk_out_pipe;
  115         uint n;
  116 
  117         usbd_devinfo(dev, 0, devinfo);
  118         USB_ATTACH_SETUP;
  119         printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
  120 
  121         err = usbd_set_config_no(dev, CONFIG_NO, 1);
  122         if (err) {
  123                 printf("%s: setting config no failed\n",
  124                     USBDEVNAME(sc->sc_dev));
  125                 USB_ATTACH_ERROR_RETURN;
  126         }
  127         err = usbd_device2interface_handle(dev, IFACE_IDX, &iface);
  128         if (err) {
  129                 printf("%s: getting interface handle failed\n",
  130                     USBDEVNAME(sc->sc_dev));
  131                 USB_ATTACH_ERROR_RETURN;
  132         }
  133 
  134         /* Will be used as a bulk pipe. */
  135         err = usbd_open_pipe(iface, INTR_IN_EP, 0, &intr_in_pipe);
  136         if (err) {
  137                 printf("%s: open bulk in failed\n", USBDEVNAME(sc->sc_dev));
  138                 USB_ATTACH_ERROR_RETURN;
  139         }
  140         err = usbd_open_pipe(iface, BULK_OUT_EP, 0, &bulk_out_pipe);
  141         if (err) {
  142                 printf("%s: open bulk in failed\n", USBDEVNAME(sc->sc_dev));
  143                 USB_ATTACH_ERROR_RETURN;
  144         }
  145 
  146         printf("%s: downloading firmware\n", USBDEVNAME(sc->sc_dev));
  147         snprintf(name, sizeof name, "%s/%s", ubtbcmfw_fwpath, MINI_DRIVER);
  148         err = ubtbcmfw_load_file(dev, bulk_out_pipe, name);
  149         if (err) {
  150                 printf("%s: loading mini-driver failed\n",
  151                        USBDEVNAME(sc->sc_dev));
  152                 USB_ATTACH_ERROR_RETURN;
  153         }
  154         usbd_delay_ms(dev, 1);
  155         err = ubtbcmfw_write(dev, bulk_out_pipe, "#", 1);
  156         if (err) {
  157                 printf("%s: write # failed\n", USBDEVNAME(sc->sc_dev));
  158                 USB_ATTACH_ERROR_RETURN;
  159         }
  160         buf[0] = 0;
  161         n = 10;
  162         err = ubtbcmfw_read(dev, intr_in_pipe, buf, &n);
  163         if (err) {
  164                 printf("%s: read # failed\n", USBDEVNAME(sc->sc_dev));
  165                 USB_ATTACH_ERROR_RETURN;
  166         }
  167         if (buf[0] != '#') {
  168                 printf("%s: memory select failed\n", USBDEVNAME(sc->sc_dev));
  169                 USB_ATTACH_ERROR_RETURN;
  170         }
  171         snprintf(name, sizeof name, "%s/%s", ubtbcmfw_fwpath, FIRMWARE);
  172         err = ubtbcmfw_load_file(dev, bulk_out_pipe, name);
  173         if (err) {
  174                 printf("%s: loading firmware failed\n",
  175                        USBDEVNAME(sc->sc_dev));
  176                 USB_ATTACH_ERROR_RETURN;
  177         }
  178         n = 10;
  179         err = ubtbcmfw_read(dev, intr_in_pipe, buf, &n);
  180         if (err) {
  181                 printf("%s: read . failed\n", USBDEVNAME(sc->sc_dev));
  182                 USB_ATTACH_ERROR_RETURN;
  183         }
  184         if (buf[0] != '.') {
  185                 printf("%s: firmware load failed\n", USBDEVNAME(sc->sc_dev));
  186                 USB_ATTACH_ERROR_RETURN;
  187         }
  188 
  189         usbd_close_pipe(intr_in_pipe);
  190         usbd_close_pipe(bulk_out_pipe);
  191 
  192         printf("%s: firmware download complete\n",
  193                USBDEVNAME(sc->sc_dev));
  194         usbd_delay_ms(dev, 500);
  195 
  196         USB_ATTACH_SUCCESS_RETURN;
  197 }
  198 
  199 USB_DETACH(ubtbcmfw)
  200 {
  201         /*USB_DETACH_START(ubtbcmfw, sc);*/
  202 
  203         return (0);
  204 }
  205 
  206 int
  207 ubtbcmfw_activate(device_ptr_t self, enum devact act)
  208 {
  209         return 0;
  210 }
  211 
  212 Static int
  213 ubtbcmfw_load_file(usbd_device_handle dev, usbd_pipe_handle out,
  214                    const char *filename)
  215 {
  216         struct proc *p = curproc;
  217         struct nameidata nd;
  218         struct vnode *vp;
  219         size_t resid, offs, size;
  220         int error;
  221         char buf[1024];
  222         struct timeval delta;
  223 
  224         NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, p);
  225         /* Loop until we are well passed boot */
  226         for (;;) {
  227                 error = vn_open(&nd, FREAD, 0);
  228                 if (!error)
  229                         break;
  230                 timersub(&boottime, &time, &delta);
  231                 if (delta.tv_sec > 60)
  232                         break;
  233                 printf("ubtbcmfw_load_file: waiting for firmware file\n");
  234                 if (tsleep(buf, PZERO, "ubtbcmfw", hz * 5) != EWOULDBLOCK)
  235                         break;
  236         }
  237         if (error)
  238                 return (error);
  239         vp = nd.ni_vp;
  240         VOP_UNLOCK(vp, 0);
  241         if (nd.ni_vp->v_type != VREG) {
  242                 error = EACCES;
  243                 goto out;
  244         }
  245 
  246         for (offs = 0; ; offs += size) {
  247                 size = sizeof buf;
  248                 error = vn_rdwr(UIO_READ, vp, buf, size, offs, UIO_SYSSPACE,
  249                     IO_NODELOCKED | IO_SYNC, p->p_ucred, &resid, p);
  250                 size -= resid;
  251                 if (error || size == 0)
  252                         break;
  253                 if (ubtbcmfw_write(dev, out, buf, size)) {
  254                         error = EIO;
  255                         break;
  256                 }
  257         }
  258 
  259 out:
  260         vn_close(vp, FREAD, p->p_ucred, p);
  261         return error;
  262 }
  263 
  264 Static usbd_status
  265 ubtbcmfw_write(usbd_device_handle dev, usbd_pipe_handle out,
  266                char *buf, uint count)
  267 {
  268         usbd_xfer_handle xfer;
  269         usbd_status err;
  270         uint n;
  271 
  272         xfer = usbd_alloc_xfer(dev);
  273         if (xfer == NULL)
  274                 return (USBD_NOMEM);
  275         n = count;
  276         err = usbd_bulk_transfer(xfer, out, 0, USBD_DEFAULT_TIMEOUT,
  277                                  buf, &n, "ubtfwr");
  278         usbd_free_xfer(xfer);
  279         return (err);
  280 }
  281 
  282 Static usbd_status
  283 ubtbcmfw_read(usbd_device_handle dev, usbd_pipe_handle in,
  284               char *buf, uint *count)
  285 {
  286         usbd_xfer_handle xfer;
  287         usbd_status err;
  288 
  289         xfer = usbd_alloc_xfer(dev);
  290         if (xfer == NULL)
  291                 return (USBD_NOMEM);
  292         err = usbd_bulk_transfer(xfer, in, USBD_SHORT_XFER_OK,
  293                                  USBD_DEFAULT_TIMEOUT, buf, count, "ubtfrd");
  294         usbd_free_xfer(xfer);
  295         return (err);
  296 }

Cache object: b6d224998214ac506ce3cf142a8d0d37


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.