aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Sangdahl <[email protected]>2024-09-28 01:48:47 -0600
committerJack Sangdahl <[email protected]>2024-09-28 01:48:47 -0600
commiteea3d410e709ebac4351f58487ed3c9f49631c44 (patch)
tree87efd0eda5ee33758204172911f9d002dcf022d4
parent5b2e4d95a74f83277b654fadceb98bef87690a54 (diff)
downloadcsci3753-eea3d410e709ebac4351f58487ed3c9f49631c44.tar.gz
csci3753-eea3d410e709ebac4351f58487ed3c9f49631c44.zip
pa3: improvements
-rw-r--r--pa3_device_driver/char_driver.c58
1 files changed, 35 insertions, 23 deletions
diff --git a/pa3_device_driver/char_driver.c b/pa3_device_driver/char_driver.c
index 7ca63e3..8bea3fb 100644
--- a/pa3_device_driver/char_driver.c
+++ b/pa3_device_driver/char_driver.c
@@ -3,11 +3,13 @@
// PA3 Device Driver
#include <linux/fs.h>
#include <linux/module.h>
+#include <linux/slab.h>
MODULE_AUTHOR("jasa7131");
MODULE_LICENSE("GPL");
#define BUFFER_SIZE 900
+#define MAJOR_NUM 510
#define DEVICE_NAME "char_dev"
static int major, counter = 0;
static char *data;
@@ -38,49 +40,59 @@ int char_driver_close(struct inode *pinode, struct file *pfile) {
ssize_t char_driver_read(struct file *pfile, char __user *buffer, size_t length,
loff_t *offset) {
- ssize_t data_read = simple_read_from_buffer(buffer, length, offset,
- data + *offset, BUFFER_SIZE);
- if (data_read < 0) {
- printk("READ FAILED: Failed to read from user buffer.\n");
- return -EFAULT;
- }
- if (data_read) {
- printk("READ SUCCESS: Read %ld bytes from %s.\n", data_read, DEVICE_NAME);
- if (data_read >= BUFFER_SIZE)
- printk("Reached EOF\n");
- }
- return data_read;
+ size_t data_avail = BUFFER_SIZE - *offset, bytes_read = length;
+ if (*offset >= BUFFER_SIZE || !length)
+ return 0;
+ if (length > data_avail)
+ bytes_read = data_avail;
+ printk("Requested data size: %zd bytes\n", length);
+ long res = copy_to_user(buffer, data + *offset, bytes_read);
+ printk("Read %zd bytes from device\n", bytes_read);
+ length -= res;
+ *offset += length;
+ return length;
}
ssize_t char_driver_write(struct file *pfile, const char __user *buffer,
size_t length, loff_t *offset) {
- ssize_t data_written = simple_write_to_buffer(data + *offset, BUFFER_SIZE,
- offset, buffer, length);
- printk("WRITE SUCCESS: Wrote %ld bytes to %s.\n", data_written, DEVICE_NAME);
- if (data_written > BUFFER_SIZE)
- printk("WRITE ERR: Buffer is filled.\n");
- return data_written;
+ size_t data_avail = BUFFER_SIZE - *offset, bytes_written = length;
+ if (*offset >= BUFFER_SIZE || !length)
+ return 0;
+ if (length > data_avail)
+ bytes_written = data_avail;
+ printk("Requested data size: %zd bytes\n", length);
+ long res = copy_from_user(data + *offset, buffer, bytes_written);
+ printk("Wrote %zd bytes to device\n", bytes_written);
+ length -= res;
+ *offset += bytes_written;
+ return length;
}
loff_t char_driver_seek(struct file *pfile, loff_t offset, int whence) {
+ loff_t new_pos = 0;
switch (whence) {
case SEEK_SET:
- pfile->f_pos = offset;
+ new_pos = offset;
break;
case SEEK_CUR:
- pfile->f_pos += offset;
+ new_pos = pfile->f_pos + offset;
break;
case SEEK_END:
- pfile->f_pos = strlen(data) - offset;
+ new_pos = BUFFER_SIZE - offset;
break;
}
- return pfile->f_pos;
+ if (new_pos > BUFFER_SIZE)
+ new_pos = BUFFER_SIZE;
+ if (new_pos < 0)
+ new_pos = 0;
+ pfile->f_pos = new_pos;
+ return new_pos;
}
static int char_driver_init(void) {
printk("Registering device %s\n", DEVICE_NAME);
data = (char *)kmalloc(BUFFER_SIZE * sizeof(char), GFP_KERNEL);
- major = register_chrdev(511, DEVICE_NAME, &char_fops);
+ major = register_chrdev(MAJOR_NUM, DEVICE_NAME, &char_fops);
if (major < 0) {
printk(KERN_ALERT "REGISTRATION FAILED: %s could not be reigstered.\n",
DEVICE_NAME);