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