mirror of
https://github.com/polhenarejos/pico-rng.git
synced 2026-06-11 04:48:17 +02:00
Driver exposes a character device /dev/pico_rng. Updated driver to support the character device. Tested with dd and cat. I am getting better performance than with Python, no shocker there.
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
#include <linux/semaphore.h>
|
#include <linux/semaphore.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_AUTHOR("Mickey Malone");
|
MODULE_AUTHOR("Mickey Malone");
|
||||||
MODULE_DESCRIPTION("Random number generator using a Raspberry Pi Pico");
|
MODULE_DESCRIPTION("Random number generator using a Raspberry Pi Pico");
|
||||||
@@ -21,7 +22,6 @@ MODULE_VERSION("1.0");
|
|||||||
**/
|
**/
|
||||||
#define VENDOR_ID 0x0
|
#define VENDOR_ID 0x0
|
||||||
#define PRODUCT_ID 0x4
|
#define PRODUCT_ID 0x4
|
||||||
#define SC_MINOR_BASE 31
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper macros
|
* Helper macros
|
||||||
@@ -35,6 +35,21 @@ static int debug = 0;
|
|||||||
module_param(debug, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
module_param(debug, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||||
MODULE_PARM_DESC(debug, "Set the log level to debug");
|
MODULE_PARM_DESC(debug, "Set the log level to debug");
|
||||||
|
|
||||||
|
static int timeout = 500;
|
||||||
|
module_param(timeout, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||||
|
MODULE_PARM_DESC(timeout, "Set the read timeout for the pico rng usb device");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main data structure for this module
|
||||||
|
**/
|
||||||
|
struct pico_rng_data {
|
||||||
|
struct usb_device *dev;
|
||||||
|
struct usb_interface *interface;
|
||||||
|
struct usb_endpoint_descriptor *endpoint;
|
||||||
|
char *buffer;
|
||||||
|
int pipe;
|
||||||
|
} module_data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prototype Functions
|
* Prototype Functions
|
||||||
**/
|
**/
|
||||||
@@ -43,13 +58,8 @@ static void pico_rng_usb_disconnect(struct usb_interface *interface);
|
|||||||
static int __init pico_rng_driver_init(void);
|
static int __init pico_rng_driver_init(void);
|
||||||
static void __exit pico_rng_driver_exit(void);
|
static void __exit pico_rng_driver_exit(void);
|
||||||
|
|
||||||
/**
|
static ssize_t pico_rng_read(struct file *file, char __user *user_buffer, size_t size, loff_t *offset);
|
||||||
static int pico_rng_open(struct inode *inode, struct file *file);
|
static int pico_rng_open(struct inode *inode, struct file *file);
|
||||||
static int pico_rng_release(struct inode *inode, struct file *file);
|
|
||||||
static ssize_t pico_rng_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos);
|
|
||||||
static ssize_t pico_rng_read(struct file *file, char __user *user, size_t count, loff_t *ppos);
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data structure of the USB vid:pid device that we will support
|
* Data structure of the USB vid:pid device that we will support
|
||||||
@@ -73,13 +83,63 @@ static struct usb_driver pico_rng_usb_driver = {
|
|||||||
* File operations data structure for the character device
|
* File operations data structure for the character device
|
||||||
* that will be implemented in this module
|
* that will be implemented in this module
|
||||||
**/
|
**/
|
||||||
/**static struct file_operations pico_rng_fops = {
|
static struct file_operations pico_rng_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.open = pico_rng_open,
|
|
||||||
.read = pico_rng_read,
|
.read = pico_rng_read,
|
||||||
.release = pico_rng_release,
|
.open = pico_rng_open,
|
||||||
};
|
};
|
||||||
**/
|
|
||||||
|
/**
|
||||||
|
* USB class data structure
|
||||||
|
**/
|
||||||
|
struct usb_class_driver pico_rng_usb_class = {
|
||||||
|
.name = "pico_rng",
|
||||||
|
.fops = &pico_rng_fops,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File ops:open
|
||||||
|
**/
|
||||||
|
static int pico_rng_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
LOGGER_DEBUG("inside pico_rng_open with inode %p file %p\n", inode, file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File ops:read
|
||||||
|
**/
|
||||||
|
static ssize_t pico_rng_read(struct file *file, char __user *user_buffer, size_t size, loff_t *offset)
|
||||||
|
{
|
||||||
|
int actual_length = 0;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
LOGGER_DEBUG("inside pico_rng_read with file %p, user_buffer %p, size %ld, offset %lld\n", file, user_buffer, size, *offset);
|
||||||
|
|
||||||
|
// int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout)
|
||||||
|
LOGGER_DEBUG("Calling usb_bulk_msg dev %p, pipe %d, buffer %p, size %d, and timeout %d", \
|
||||||
|
module_data.dev, module_data.pipe, module_data.buffer, module_data.endpoint->wMaxPacketSize, timeout);
|
||||||
|
|
||||||
|
retval = usb_bulk_msg(module_data.dev,
|
||||||
|
module_data.pipe,
|
||||||
|
module_data.buffer,
|
||||||
|
module_data.endpoint->wMaxPacketSize,
|
||||||
|
&actual_length,
|
||||||
|
timeout);
|
||||||
|
|
||||||
|
if(retval)
|
||||||
|
{
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER_DEBUG("Copying %d bytest of random data to userspace with offset %lld\n", actual_length, *offset);
|
||||||
|
if(copy_to_user(user_buffer, module_data.buffer, module_data.endpoint->wMaxPacketSize))
|
||||||
|
{
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return module_data.endpoint->wMaxPacketSize;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* USB: Probe
|
* USB: Probe
|
||||||
@@ -87,45 +147,50 @@ static struct usb_driver pico_rng_usb_driver = {
|
|||||||
**/
|
**/
|
||||||
static int pico_rng_usb_probe(struct usb_interface *interface, const struct usb_device_id *id)
|
static int pico_rng_usb_probe(struct usb_interface *interface, const struct usb_device_id *id)
|
||||||
{
|
{
|
||||||
struct usb_device *dev = interface_to_usbdev(interface);
|
|
||||||
struct usb_endpoint_descriptor *endpoint = NULL;
|
|
||||||
int retval = -ENODEV;
|
int retval = -ENODEV;
|
||||||
char *buffer;
|
|
||||||
int actual_length;
|
|
||||||
int pipe = 0;
|
|
||||||
|
|
||||||
retval = usb_find_bulk_in_endpoint(interface->cur_altsetting, &endpoint);
|
module_data.dev = interface_to_usbdev(interface);
|
||||||
|
if(!module_data.dev)
|
||||||
|
{
|
||||||
|
LOGGER_ERR("Unable to locate usb device");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
module_data.interface = interface;
|
||||||
|
if(!module_data.interface)
|
||||||
|
{
|
||||||
|
LOGGER_ERR("Invalid interface");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = usb_find_bulk_in_endpoint(module_data.interface->cur_altsetting, &(module_data.endpoint));
|
||||||
if(retval)
|
if(retval)
|
||||||
{
|
{
|
||||||
LOGGER_ERR("Unable to find bulk endpoint %d\n", retval);
|
LOGGER_ERR("Unable to find bulk endpoint %d\n", retval);
|
||||||
return(retval);
|
return(retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
pipe = usb_rcvbulkpipe(dev, endpoint->bEndpointAddress);
|
module_data.pipe = usb_rcvbulkpipe(module_data.dev, module_data.endpoint->bEndpointAddress);
|
||||||
|
|
||||||
LOGGER_DEBUG("endpoint found %p with pipe %d", endpoint, pipe);
|
LOGGER_DEBUG("endpoint found %p with pipe %d", module_data.endpoint, module_data.pipe);
|
||||||
|
|
||||||
buffer = kmalloc(endpoint->wMaxPacketSize, GFP_KERNEL);
|
module_data.buffer = NULL;
|
||||||
|
module_data.buffer = kmalloc(module_data.endpoint->wMaxPacketSize, GFP_KERNEL);
|
||||||
|
if(!module_data.buffer)
|
||||||
|
{
|
||||||
|
LOGGER_ERR("failed to allocate buffer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = usb_register_dev(module_data.interface, &pico_rng_usb_class);
|
||||||
|
if(retval)
|
||||||
|
{
|
||||||
|
LOGGER_ERR("not able to get a minor for this device\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout)
|
// int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout)
|
||||||
retval = usb_bulk_msg (dev,
|
//retval = usb_bulk_msg(dev, pipe, buffer, 64, &actual_length, 500);
|
||||||
pipe,
|
|
||||||
buffer,
|
|
||||||
64,
|
|
||||||
&actual_length,
|
|
||||||
5000);
|
|
||||||
|
|
||||||
/* if the read was successful, copy the data to user space */
|
|
||||||
if (!retval)
|
|
||||||
{
|
|
||||||
LOGGER_INFO("%s\n", buffer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOGGER_INFO("usb_bulk_msg raised an error %d\n", retval);
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree(buffer);
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@@ -137,9 +202,14 @@ static int pico_rng_usb_probe(struct usb_interface *interface, const struct usb_
|
|||||||
static void pico_rng_usb_disconnect(struct usb_interface *interface)
|
static void pico_rng_usb_disconnect(struct usb_interface *interface)
|
||||||
{
|
{
|
||||||
LOGGER_INFO("pico rng usb device disconnected\n");
|
LOGGER_INFO("pico rng usb device disconnected\n");
|
||||||
|
usb_deregister_dev(module_data.interface, &pico_rng_usb_class);
|
||||||
|
module_data.dev = NULL;
|
||||||
|
module_data.interface = NULL;
|
||||||
|
module_data.pipe = 0;
|
||||||
|
kfree(module_data.buffer);
|
||||||
|
module_data.buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int __init pico_rng_driver_init(void)
|
static int __init pico_rng_driver_init(void)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
@@ -156,12 +226,18 @@ static int __init pico_rng_driver_init(void)
|
|||||||
LOGGER_INFO("pico rng driver registered successfully\n");
|
LOGGER_INFO("pico rng driver registered successfully\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit pico_rng_driver_exit(void)
|
static void __exit pico_rng_driver_exit(void)
|
||||||
{
|
{
|
||||||
usb_deregister(&pico_rng_usb_driver);
|
usb_deregister(&pico_rng_usb_driver);
|
||||||
|
|
||||||
|
if(module_data.buffer)
|
||||||
|
{
|
||||||
|
kfree(module_data.buffer);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user