On 14/04/15(Tue) 15:22, attila wrote:
> Martin Pieuchot <m...@openbsd.org> writes:
> >> 
> >> static const struct usb_devno ualea_devs[] = {
> >>    { USB_VENDOR_ARANEUS,   USB_PRODUCT_ARANEUS_ALEA }
> >> };
> >
> > Is it possible to match your device based on the content of the device
> > descriptor instead of whitelisting IDs?  Whitelisting means that if the
> > company produce a compatible device with a new ID we'll need to modify
> > the driver.
> >
> 
> Sadly, I don't think it is possible... you mean by looking at
> bDeviceClass/bDeviceSubClass/bDeviceProtocol?  He only gives me zeroes
> [...]
> Perhaps I am misunderstanding; is there something else in there I
> could/should match on?  I've changed the attach routine in the updated
> version to check vendor/product/iface, at least.

I was thinking at bInterfaceClass and bInterfaceProtocol but when they
are both to "vendor defined" (255), matching against the ID is the right
thing to do. 

> I looked and it appears that M_ZERO is used when allocating the memory
> for all of these structures, so I take it that explicit zeroing of
> things when tearing down is neither required nor desired?  I removed
> this kind of thing from ualea.c because it looked like it wasn't
> necessary.

That's right.

> I'm attaching the updated driver.
> 
> Thank you for the critique.  I suppose I need to write a man page for
> this as well... working on it.

Perfect, I'll put it in tree together with your driver :)

> 
> Pax, -A
> --
> att...@stalphonsos.com | http://trac.haqistan.net/~attila
> keyid E6CC1EDB | 4D91 1B98 A210 1D71 2A0E  AC29 9677 D0A6 E6CC 1EDB
> 
> 

