/* Find the first bulk IN endpoint and its packet size */
res = usb_find_bulk_in_endpoint(altsetting, &epd); if (res) {
usb_dbg(interface, "no IN endpoint found"); return res;
}
/* get the interface from minor number and driver information */
interface = usb_find_interface(&chaoskey_driver, iminor(inode)); if (!interface) return -ENODEV;
usb_dbg(interface, "open");
dev = usb_get_intfdata(interface); if (!dev) {
usb_dbg(interface, "open (dev)"); return -ENODEV;
}
/* must be seen first before validity is announced */
smp_wmb();
dev->reading = false;
wake_up(&dev->wait_q);
}
/* Fill the buffer. Called with dev->lock held
*/ staticint _chaoskey_fill(struct chaoskey *dev)
{
DEFINE_WAIT(wait); int result; bool started;
usb_dbg(dev->interface, "fill");
/* Return immediately if someone called before the buffer was
* empty */ if (dev->valid != dev->used) {
usb_dbg(dev->interface, "not empty yet (valid %d used %d)",
dev->valid, dev->used); return0;
}
/* Bail if the device has been removed */ if (!dev->present) {
usb_dbg(dev->interface, "device not present"); return -ENODEV;
}
/* Make sure the device is awake */
result = usb_autopm_get_interface(dev->interface); if (result) {
usb_dbg(dev->interface, "wakeup failed (result %d)", result); return result;
}
dev->reading = true;
result = usb_submit_urb(dev->urb, GFP_KERNEL); if (result < 0) {
result = usb_translate_errors(result);
dev->reading = false; goto out;
}
/* The first read on the Alea takes a little under 2 seconds. *Readsafterthefirstreadtakeonlyafewmicroseconds *though.Presumablytheentropy-generatingcircuitneeds *timetorampup.So,wewaitlongeronthefirstread.
*/
started = dev->reads_started;
dev->reads_started = true;
result = wait_event_interruptible_timeout(
dev->wait_q,
!dev->reading,
(started ? NAK_TIMEOUT : ALEA_FIRST_TIMEOUT) );
if (result < 0) {
usb_kill_urb(dev->urb); goto out;
}
if (result == 0) {
result = -ETIMEDOUT;
usb_kill_urb(dev->urb);
} else {
result = dev->valid;
}
out: /* Let the device go back to sleep eventually */
usb_autopm_put_interface(dev->interface);
static ssize_t chaoskey_read(struct file *file, char __user *buffer,
size_t count,
loff_t *ppos)
{ struct chaoskey *dev;
ssize_t read_count = 0; int this_time; int result = 0; unsignedlong remain;
dev = file->private_data;
if (dev == NULL || !dev->present) return -ENODEV;
usb_dbg(dev->interface, "read %zu", count);
while (count > 0) {
/* Grab the rng_lock briefly to ensure that the hwrng interface *getspriorityoverotheruseraccess
*/
result = mutex_lock_interruptible(&dev->rng_lock); if (result) goto bail;
mutex_unlock(&dev->rng_lock);
result = mutex_lock_interruptible(&dev->lock); if (result) goto bail; if (dev->valid == dev->used) {
result = _chaoskey_fill(dev); if (result < 0) {
mutex_unlock(&dev->lock); goto bail;
}
}
usb_dbg(dev->interface, "rng_read max %zu wait %d", max, wait);
if (!dev->present) {
usb_dbg(dev->interface, "device not present"); return0;
}
/* Hold the rng_lock until we acquire the device lock so that *thisoperationgetspriorityoverotheruseraccesstothe *device
*/
mutex_lock(&dev->rng_lock);
mutex_lock(&dev->lock);
mutex_unlock(&dev->rng_lock);
/* Try to fill the buffer if empty. It doesn't actually matter *if_chaoskey_fillworks;we'lljustreturnzerobytesas *thebufferwillstillbeempty
*/ if (dev->valid == dev->used)
(void) _chaoskey_fill(dev);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.