xref: /openbsd/sys/dev/usb/uonerng.c (revision c0d38480)
1*c0d38480Smpi /*	$OpenBSD: uonerng.c,v 1.2 2016/09/02 09:14:59 mpi Exp $ */
20667ff19Smpi /*
30667ff19Smpi  * Copyright (C) 2015 Devin Reade <gdr@gno.org>
40667ff19Smpi  * Copyright (C) 2015 Sean Levy <attila@stalphonsos.com>
50667ff19Smpi  * Copyright (c) 2007 Marc Balmer <mbalmer@openbsd.org>
60667ff19Smpi  * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
70667ff19Smpi  * Copyright (c) 1998 The NetBSD Foundation, Inc.
80667ff19Smpi  *
90667ff19Smpi  * Permission to use, copy, modify, and distribute this software for any
100667ff19Smpi  * purpose with or without fee is hereby granted, provided that the above
110667ff19Smpi  * copyright notice and this permission notice appear in all copies.
120667ff19Smpi  *
130667ff19Smpi  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
140667ff19Smpi  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
150667ff19Smpi  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
160667ff19Smpi  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
170667ff19Smpi  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
180667ff19Smpi  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
190667ff19Smpi  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
200667ff19Smpi  */
210667ff19Smpi 
220667ff19Smpi /*
230667ff19Smpi  * Moonbase Otago OneRNG TRNG.  Note that the encoded vendor for this
240667ff19Smpi  * device is OpenMoko as OpenMoko has made its device ranges available
250667ff19Smpi  * for other open source / open hardware vendors.
260667ff19Smpi  *
270667ff19Smpi  * Product information can be found here:
280667ff19Smpi  *     http://onerng.info/onerng
290667ff19Smpi  *
300667ff19Smpi  * Based on the ualea(4), uow(4), and umodem(4) source code.
310667ff19Smpi  */
320667ff19Smpi 
330667ff19Smpi #include <sys/param.h>
340667ff19Smpi #include <sys/systm.h>
350667ff19Smpi #include <sys/device.h>
360667ff19Smpi #include <sys/time.h>
370667ff19Smpi #include <sys/timeout.h>
380667ff19Smpi #include <machine/bus.h>
390667ff19Smpi 
400667ff19Smpi #include <dev/usb/usb.h>
410667ff19Smpi #include <dev/usb/usbdi.h>
420667ff19Smpi #include <dev/usb/usbdivar.h>
430667ff19Smpi #include <dev/usb/usbdi_util.h>
440667ff19Smpi #include <dev/usb/usbdevs.h>
450667ff19Smpi #include <dev/usb/usbcdc.h>
460667ff19Smpi 
470667ff19Smpi #include <dev/rndvar.h>
480667ff19Smpi 
490667ff19Smpi /*
500667ff19Smpi  * The OneRNG is documented to provide ~350kbits/s of entropy at
510667ff19Smpi  * ~7.8 bits/byte, and when used at a lower rate providing close
520667ff19Smpi  * to 8 bits/byte.
530667ff19Smpi  *
540667ff19Smpi  * Although this driver is able to consume the data at the full rate,
550667ff19Smpi  * we tune this down to 10kbit/s as the OpenBSD RNG is better off
560667ff19Smpi  * with small amounts of input at a time so as to not saturate the
570667ff19Smpi  * input queue and mute other sources of entropy.
580667ff19Smpi  *
590667ff19Smpi  * Furthermore, unlike other implementations, for us there is no benefit
600667ff19Smpi  * to discarding the initial bytes retrieved from the OneRNG, regardless
610667ff19Smpi  * of the quality of the data. (Empirical tests suggest that the initial
620667ff19Smpi  * quality is fine, anyway.)
630667ff19Smpi  */
640667ff19Smpi #define ONERNG_BUFSIZ		128
650667ff19Smpi #define ONERNG_MSECS		100
660667ff19Smpi 
670667ff19Smpi #define ONERNG_TIMEOUT  	1000	/* ms */
680667ff19Smpi 
690667ff19Smpi /*
700667ff19Smpi  * Define ONERNG_MEASURE_RATE to periodically log rate at which we provide
710667ff19Smpi  * random data to the kernel.
720667ff19Smpi  */
730667ff19Smpi #ifdef ONERNG_MEASURE_RATE
740667ff19Smpi #define ONERNG_RATE_SECONDS 30
750667ff19Smpi #endif
760667ff19Smpi 
770667ff19Smpi /* OneRNG operational modes */
780667ff19Smpi #define ONERNG_OP_ENABLE	"cmdO\n" /* start emitting data */
790667ff19Smpi #define ONERNG_OP_DISABLE	"cmdo\n" /* stop emitting data */
800667ff19Smpi #define ONERNG_OP_FLUSH_ENTROPY	"cmdw\n"
810667ff19Smpi 
820667ff19Smpi /* permits extracting the firmware in order to check the crypto signature */
830667ff19Smpi #define ONERNG_OP_EXTRACT_FIRMWARE "cmdX\n"
840667ff19Smpi 
850667ff19Smpi /*
860667ff19Smpi  * Noise sources include an avalache circuit and an RF circuit.
870667ff19Smpi  * There is also a whitener to provide a uniform distribution.
880667ff19Smpi  * Different combinations are possible.
890667ff19Smpi  */
900667ff19Smpi #define ONERNG_AVALANCHE_WHITENER	"cmd0\n" /* device default */
910667ff19Smpi #define ONERNG_AVALANCHE		"cmd1\n"
920667ff19Smpi #define ONERNG_AVALANCHE_RF_WHITENER	"cmd2\n"
930667ff19Smpi #define ONERNG_AVALANCHE_RF		"cmd3\n"
940667ff19Smpi #define ONERNG_SILENT			"cmd4\n" /* none; necessary for cmdX */
950667ff19Smpi #define ONERNG_SILENT2			"cmd5\n"
960667ff19Smpi #define ONERNG_RF_WHITENER		"cmd6\n"
970667ff19Smpi #define ONERNG_RF			"cmd7\n"
980667ff19Smpi 
990667ff19Smpi 
1000667ff19Smpi #define ONERNG_IFACE_CTRL_INDEX	0
1010667ff19Smpi #define ONERNG_IFACE_DATA_INDEX	1
1020667ff19Smpi 
1030667ff19Smpi #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)
1040667ff19Smpi 
1050667ff19Smpi struct uonerng_softc {
1060667ff19Smpi 	struct	  device sc_dev;
1070667ff19Smpi 	struct	  usbd_device *sc_udev;
1080667ff19Smpi 
1090667ff19Smpi 	int	  sc_ctl_iface_no;			/* control */
1100667ff19Smpi 	struct	  usbd_interface *sc_data_iface;	/* data */
1110667ff19Smpi 
1120667ff19Smpi 	struct	  usbd_pipe *sc_inpipe;
1130667ff19Smpi 	struct	  usbd_pipe *sc_outpipe;
1140667ff19Smpi 
1150667ff19Smpi 	struct	  timeout sc_timeout;
1160667ff19Smpi 	struct	  usb_task sc_task;
1170667ff19Smpi 	struct	  usbd_xfer *sc_xfer;
1180667ff19Smpi 	int      *sc_buf;
1190667ff19Smpi #ifdef ONERNG_MEASURE_RATE
1200667ff19Smpi 	struct	  timeval sc_start;
1210667ff19Smpi 	struct	  timeval sc_cur;
1220667ff19Smpi 	int	  sc_counted_bytes;
1230667ff19Smpi #endif
1240667ff19Smpi 	u_char	  sc_dtr;			/* current DTR state */
1250667ff19Smpi 	u_char	  sc_rts;			/* current RTS state */
1260667ff19Smpi 	u_char	  sc_first_run;
1270667ff19Smpi };
1280667ff19Smpi 
1290667ff19Smpi int uonerng_match(struct device *, void *, void *);
1300667ff19Smpi void uonerng_attach(struct device *, struct device *, void *);
1310667ff19Smpi int uonerng_detach(struct device *, int);
1320667ff19Smpi void uonerng_task(void *);
1330667ff19Smpi void uonerng_timeout(void *);
1340667ff19Smpi int uonerng_enable(struct uonerng_softc *sc);
1350667ff19Smpi void uonerng_cleanup(struct uonerng_softc *sc);
1360667ff19Smpi usbd_status uonerng_set_line_state(struct uonerng_softc *sc);
1370667ff19Smpi usbd_status uonerng_rts(struct uonerng_softc *sc, int onoff);
1380667ff19Smpi 
1390667ff19Smpi struct cfdriver uonerng_cd = {
1400667ff19Smpi 	NULL, "uonerng", DV_DULL
1410667ff19Smpi };
1420667ff19Smpi 
1430667ff19Smpi const struct cfattach uonerng_ca = {
1440667ff19Smpi 	sizeof(struct uonerng_softc), uonerng_match, uonerng_attach, uonerng_detach
1450667ff19Smpi };
1460667ff19Smpi 
1470667ff19Smpi int
1480667ff19Smpi uonerng_match(struct device *parent, void *match, void *aux)
1490667ff19Smpi {
1500667ff19Smpi 	struct usb_attach_arg *uaa = aux;
1510667ff19Smpi 
152*c0d38480Smpi 	if (uaa->iface == NULL)
1530667ff19Smpi 		return UMATCH_NONE;
1540667ff19Smpi 
1550667ff19Smpi 	if (uaa->vendor != USB_VENDOR_OPENMOKO2 ||
1560667ff19Smpi 	    uaa->product != USB_PRODUCT_OPENMOKO2_ONERNG)
1570667ff19Smpi 		return UMATCH_NONE;
1580667ff19Smpi 
1590667ff19Smpi 	return UMATCH_VENDOR_PRODUCT;
1600667ff19Smpi }
1610667ff19Smpi 
1620667ff19Smpi void
1630667ff19Smpi uonerng_attach(struct device *parent, struct device *self, void *aux)
1640667ff19Smpi {
1650667ff19Smpi 	struct uonerng_softc *sc = (struct uonerng_softc *)self;
1660667ff19Smpi 	struct usb_attach_arg *uaa = aux;
1670667ff19Smpi 	struct usbd_interface *iface = uaa->iface;
1680667ff19Smpi 	usb_interface_descriptor_t *id;
1690667ff19Smpi 	usb_endpoint_descriptor_t *ed;
1700667ff19Smpi 	int ep_ibulk = -1, ep_obulk = -1;
1710667ff19Smpi 	usbd_status err;
1720667ff19Smpi 	int i;
1730667ff19Smpi 
1740667ff19Smpi 	sc->sc_udev = uaa->device;
1750667ff19Smpi 	sc->sc_dtr = -1;
1760667ff19Smpi 	sc->sc_rts = -1;
1770667ff19Smpi 	sc->sc_first_run = 1;
1780667ff19Smpi 
1790667ff19Smpi 	usb_init_task(&sc->sc_task, uonerng_task, sc, USB_TASK_TYPE_GENERIC);
1800667ff19Smpi 
1810667ff19Smpi 	/* locate the control interface number and the data interface */
1820667ff19Smpi 	err = usbd_device2interface_handle(sc->sc_udev,
1830667ff19Smpi 	    ONERNG_IFACE_CTRL_INDEX, &iface);
1840667ff19Smpi 	if (err || iface == NULL) {
1850667ff19Smpi 		printf("%s: failed to locate control interface, err=%s\n",
1860667ff19Smpi 		    DEVNAME(sc), usbd_errstr(err));
1870667ff19Smpi 		goto fail;
1880667ff19Smpi 	}
1890667ff19Smpi 	id = usbd_get_interface_descriptor(iface);
1900667ff19Smpi 	if (id != NULL &&
1910667ff19Smpi 	    id->bInterfaceClass == UICLASS_CDC &&
1920667ff19Smpi 	    id->bInterfaceSubClass == UISUBCLASS_ABSTRACT_CONTROL_MODEL &&
1930667ff19Smpi 	    id->bInterfaceProtocol == UIPROTO_CDC_AT) {
1940667ff19Smpi 		sc->sc_ctl_iface_no = id->bInterfaceNumber;
1950667ff19Smpi 	} else {
1960667ff19Smpi 		printf("%s: control interface number not found\n",
1970667ff19Smpi 		    DEVNAME(sc));
1980667ff19Smpi 		goto fail;
1990667ff19Smpi 	}
2000667ff19Smpi 
2010667ff19Smpi 	err = usbd_device2interface_handle(sc->sc_udev,
2020667ff19Smpi 	    ONERNG_IFACE_DATA_INDEX, &sc->sc_data_iface);
2030667ff19Smpi 	if (err || sc->sc_data_iface == NULL) {
2040667ff19Smpi 		printf("%s: failed to locate data interface, err=%s\n",
2050667ff19Smpi 		    DEVNAME(sc), usbd_errstr(err));
2060667ff19Smpi 		goto fail;
2070667ff19Smpi 	}
2080667ff19Smpi 
2090667ff19Smpi 	/* Find the bulk endpoints */
2100667ff19Smpi 	id = usbd_get_interface_descriptor(sc->sc_data_iface);
2110667ff19Smpi 	if (id == NULL ||
2120667ff19Smpi 	    id->bInterfaceClass != UICLASS_CDC_DATA ||
2130667ff19Smpi 	    id->bInterfaceSubClass != UISUBCLASS_DATA) {
2140667ff19Smpi 		printf("%s: no data interface descriptor\n", DEVNAME(sc));
2150667ff19Smpi 		goto fail;
2160667ff19Smpi 	}
2170667ff19Smpi 	for (i = 0; i < id->bNumEndpoints; i++) {
2180667ff19Smpi 		ed = usbd_interface2endpoint_descriptor(sc->sc_data_iface, i);
2190667ff19Smpi 		if (ed == NULL) {
2200667ff19Smpi 			printf("%s: no endpoint descriptor for %d\n",
2210667ff19Smpi 			    DEVNAME(sc), i);
2220667ff19Smpi 			goto fail;
2230667ff19Smpi 		}
2240667ff19Smpi 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
2250667ff19Smpi 		    (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
2260667ff19Smpi                         ep_ibulk = ed->bEndpointAddress;
2270667ff19Smpi                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
2280667ff19Smpi 			   (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
2290667ff19Smpi                         ep_obulk = ed->bEndpointAddress;
2300667ff19Smpi                 }
2310667ff19Smpi         }
2320667ff19Smpi 
2330667ff19Smpi 	if (ep_ibulk == -1) {
2340667ff19Smpi 		printf("%s: Could not find data bulk in\n", DEVNAME(sc));
2350667ff19Smpi 		goto fail;
2360667ff19Smpi 	}
2370667ff19Smpi 	if (ep_obulk == -1) {
2380667ff19Smpi 		printf("%s: Could not find data bulk out\n", DEVNAME(sc));
2390667ff19Smpi 		goto fail;
2400667ff19Smpi 	}
2410667ff19Smpi 
2420667ff19Smpi 	/* Open pipes */
2430667ff19Smpi 	err = usbd_open_pipe(sc->sc_data_iface, ep_ibulk,
2440667ff19Smpi 	    USBD_EXCLUSIVE_USE, &sc->sc_inpipe);
2450667ff19Smpi 	if (err) {
2460667ff19Smpi 		printf("%s: failed to open bulk-in pipe: %s\n",
2470667ff19Smpi 		    DEVNAME(sc), usbd_errstr(err));
2480667ff19Smpi 		goto fail;
2490667ff19Smpi 	}
2500667ff19Smpi 	err = usbd_open_pipe(sc->sc_data_iface, ep_obulk,
2510667ff19Smpi 	    USBD_EXCLUSIVE_USE, &sc->sc_outpipe);
2520667ff19Smpi 	if (err) {
2530667ff19Smpi 		printf("%s: failed to open bulk-out pipe: %s\n",
2540667ff19Smpi 		    DEVNAME(sc), usbd_errstr(err));
2550667ff19Smpi 		goto fail;
2560667ff19Smpi 	}
2570667ff19Smpi 
2580667ff19Smpi 	/* Allocate xfer/buffer for bulk transfers */
2590667ff19Smpi 	sc->sc_xfer = usbd_alloc_xfer(sc->sc_udev);
2600667ff19Smpi 	if (sc->sc_xfer == NULL) {
2610667ff19Smpi 		printf("%s: could not alloc xfer\n", DEVNAME(sc));
2620667ff19Smpi 		goto fail;
2630667ff19Smpi 	}
2640667ff19Smpi 	sc->sc_buf = usbd_alloc_buffer(sc->sc_xfer, ONERNG_BUFSIZ);
2650667ff19Smpi 	if (sc->sc_buf == NULL) {
2660667ff19Smpi 		printf("%s: could not alloc %d-byte buffer\n", DEVNAME(sc),
2670667ff19Smpi 		    ONERNG_BUFSIZ);
2680667ff19Smpi 		goto fail;
2690667ff19Smpi 	}
2700667ff19Smpi 
2710667ff19Smpi 	if (uonerng_enable(sc) != 0) {
2720667ff19Smpi 		goto fail;
2730667ff19Smpi 	}
2740667ff19Smpi 
2750667ff19Smpi 	timeout_set(&sc->sc_timeout, uonerng_timeout, sc);
2760667ff19Smpi 
2770667ff19Smpi 	/* get the initial random data as early as possible */
2780667ff19Smpi 	uonerng_task(sc);
2790667ff19Smpi 
2800667ff19Smpi 	usb_add_task(sc->sc_udev, &sc->sc_task);
2810667ff19Smpi 	return;
2820667ff19Smpi 
2830667ff19Smpi  fail:
2840667ff19Smpi 	usbd_deactivate(sc->sc_udev);
2850667ff19Smpi 	uonerng_cleanup(sc);
2860667ff19Smpi }
2870667ff19Smpi 
2880667ff19Smpi int
2890667ff19Smpi uonerng_enable(struct uonerng_softc *sc)
2900667ff19Smpi {
2910667ff19Smpi 	int err;
2920667ff19Smpi 
2930667ff19Smpi 	if ((err = uonerng_rts(sc, 0))) {
2940667ff19Smpi 		printf("%s: failed to clear RTS: %s\n", DEVNAME(sc),
2950667ff19Smpi 		    usbd_errstr(err));
2960667ff19Smpi 		return (1);
2970667ff19Smpi 	}
2980667ff19Smpi 
2990667ff19Smpi 	usbd_setup_xfer(sc->sc_xfer, sc->sc_outpipe, sc,
3000667ff19Smpi 	    ONERNG_AVALANCHE_WHITENER, sizeof(ONERNG_AVALANCHE_WHITENER),
3010667ff19Smpi 	    USBD_SYNCHRONOUS, ONERNG_TIMEOUT, NULL);
3020667ff19Smpi 	if ((err = usbd_transfer(sc->sc_xfer))) {
3030667ff19Smpi 		printf("%s: failed to set operating mode: %s\n",
3040667ff19Smpi 		    DEVNAME(sc), usbd_errstr(err));
3050667ff19Smpi 		return (1);
3060667ff19Smpi 	}
3070667ff19Smpi 
3080667ff19Smpi 	usbd_setup_xfer(sc->sc_xfer, sc->sc_outpipe, sc,
3090667ff19Smpi 	    ONERNG_OP_ENABLE, sizeof(ONERNG_OP_ENABLE),
3100667ff19Smpi 	    USBD_SYNCHRONOUS, ONERNG_TIMEOUT, NULL);
3110667ff19Smpi 	if ((err = usbd_transfer(sc->sc_xfer))) {
3120667ff19Smpi 		printf("%s: failed to enable device: %s\n",
3130667ff19Smpi 		    DEVNAME(sc), usbd_errstr(err));
3140667ff19Smpi 		return (1);
3150667ff19Smpi 	}
3160667ff19Smpi 
3170667ff19Smpi 	return (0);
3180667ff19Smpi }
3190667ff19Smpi 
3200667ff19Smpi int
3210667ff19Smpi uonerng_detach(struct device *self, int flags)
3220667ff19Smpi {
3230667ff19Smpi 	struct uonerng_softc *sc = (struct uonerng_softc *)self;
3240667ff19Smpi 
3250667ff19Smpi 	usb_rem_task(sc->sc_udev, &sc->sc_task);
3260667ff19Smpi 	if (timeout_initialized(&sc->sc_timeout)) {
3270667ff19Smpi 		timeout_del(&sc->sc_timeout);
3280667ff19Smpi 	}
3290667ff19Smpi 	uonerng_cleanup(sc);
3300667ff19Smpi 	return (0);
3310667ff19Smpi }
3320667ff19Smpi 
3330667ff19Smpi void
3340667ff19Smpi uonerng_cleanup(struct uonerng_softc *sc)
3350667ff19Smpi {
3360667ff19Smpi 	if (sc->sc_inpipe != NULL) {
3370667ff19Smpi 		usbd_close_pipe(sc->sc_inpipe);
3380667ff19Smpi 		sc->sc_inpipe = NULL;
3390667ff19Smpi 	}
3400667ff19Smpi 	if (sc->sc_outpipe != NULL) {
3410667ff19Smpi 		usbd_close_pipe(sc->sc_outpipe);
3420667ff19Smpi 		sc->sc_outpipe = NULL;
3430667ff19Smpi 	}
3440667ff19Smpi 
3450667ff19Smpi 	/* usbd_free_xfer will also free the buffer if necessary */
3460667ff19Smpi 	if (sc->sc_xfer != NULL) {
3470667ff19Smpi 		usbd_free_xfer(sc->sc_xfer);
3480667ff19Smpi 		sc->sc_xfer = NULL;
3490667ff19Smpi 	}
3500667ff19Smpi }
3510667ff19Smpi 
3520667ff19Smpi usbd_status
3530667ff19Smpi uonerng_rts(struct uonerng_softc *sc, int onoff)
3540667ff19Smpi {
3550667ff19Smpi 	if (sc->sc_rts == onoff)
3560667ff19Smpi 		return USBD_NORMAL_COMPLETION;
3570667ff19Smpi 	sc->sc_rts = onoff;
3580667ff19Smpi 
3590667ff19Smpi 	return uonerng_set_line_state(sc);
3600667ff19Smpi }
3610667ff19Smpi 
3620667ff19Smpi usbd_status
3630667ff19Smpi uonerng_set_line_state(struct uonerng_softc *sc)
3640667ff19Smpi {
3650667ff19Smpi 	usb_device_request_t req;
3660667ff19Smpi 	int ls;
3670667ff19Smpi 
3680667ff19Smpi 	ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) |
3690667ff19Smpi 	     (sc->sc_rts ? UCDC_LINE_RTS : 0);
3700667ff19Smpi 	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
3710667ff19Smpi 	req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
3720667ff19Smpi 	USETW(req.wValue, ls);
3730667ff19Smpi 	USETW(req.wIndex, sc->sc_ctl_iface_no);
3740667ff19Smpi 	USETW(req.wLength, 0);
3750667ff19Smpi 
3760667ff19Smpi 	return usbd_do_request(sc->sc_udev, &req, 0);
3770667ff19Smpi }
3780667ff19Smpi 
3790667ff19Smpi void
3800667ff19Smpi uonerng_task(void *arg)
3810667ff19Smpi {
3820667ff19Smpi 	struct uonerng_softc *sc = (struct uonerng_softc *) arg;
3830667ff19Smpi 	usbd_status error;
3840667ff19Smpi 	u_int32_t len, int_count, i;
3850667ff19Smpi #ifdef ONERNG_MEASURE_RATE
3860667ff19Smpi 	time_t elapsed;
3870667ff19Smpi 	int rate;
3880667ff19Smpi #endif
3890667ff19Smpi 
3900667ff19Smpi 	usbd_setup_xfer(sc->sc_xfer, sc->sc_inpipe, NULL, sc->sc_buf,
3910667ff19Smpi 	    ONERNG_BUFSIZ,
3920667ff19Smpi 	    USBD_SHORT_XFER_OK | USBD_SYNCHRONOUS | USBD_NO_COPY,
3930667ff19Smpi 	    ONERNG_TIMEOUT, NULL);
3940667ff19Smpi 	error = usbd_transfer(sc->sc_xfer);
3950667ff19Smpi 	if (error) {
3960667ff19Smpi 		printf("%s: xfer failed: %s\n", DEVNAME(sc),
3970667ff19Smpi 		    usbd_errstr(error));
3980667ff19Smpi 		goto bail;
3990667ff19Smpi 	}
4000667ff19Smpi 	usbd_get_xfer_status(sc->sc_xfer, NULL, NULL, &len, NULL);
4010667ff19Smpi 	if (len < sizeof(int)) {
4020667ff19Smpi 		printf("%s: xfer too short (%u bytes) - dropping\n",
4030667ff19Smpi 		    DEVNAME(sc), len);
4040667ff19Smpi 		goto bail;
4050667ff19Smpi 	}
4060667ff19Smpi 
4070667ff19Smpi #ifdef ONERNG_MEASURE_RATE
4080667ff19Smpi 	if (sc->sc_first_run) {
4090667ff19Smpi 		sc->sc_counted_bytes = 0;
4100667ff19Smpi 		getmicrotime(&(sc->sc_start));
4110667ff19Smpi 	}
4120667ff19Smpi 	sc->sc_counted_bytes += len;
4130667ff19Smpi 	getmicrotime(&(sc->sc_cur));
4140667ff19Smpi 	elapsed = sc->sc_cur.tv_sec - sc->sc_start.tv_sec;
4150667ff19Smpi 	if (elapsed >= ONERNG_RATE_SECONDS) {
4160667ff19Smpi 		rate = (8 * sc->sc_counted_bytes) / (elapsed * 1024);
4170667ff19Smpi 		printf("%s: transfer rate = %d kb/s\n", DEVNAME(sc), rate);
4180667ff19Smpi 
4190667ff19Smpi 		/* set up for next measurement */
4200667ff19Smpi 		sc->sc_counted_bytes = 0;
4210667ff19Smpi 		getmicrotime(&(sc->sc_start));
4220667ff19Smpi 	}
4230667ff19Smpi #endif
4240667ff19Smpi 
4250667ff19Smpi 	int_count = len / sizeof(int);
4260667ff19Smpi 	for (i = 0; i < int_count; i++) {
4270667ff19Smpi 		add_true_randomness(sc->sc_buf[i]);
4280667ff19Smpi 	}
4290667ff19Smpi bail:
4300667ff19Smpi 
4310667ff19Smpi 	if (sc->sc_first_run) {
4320667ff19Smpi 		sc->sc_first_run = 0;
4330667ff19Smpi 	} else {
4340667ff19Smpi 		timeout_add_msec(&sc->sc_timeout, ONERNG_MSECS);
4350667ff19Smpi 	}
4360667ff19Smpi }
4370667ff19Smpi 
4380667ff19Smpi void
4390667ff19Smpi uonerng_timeout(void *arg)
4400667ff19Smpi {
4410667ff19Smpi 	struct uonerng_softc *sc = arg;
4420667ff19Smpi 
4430667ff19Smpi 	usb_add_task(sc->sc_udev, &sc->sc_task);
4440667ff19Smpi }
445