Skip to content

Commit

Permalink
Supporting llseek() and unlocked_ioctl()
Browse files Browse the repository at this point in the history
  • Loading branch information
stamrakar authored and stamrakar committed Nov 4, 2024
1 parent 46c8a8b commit 03f3d95
Showing 1 changed file with 103 additions and 1 deletion.
104 changes: 103 additions & 1 deletion aesd-char-driver/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include <linux/uaccess.h>
#include <linux/fs.h> // file_operations


#include "aesd_ioctl.h"
#include "aesdchar.h"


Expand Down Expand Up @@ -71,6 +71,106 @@ int aesd_release(struct inode *inode, struct file *filp)
return 0;
}

/**
* "The llseek method is used to change the current read/write position
* in a file, and the new position is returne as a (positive) return value.
* The loff_t parameter is a "long offset" and is at least 64 bits wide
* even on 32-bit platforms. Errors are signaled by a negative return value.
* If this function pointer is NULL, seek calls will modify the position
* counter in the file structure in potentially unpredictable ways."
* Linux Device Drivers Chapter 3, J. Corbet, A Rubini, G. Kroah-Hartman
*/
loff_t aesd_llseek(struct file *filp, loff_t offset, int whence)
{
ssize_t retval;
loff_t fsl;
loff_t circbuffsize=0;
struct aesd_dev *dev = NULL;
struct aesd_buffer_entry *entry = NULL;
uint8_t stread;
if (filp == NULL)
{
retval = -EINVAL;
PDEBUG("file pointer filp NULL, returning %zu", retval);
goto errout;
}

dev = filp->private_data;

if (mutex_lock_interruptible(&dev->bufferlock))
{
retval = -ERESTARTSYS;
PDEBUG("mutex lock interruptible, returning %zu", retval);
goto errout;
}

AESD_CIRCULAR_BUFFER_FOREACH(entry, &(aesd_device.circular), stread)
{
if(entry->buffptr != NULL)
circbuffsize += entry->size;
}

//need to get the total size of all content of the circular buffer
fsl = fixed_size_llseek(filp, offset, whence, circbuffsize);
if (fsl == -EINVAL)
{
retval = fsl;
PDEBUG("fixed_size_llseek() returned -EINVAL. %zu", retval);
goto unlockout;
}
retval = fsl;
//filp->f_pos += fsl;
return retval;

unlockout:
mutex_unlock(&dev->bufferlock);
errout:
return retval;
}


/**
* Adjust the file offset (f_pos) parameter of @param filp based on the location specified by
* @param write_cmd (the zero referenced command to locate) and @param write_cmd_offset
* (the zero referenced offset into the command)
* @return 0 if successful, negative if error occurred:
* -ERESTARTSYS if mutex could not be obtained
* -EINVAL if write command or write_cmd_offset was out of range.
*/
static long aesd_adjust_file_offset(struct file *filp, unsigned int write_cmd, unsigned int write_cmd_offset)
{

}

int aesd_unlocked_ioctl(struct inode *node, struct file *filp, unsigned int vala, unsigned long valb)
{
ssize_t retval;
if (filp == NULL)
{
retval = -EINVAL;
PDEBUG("file pointer filp NULL, returning %zu", retval);
goto errout;
}

case AESDCHAR_IOCSEEKTO
{
struct aesd_seekto seekto;
if (copy_from_user(&seekto, (const void __user *)arg, sizeof(seekto)) != 0) {
retval = EFAULT;
} else {
retval = aesd_adjust_file_offset(filp, seekto.write_cmd, seekto.write_cmd_offset);
}
break;
}

default:
break;


errout:
return retval;
}

ssize_t aesd_read(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos)
{
Expand Down Expand Up @@ -243,6 +343,8 @@ struct file_operations aesd_fops = {
.write = aesd_write,
.open = aesd_open,
.release = aesd_release,
.llseek = aesd_llseek,
.unlocked_ioctl = aesd_unlocked_ioctl,
};

static int aesd_setup_cdev(struct aesd_dev *dev)
Expand Down

0 comments on commit 03f3d95

Please sign in to comment.