diff --git a/driver/pico_rng.c b/driver/pico_rng.c index b356922..c8458e5 100644 --- a/driver/pico_rng.c +++ b/driver/pico_rng.c @@ -11,6 +11,7 @@ #include #include + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mickey Malone"); MODULE_DESCRIPTION("Random number generator using a Raspberry Pi Pico"); @@ -21,7 +22,6 @@ MODULE_VERSION("1.0"); **/ #define VENDOR_ID 0x0 #define PRODUCT_ID 0x4 -#define SC_MINOR_BASE 31 /** * Helper macros @@ -35,6 +35,21 @@ static int debug = 0; module_param(debug, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 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 **/ @@ -43,13 +58,8 @@ static void pico_rng_usb_disconnect(struct usb_interface *interface); static int __init pico_rng_driver_init(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_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 @@ -73,13 +83,63 @@ static struct usb_driver pico_rng_usb_driver = { * File operations data structure for the character device * that will be implemented in this module **/ -/**static struct file_operations pico_rng_fops = { +static struct file_operations pico_rng_fops = { .owner = THIS_MODULE, - .open = pico_rng_open, .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 @@ -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) { - struct usb_device *dev = interface_to_usbdev(interface); - struct usb_endpoint_descriptor *endpoint = NULL; - int retval = -ENODEV; - char *buffer; - int actual_length; - int pipe = 0; + int retval = -ENODEV; - 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) { LOGGER_ERR("Unable to find bulk endpoint %d\n", 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); - - // 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, - pipe, - buffer, - 64, - &actual_length, - 5000); - - /* if the read was successful, copy the data to user space */ - if (!retval) + module_data.buffer = NULL; + module_data.buffer = kmalloc(module_data.endpoint->wMaxPacketSize, GFP_KERNEL); + if(!module_data.buffer) { - LOGGER_INFO("%s\n", buffer); - } - else - { - LOGGER_INFO("usb_bulk_msg raised an error %d\n", retval); + LOGGER_ERR("failed to allocate buffer"); + return -1; } - kfree(buffer); + 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) + //retval = usb_bulk_msg(dev, pipe, buffer, 64, &actual_length, 500); 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) { 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) { int retval = 0; @@ -156,12 +226,18 @@ static int __init pico_rng_driver_init(void) LOGGER_INFO("pico rng driver registered successfully\n"); } - return retval; + return 0; } static void __exit pico_rng_driver_exit(void) { usb_deregister(&pico_rng_usb_driver); + + if(module_data.buffer) + { + kfree(module_data.buffer); + } + return; }