> /*    $OpenBSD$ */
> /*
>  * Copyright (c) 2006 Alexander Yurchenko <gra...@openbsd.org>
>  * Copyright (c) 2007 Marc Balmer <mbal...@openbsd.org>
>  * Copyright (C) 2015 attila <att...@stalphonsos.com>
>  *
>  * Permission to use, copy, modify, and distribute this software for any
>  * purpose with or without fee is hereby granted, provided that the above
>  * copyright notice and this permission notice appear in all copies.
>  *
>  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
>  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
>  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
>  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
>  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
>  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
>  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>  */
> 
> /*
>  * Alea II TRNG.  Produces 100kbit/sec of entropy by black magic
>  *
>  * Product information in English can be found here:
>  *     http://www.araneus.fi/products/alea2/en/
>  */
> 
> #include <sys/param.h>
> #include <sys/systm.h>
> #include <sys/device.h>
> #include <sys/kernel.h>
> #include <sys/timeout.h>
> #include <dev/usb/usb.h>
> #include <dev/usb/usbdevs.h>
> #include <dev/usb/usbdi.h>
> #include <dev/usb/usbdi_util.h>
> #include <dev/rndvar.h>
> 
> #define ALEA_IFACE            0
> #define ALEA_MSECS            100
> #define ALEA_READ_TIMEOUT     1000
> #define ALEA_BUFSIZ           ((1024/8)*100)  /* 100 kbits */
> 
> #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)
> 
> struct ualea_softc {
>       struct  device sc_dev;
>       struct  usbd_device *sc_udev;
>       struct  usbd_pipe *sc_pipe;
>       struct  timeout sc_timeout;
>       struct  usb_task sc_task;
>       struct  usbd_xfer *sc_xfer;
>       int     *sc_buf;
> };
> 
> int ualea_match(struct device *, void *, void *);
> void ualea_attach(struct device *, struct device *, void *);
> int ualea_detach(struct device *, int);
> void ualea_task(void *);
> void ualea_timeout(void *);
> 
> struct cfdriver ualea_cd = {
>       NULL, "ualea", DV_DULL
> };
> 
> const struct cfattach ualea_ca = {
>       sizeof(struct ualea_softc),
>       ualea_match,
>       ualea_attach,
>       ualea_detach
> };
> 
> int
> ualea_match(struct device *parent, void *match, void *aux)
> {
>       struct usb_attach_arg *uaa = aux;
> 
>       if (uaa->iface == NULL)
>               return (UMATCH_NONE);
>       if ((uaa->vendor == USB_VENDOR_ARANEUS) &&
>           (uaa->product == USB_PRODUCT_ARANEUS_ALEA) &&
>           (uaa->ifaceno == ALEA_IFACE))
>               return (UMATCH_VENDOR_PRODUCT);
>       return (UMATCH_NONE);
> }
> 
> void
> ualea_attach(struct device *parent, struct device *self, void *aux)
> {
>       struct ualea_softc *sc = (struct ualea_softc *)self;
>       struct usb_attach_arg *uaa = aux;
>       usb_interface_descriptor_t *id;
>       usb_endpoint_descriptor_t *ed;
>       int ep_ibulk = -1;
>       usbd_status error;
>       int i;
> 
>       sc->sc_udev = uaa->device;
>       id = usbd_get_interface_descriptor(uaa->iface);
>       for (i = 0; i < id->bNumEndpoints; i++) {
>               ed = usbd_interface2endpoint_descriptor(uaa->iface, i);
>               if (ed == NULL) {
>                       printf("%s: failed to get endpoint %d descriptor\n",
>                           DEVNAME(sc), i);
>                       return;
>               }
>               if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
>                   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
>                       ep_ibulk = ed->bEndpointAddress;
>                       break;
>               }
>       }
>       if (ep_ibulk == -1) {
>               printf("%s: missing endpoint\n", DEVNAME(sc));
>               return;
>       }
>       error = usbd_open_pipe(uaa->iface, ep_ibulk, USBD_EXCLUSIVE_USE,
>                   &sc->sc_pipe);
>       if (error) {
>               printf("%s: failed to open bulk-in pipe: %s\n",
>                   DEVNAME(sc), usbd_errstr(error));
>               return;
>       }
>       sc->sc_xfer = usbd_alloc_xfer(sc->sc_udev);
>       if (sc->sc_xfer == NULL) {
>               printf("%s: could not alloc xfer\n", DEVNAME(sc));
>               return;
>       }
>       sc->sc_buf = usbd_alloc_buffer(sc->sc_xfer, ALEA_BUFSIZ);
>       if (sc->sc_buf == NULL) {
>               printf("%s: could not alloc %d-byte buffer\n", DEVNAME(sc),
>                   ALEA_BUFSIZ);
>               return;
>       }
>       usb_init_task(&sc->sc_task, ualea_task, sc, USB_TASK_TYPE_GENERIC);
>       timeout_set(&sc->sc_timeout, ualea_timeout, sc);
>       usb_add_task(sc->sc_udev, &sc->sc_task);
> }
> 
> int
> ualea_detach(struct device *self, int flags)
> {
>       struct ualea_softc *sc = (struct ualea_softc *)self;
> 
>       usb_rem_task(sc->sc_udev, &sc->sc_task);
>       if (timeout_initialized(&sc->sc_timeout))
>               timeout_del(&sc->sc_timeout);
>       if (sc->sc_xfer)
>               usbd_free_xfer(sc->sc_xfer);
>       if (sc->sc_pipe != NULL)
>               usbd_close_pipe(sc->sc_pipe);
> 
>       return (0);
> }
> 
> void
> ualea_task(void *arg)
> {
>       struct ualea_softc *sc = (struct ualea_softc *)arg;
>       usbd_status error;
>       u_int32_t len, i;
> 
>       usbd_setup_xfer(sc->sc_xfer, sc->sc_pipe, NULL, sc->sc_buf,
>           ALEA_BUFSIZ, USBD_SHORT_XFER_OK | USBD_SYNCHRONOUS,
>           ALEA_READ_TIMEOUT, NULL);
>       error = usbd_transfer(sc->sc_xfer);
>       if (error) {
>               printf("%s: xfer failed: %s\n", DEVNAME(sc),
>                   usbd_errstr(error));
>               goto bail;
>       }
>       usbd_get_xfer_status(sc->sc_xfer, NULL, NULL, &len, NULL);
>       if (len < sizeof(int)) {
>               printf("%s: xfer too short (%u bytes) - dropping\n",
>                   DEVNAME(sc), len);
>               goto bail;
>       }
>       len /= sizeof(int);
>       /*
>        * A random(|ness) koan:
>        *   children chug entropy like thirsty rhinos
>        *     surfing at the mall
>        *    privacy died in their hands
>        */
>       for (i = 0; i < len; i++)
>               add_true_randomness(sc->sc_buf[i]);
> bail:
>       timeout_add_msec(&sc->sc_timeout, ALEA_MSECS);
> }
> 
> void
> ualea_timeout(void *arg)
> {
>       struct ualea_softc *sc = arg;
> 
>       usb_add_task(sc->sc_udev, &sc->sc_task);
> }

Reply via email to