1*81508fe3Sjsg /* $OpenBSD: uonerng.c,v 1.7 2024/05/23 03:21:09 jsg 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/timeout.h>
370667ff19Smpi #include <machine/bus.h>
380667ff19Smpi
390667ff19Smpi #include <dev/usb/usb.h>
400667ff19Smpi #include <dev/usb/usbdi.h>
410667ff19Smpi #include <dev/usb/usbdevs.h>
420667ff19Smpi #include <dev/usb/usbcdc.h>
430667ff19Smpi
440667ff19Smpi /*
450667ff19Smpi * The OneRNG is documented to provide ~350kbits/s of entropy at
460667ff19Smpi * ~7.8 bits/byte, and when used at a lower rate providing close
470667ff19Smpi * to 8 bits/byte.
480667ff19Smpi *
490667ff19Smpi * Although this driver is able to consume the data at the full rate,
500667ff19Smpi * we tune this down to 10kbit/s as the OpenBSD RNG is better off
510667ff19Smpi * with small amounts of input at a time so as to not saturate the
520667ff19Smpi * input queue and mute other sources of entropy.
530667ff19Smpi *
540667ff19Smpi * Furthermore, unlike other implementations, for us there is no benefit
550667ff19Smpi * to discarding the initial bytes retrieved from the OneRNG, regardless
560667ff19Smpi * of the quality of the data. (Empirical tests suggest that the initial
570667ff19Smpi * quality is fine, anyway.)
580667ff19Smpi */
590667ff19Smpi #define ONERNG_BUFSIZ 128
600667ff19Smpi #define ONERNG_MSECS 100
610667ff19Smpi
620667ff19Smpi #define ONERNG_TIMEOUT 1000 /* ms */
630667ff19Smpi
640667ff19Smpi /*
650667ff19Smpi * Define ONERNG_MEASURE_RATE to periodically log rate at which we provide
660667ff19Smpi * random data to the kernel.
670667ff19Smpi */
680667ff19Smpi #ifdef ONERNG_MEASURE_RATE
690667ff19Smpi #define ONERNG_RATE_SECONDS 30
700667ff19Smpi #endif
710667ff19Smpi
720667ff19Smpi /* OneRNG operational modes */
730667ff19Smpi #define ONERNG_OP_ENABLE "cmdO\n" /* start emitting data */
740667ff19Smpi #define ONERNG_OP_DISABLE "cmdo\n" /* stop emitting data */
750667ff19Smpi #define ONERNG_OP_FLUSH_ENTROPY "cmdw\n"
760667ff19Smpi
770667ff19Smpi /* permits extracting the firmware in order to check the crypto signature */
780667ff19Smpi #define ONERNG_OP_EXTRACT_FIRMWARE "cmdX\n"
790667ff19Smpi
800667ff19Smpi /*
814b1a56afSjsg * Noise sources include an avalanche circuit and an RF circuit.
820667ff19Smpi * There is also a whitener to provide a uniform distribution.
830667ff19Smpi * Different combinations are possible.
840667ff19Smpi */
850667ff19Smpi #define ONERNG_AVALANCHE_WHITENER "cmd0\n" /* device default */
860667ff19Smpi #define ONERNG_AVALANCHE "cmd1\n"
870667ff19Smpi #define ONERNG_AVALANCHE_RF_WHITENER "cmd2\n"
880667ff19Smpi #define ONERNG_AVALANCHE_RF "cmd3\n"
890667ff19Smpi #define ONERNG_SILENT "cmd4\n" /* none; necessary for cmdX */
900667ff19Smpi #define ONERNG_SILENT2 "cmd5\n"
910667ff19Smpi #define ONERNG_RF_WHITENER "cmd6\n"
920667ff19Smpi #define ONERNG_RF "cmd7\n"
930667ff19Smpi
940667ff19Smpi
950667ff19Smpi #define ONERNG_IFACE_CTRL_INDEX 0
960667ff19Smpi #define ONERNG_IFACE_DATA_INDEX 1
970667ff19Smpi
980667ff19Smpi #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)
990667ff19Smpi
1000667ff19Smpi struct uonerng_softc {
1010667ff19Smpi struct device sc_dev;
1020667ff19Smpi struct usbd_device *sc_udev;
1030667ff19Smpi
1040667ff19Smpi int sc_ctl_iface_no; /* control */
1050667ff19Smpi struct usbd_interface *sc_data_iface; /* data */
1060667ff19Smpi
1070667ff19Smpi struct usbd_pipe *sc_inpipe;
1080667ff19Smpi struct usbd_pipe *sc_outpipe;
1090667ff19Smpi
1100667ff19Smpi struct timeout sc_timeout;
1110667ff19Smpi struct usb_task sc_task;
1120667ff19Smpi struct usbd_xfer *sc_xfer;
1130667ff19Smpi int *sc_buf;
1140667ff19Smpi #ifdef ONERNG_MEASURE_RATE
1150667ff19Smpi struct timeval sc_start;
1160667ff19Smpi struct timeval sc_cur;
1170667ff19Smpi int sc_counted_bytes;
1180667ff19Smpi #endif
1190667ff19Smpi u_char sc_dtr; /* current DTR state */
1200667ff19Smpi u_char sc_rts; /* current RTS state */
1210667ff19Smpi u_char sc_first_run;
1220667ff19Smpi };
1230667ff19Smpi
1240667ff19Smpi int uonerng_match(struct device *, void *, void *);
1250667ff19Smpi void uonerng_attach(struct device *, struct device *, void *);
1260667ff19Smpi int uonerng_detach(struct device *, int);
1270667ff19Smpi void uonerng_task(void *);
1280667ff19Smpi void uonerng_timeout(void *);
1290667ff19Smpi int uonerng_enable(struct uonerng_softc *sc);
1300667ff19Smpi void uonerng_cleanup(struct uonerng_softc *sc);
1310667ff19Smpi usbd_status uonerng_set_line_state(struct uonerng_softc *sc);
1320667ff19Smpi usbd_status uonerng_rts(struct uonerng_softc *sc, int onoff);
1330667ff19Smpi
1340667ff19Smpi struct cfdriver uonerng_cd = {
1350667ff19Smpi NULL, "uonerng", DV_DULL
1360667ff19Smpi };
1370667ff19Smpi
1380667ff19Smpi const struct cfattach uonerng_ca = {
1390667ff19Smpi sizeof(struct uonerng_softc), uonerng_match, uonerng_attach, uonerng_detach
1400667ff19Smpi };
1410667ff19Smpi
1420667ff19Smpi int
uonerng_match(struct device * parent,void * match,void * aux)1430667ff19Smpi uonerng_match(struct device *parent, void *match, void *aux)
1440667ff19Smpi {
1450667ff19Smpi struct usb_attach_arg *uaa = aux;
1460667ff19Smpi
147c0d38480Smpi if (uaa->iface == NULL)
1480667ff19Smpi return UMATCH_NONE;
1490667ff19Smpi
1500667ff19Smpi if (uaa->vendor != USB_VENDOR_OPENMOKO2 ||
1510667ff19Smpi uaa->product != USB_PRODUCT_OPENMOKO2_ONERNG)
1520667ff19Smpi return UMATCH_NONE;
1530667ff19Smpi
1540667ff19Smpi return UMATCH_VENDOR_PRODUCT;
1550667ff19Smpi }
1560667ff19Smpi
1570667ff19Smpi void
uonerng_attach(struct device * parent,struct device * self,void * aux)1580667ff19Smpi uonerng_attach(struct device *parent, struct device *self, void *aux)
1590667ff19Smpi {
1600667ff19Smpi struct uonerng_softc *sc = (struct uonerng_softc *)self;
1610667ff19Smpi struct usb_attach_arg *uaa = aux;
1620667ff19Smpi struct usbd_interface *iface = uaa->iface;
1630667ff19Smpi usb_interface_descriptor_t *id;
1640667ff19Smpi usb_endpoint_descriptor_t *ed;
1650667ff19Smpi int ep_ibulk = -1, ep_obulk = -1;
1660667ff19Smpi usbd_status err;
1670667ff19Smpi int i;
1680667ff19Smpi
1690667ff19Smpi sc->sc_udev = uaa->device;
1700667ff19Smpi sc->sc_dtr = -1;
1710667ff19Smpi sc->sc_rts = -1;
1720667ff19Smpi sc->sc_first_run = 1;
1730667ff19Smpi
1740667ff19Smpi usb_init_task(&sc->sc_task, uonerng_task, sc, USB_TASK_TYPE_GENERIC);
1750667ff19Smpi
1760667ff19Smpi /* locate the control interface number and the data interface */
1770667ff19Smpi err = usbd_device2interface_handle(sc->sc_udev,
1780667ff19Smpi ONERNG_IFACE_CTRL_INDEX, &iface);
1790667ff19Smpi if (err || iface == NULL) {
1800667ff19Smpi printf("%s: failed to locate control interface, err=%s\n",
1810667ff19Smpi DEVNAME(sc), usbd_errstr(err));
1820667ff19Smpi goto fail;
1830667ff19Smpi }
1840667ff19Smpi id = usbd_get_interface_descriptor(iface);
1850667ff19Smpi if (id != NULL &&
1860667ff19Smpi id->bInterfaceClass == UICLASS_CDC &&
1870667ff19Smpi id->bInterfaceSubClass == UISUBCLASS_ABSTRACT_CONTROL_MODEL &&
1880667ff19Smpi id->bInterfaceProtocol == UIPROTO_CDC_AT) {
1890667ff19Smpi sc->sc_ctl_iface_no = id->bInterfaceNumber;
1900667ff19Smpi } else {
1910667ff19Smpi printf("%s: control interface number not found\n",
1920667ff19Smpi DEVNAME(sc));
1930667ff19Smpi goto fail;
1940667ff19Smpi }
1950667ff19Smpi
1960667ff19Smpi err = usbd_device2interface_handle(sc->sc_udev,
1970667ff19Smpi ONERNG_IFACE_DATA_INDEX, &sc->sc_data_iface);
1980667ff19Smpi if (err || sc->sc_data_iface == NULL) {
1990667ff19Smpi printf("%s: failed to locate data interface, err=%s\n",
2000667ff19Smpi DEVNAME(sc), usbd_errstr(err));
2010667ff19Smpi goto fail;
2020667ff19Smpi }
2030667ff19Smpi
2040667ff19Smpi /* Find the bulk endpoints */
2050667ff19Smpi id = usbd_get_interface_descriptor(sc->sc_data_iface);
2060667ff19Smpi if (id == NULL ||
2070667ff19Smpi id->bInterfaceClass != UICLASS_CDC_DATA ||
2080667ff19Smpi id->bInterfaceSubClass != UISUBCLASS_DATA) {
2090667ff19Smpi printf("%s: no data interface descriptor\n", DEVNAME(sc));
2100667ff19Smpi goto fail;
2110667ff19Smpi }
2120667ff19Smpi for (i = 0; i < id->bNumEndpoints; i++) {
2130667ff19Smpi ed = usbd_interface2endpoint_descriptor(sc->sc_data_iface, i);
2140667ff19Smpi if (ed == NULL) {
2150667ff19Smpi printf("%s: no endpoint descriptor for %d\n",
2160667ff19Smpi DEVNAME(sc), i);
2170667ff19Smpi goto fail;
2180667ff19Smpi }
2190667ff19Smpi if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
220a222a8f6Sjasper UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
2210667ff19Smpi ep_ibulk = ed->bEndpointAddress;
2220667ff19Smpi } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
223a222a8f6Sjasper UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
2240667ff19Smpi ep_obulk = ed->bEndpointAddress;
2250667ff19Smpi }
2260667ff19Smpi }
2270667ff19Smpi
2280667ff19Smpi if (ep_ibulk == -1) {
2290667ff19Smpi printf("%s: Could not find data bulk in\n", DEVNAME(sc));
2300667ff19Smpi goto fail;
2310667ff19Smpi }
2320667ff19Smpi if (ep_obulk == -1) {
2330667ff19Smpi printf("%s: Could not find data bulk out\n", DEVNAME(sc));
2340667ff19Smpi goto fail;
2350667ff19Smpi }
2360667ff19Smpi
2370667ff19Smpi /* Open pipes */
2380667ff19Smpi err = usbd_open_pipe(sc->sc_data_iface, ep_ibulk,
2390667ff19Smpi USBD_EXCLUSIVE_USE, &sc->sc_inpipe);
2400667ff19Smpi if (err) {
2410667ff19Smpi printf("%s: failed to open bulk-in pipe: %s\n",
2420667ff19Smpi DEVNAME(sc), usbd_errstr(err));
2430667ff19Smpi goto fail;
2440667ff19Smpi }
2450667ff19Smpi err = usbd_open_pipe(sc->sc_data_iface, ep_obulk,
2460667ff19Smpi USBD_EXCLUSIVE_USE, &sc->sc_outpipe);
2470667ff19Smpi if (err) {
2480667ff19Smpi printf("%s: failed to open bulk-out pipe: %s\n",
2490667ff19Smpi DEVNAME(sc), usbd_errstr(err));
2500667ff19Smpi goto fail;
2510667ff19Smpi }
2520667ff19Smpi
2530667ff19Smpi /* Allocate xfer/buffer for bulk transfers */
2540667ff19Smpi sc->sc_xfer = usbd_alloc_xfer(sc->sc_udev);
2550667ff19Smpi if (sc->sc_xfer == NULL) {
2560667ff19Smpi printf("%s: could not alloc xfer\n", DEVNAME(sc));
2570667ff19Smpi goto fail;
2580667ff19Smpi }
2590667ff19Smpi sc->sc_buf = usbd_alloc_buffer(sc->sc_xfer, ONERNG_BUFSIZ);
2600667ff19Smpi if (sc->sc_buf == NULL) {
2610667ff19Smpi printf("%s: could not alloc %d-byte buffer\n", DEVNAME(sc),
2620667ff19Smpi ONERNG_BUFSIZ);
2630667ff19Smpi goto fail;
2640667ff19Smpi }
2650667ff19Smpi
2660667ff19Smpi if (uonerng_enable(sc) != 0) {
2670667ff19Smpi goto fail;
2680667ff19Smpi }
2690667ff19Smpi
2700667ff19Smpi timeout_set(&sc->sc_timeout, uonerng_timeout, sc);
2710667ff19Smpi
2720667ff19Smpi /* get the initial random data as early as possible */
2730667ff19Smpi uonerng_task(sc);
2740667ff19Smpi
2750667ff19Smpi usb_add_task(sc->sc_udev, &sc->sc_task);
2760667ff19Smpi return;
2770667ff19Smpi
2780667ff19Smpi fail:
2790667ff19Smpi usbd_deactivate(sc->sc_udev);
2800667ff19Smpi uonerng_cleanup(sc);
2810667ff19Smpi }
2820667ff19Smpi
2830667ff19Smpi int
uonerng_enable(struct uonerng_softc * sc)2840667ff19Smpi uonerng_enable(struct uonerng_softc *sc)
2850667ff19Smpi {
2860667ff19Smpi int err;
2870667ff19Smpi
2880667ff19Smpi if ((err = uonerng_rts(sc, 0))) {
2890667ff19Smpi printf("%s: failed to clear RTS: %s\n", DEVNAME(sc),
2900667ff19Smpi usbd_errstr(err));
2910667ff19Smpi return (1);
2920667ff19Smpi }
2930667ff19Smpi
2940667ff19Smpi usbd_setup_xfer(sc->sc_xfer, sc->sc_outpipe, sc,
2950667ff19Smpi ONERNG_AVALANCHE_WHITENER, sizeof(ONERNG_AVALANCHE_WHITENER),
2960667ff19Smpi USBD_SYNCHRONOUS, ONERNG_TIMEOUT, NULL);
2970667ff19Smpi if ((err = usbd_transfer(sc->sc_xfer))) {
2980667ff19Smpi printf("%s: failed to set operating mode: %s\n",
2990667ff19Smpi DEVNAME(sc), usbd_errstr(err));
3000667ff19Smpi return (1);
3010667ff19Smpi }
3020667ff19Smpi
3030667ff19Smpi usbd_setup_xfer(sc->sc_xfer, sc->sc_outpipe, sc,
3040667ff19Smpi ONERNG_OP_ENABLE, sizeof(ONERNG_OP_ENABLE),
3050667ff19Smpi USBD_SYNCHRONOUS, ONERNG_TIMEOUT, NULL);
3060667ff19Smpi if ((err = usbd_transfer(sc->sc_xfer))) {
3070667ff19Smpi printf("%s: failed to enable device: %s\n",
3080667ff19Smpi DEVNAME(sc), usbd_errstr(err));
3090667ff19Smpi return (1);
3100667ff19Smpi }
3110667ff19Smpi
3120667ff19Smpi return (0);
3130667ff19Smpi }
3140667ff19Smpi
3150667ff19Smpi int
uonerng_detach(struct device * self,int flags)3160667ff19Smpi uonerng_detach(struct device *self, int flags)
3170667ff19Smpi {
3180667ff19Smpi struct uonerng_softc *sc = (struct uonerng_softc *)self;
3190667ff19Smpi
3200667ff19Smpi usb_rem_task(sc->sc_udev, &sc->sc_task);
3210667ff19Smpi if (timeout_initialized(&sc->sc_timeout)) {
3220667ff19Smpi timeout_del(&sc->sc_timeout);
3230667ff19Smpi }
3240667ff19Smpi uonerng_cleanup(sc);
3250667ff19Smpi return (0);
3260667ff19Smpi }
3270667ff19Smpi
3280667ff19Smpi void
uonerng_cleanup(struct uonerng_softc * sc)3290667ff19Smpi uonerng_cleanup(struct uonerng_softc *sc)
3300667ff19Smpi {
3310667ff19Smpi if (sc->sc_inpipe != NULL) {
3320667ff19Smpi usbd_close_pipe(sc->sc_inpipe);
3330667ff19Smpi sc->sc_inpipe = NULL;
3340667ff19Smpi }
3350667ff19Smpi if (sc->sc_outpipe != NULL) {
3360667ff19Smpi usbd_close_pipe(sc->sc_outpipe);
3370667ff19Smpi sc->sc_outpipe = NULL;
3380667ff19Smpi }
3390667ff19Smpi
3400667ff19Smpi /* usbd_free_xfer will also free the buffer if necessary */
3410667ff19Smpi if (sc->sc_xfer != NULL) {
3420667ff19Smpi usbd_free_xfer(sc->sc_xfer);
3430667ff19Smpi sc->sc_xfer = NULL;
3440667ff19Smpi }
3450667ff19Smpi }
3460667ff19Smpi
3470667ff19Smpi usbd_status
uonerng_rts(struct uonerng_softc * sc,int onoff)3480667ff19Smpi uonerng_rts(struct uonerng_softc *sc, int onoff)
3490667ff19Smpi {
3500667ff19Smpi if (sc->sc_rts == onoff)
3510667ff19Smpi return USBD_NORMAL_COMPLETION;
3520667ff19Smpi sc->sc_rts = onoff;
3530667ff19Smpi
3540667ff19Smpi return uonerng_set_line_state(sc);
3550667ff19Smpi }
3560667ff19Smpi
3570667ff19Smpi usbd_status
uonerng_set_line_state(struct uonerng_softc * sc)3580667ff19Smpi uonerng_set_line_state(struct uonerng_softc *sc)
3590667ff19Smpi {
3600667ff19Smpi usb_device_request_t req;
3610667ff19Smpi int ls;
3620667ff19Smpi
3630667ff19Smpi ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) |
3640667ff19Smpi (sc->sc_rts ? UCDC_LINE_RTS : 0);
3650667ff19Smpi req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
3660667ff19Smpi req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
3670667ff19Smpi USETW(req.wValue, ls);
3680667ff19Smpi USETW(req.wIndex, sc->sc_ctl_iface_no);
3690667ff19Smpi USETW(req.wLength, 0);
3700667ff19Smpi
3710667ff19Smpi return usbd_do_request(sc->sc_udev, &req, 0);
3720667ff19Smpi }
3730667ff19Smpi
3740667ff19Smpi void
uonerng_task(void * arg)3750667ff19Smpi uonerng_task(void *arg)
3760667ff19Smpi {
3770667ff19Smpi struct uonerng_softc *sc = (struct uonerng_softc *) arg;
3780667ff19Smpi usbd_status error;
3790667ff19Smpi u_int32_t len, int_count, i;
3800667ff19Smpi #ifdef ONERNG_MEASURE_RATE
3810667ff19Smpi time_t elapsed;
3820667ff19Smpi int rate;
3830667ff19Smpi #endif
3840667ff19Smpi
3850667ff19Smpi usbd_setup_xfer(sc->sc_xfer, sc->sc_inpipe, NULL, sc->sc_buf,
3860667ff19Smpi ONERNG_BUFSIZ,
3870667ff19Smpi USBD_SHORT_XFER_OK | USBD_SYNCHRONOUS | USBD_NO_COPY,
3880667ff19Smpi ONERNG_TIMEOUT, NULL);
3890667ff19Smpi error = usbd_transfer(sc->sc_xfer);
3900667ff19Smpi if (error) {
3910667ff19Smpi printf("%s: xfer failed: %s\n", DEVNAME(sc),
3920667ff19Smpi usbd_errstr(error));
3930667ff19Smpi goto bail;
3940667ff19Smpi }
3950667ff19Smpi usbd_get_xfer_status(sc->sc_xfer, NULL, NULL, &len, NULL);
3960667ff19Smpi if (len < sizeof(int)) {
3970667ff19Smpi printf("%s: xfer too short (%u bytes) - dropping\n",
3980667ff19Smpi DEVNAME(sc), len);
3990667ff19Smpi goto bail;
4000667ff19Smpi }
4010667ff19Smpi
4020667ff19Smpi #ifdef ONERNG_MEASURE_RATE
4030667ff19Smpi if (sc->sc_first_run) {
4040667ff19Smpi sc->sc_counted_bytes = 0;
4050667ff19Smpi getmicrotime(&(sc->sc_start));
4060667ff19Smpi }
4070667ff19Smpi sc->sc_counted_bytes += len;
4080667ff19Smpi getmicrotime(&(sc->sc_cur));
4090667ff19Smpi elapsed = sc->sc_cur.tv_sec - sc->sc_start.tv_sec;
4100667ff19Smpi if (elapsed >= ONERNG_RATE_SECONDS) {
4110667ff19Smpi rate = (8 * sc->sc_counted_bytes) / (elapsed * 1024);
4120667ff19Smpi printf("%s: transfer rate = %d kb/s\n", DEVNAME(sc), rate);
4130667ff19Smpi
4140667ff19Smpi /* set up for next measurement */
4150667ff19Smpi sc->sc_counted_bytes = 0;
4160667ff19Smpi getmicrotime(&(sc->sc_start));
4170667ff19Smpi }
4180667ff19Smpi #endif
4190667ff19Smpi
4200667ff19Smpi int_count = len / sizeof(int);
4210667ff19Smpi for (i = 0; i < int_count; i++) {
4229e9abf5bSjasper enqueue_randomness(sc->sc_buf[i]);
4230667ff19Smpi }
4240667ff19Smpi bail:
4250667ff19Smpi
4260667ff19Smpi if (sc->sc_first_run) {
4270667ff19Smpi sc->sc_first_run = 0;
4280667ff19Smpi } else {
4290667ff19Smpi timeout_add_msec(&sc->sc_timeout, ONERNG_MSECS);
4300667ff19Smpi }
4310667ff19Smpi }
4320667ff19Smpi
4330667ff19Smpi void
uonerng_timeout(void * arg)4340667ff19Smpi uonerng_timeout(void *arg)
4350667ff19Smpi {
4360667ff19Smpi struct uonerng_softc *sc = arg;
4370667ff19Smpi
4380667ff19Smpi usb_add_task(sc->sc_udev, &sc->sc_task);
4390667ff19Smpi }
440