Kaostias
Kaostias

Reputation: 321

Argument invalid when using cat to read a character device driver

When I try to read a char device using:

cat /dev/fifodev

I receive the next message from the terminal

cat: /dev/fifodev: Invalid argument.

I have created the file and gaven it the permissions like this

sudo mknod /dev/fifodev c 251 0
sudo chmod 666 /dev/fifodev 

The code of my driver is:

/* 
 * Called when a process, which already opened the dev file, attempts to
 * read from it.
 */
static ssize_t device_read(struct file *filp,   /* see include/linux/fs.h   */
               char *buffer,    /* buffer to fill with data */
               size_t length,   /* length of the buffer     */
               loff_t * offset)
{
    char aux[BUF_LEN];

    printk(KERN_ALERT "Entering into device_read");

    if (size_cbuffer_t(buf)<length){
        return -EINVAL;
    }   

    remove_items_cbuffer_t (buf,aux, length);
    copy_to_user(buffer, aux, length);


    printk(KERN_ALERT "Getting out from device_read");

    return length;
}

What problem do I have here? Why can't I use cat with the /dev/fifodev file?

Upvotes: 0

Views: 7156

Answers (2)

Kumar Gaurav
Kumar Gaurav

Reputation: 1327

In the function prototype buffer should be mentioned as __user to specify it as userspace pointer. Return of the read method is length of the string read. This functions keeps getting recalled until it returns zero. I think following code will work.

    static ssize_t device_read(struct file *filp,   /* see include/linux/fs.h   */
               char __user *buffer,    /* buffer to fill with data */
               size_t length,   /* length of the buffer     */
               loff_t * offset)
{
    char aux[BUF_LEN];
    int byte_to_read,maxbyte;   
    printk(KERN_ALERT "Entering into device_read");
    /*
    if (size_cbuffer_t(buf)<length){
        return -EINVAL;
    }   
    */
    maxbyte=strlen(buf) - *offset; //considering buf is the pointer where you have data to copy to buffer(userspace)
    byte_to_read=maxbyte>length?length:maxbyte;
    if(byte_to_read==0)
    {
        printk(KERN_ALERT "Allready Read\n");
        return 0;
    }
    aux=buf;//as in your code AUX doesn't have anything. i'm supposing you want to copy data to this from buf and then use copy_to_user
    remove_items_cbuffer_t (buf,aux, length); //i have no idea why you have used this but i'm sure this wont create any problem
    copy_to_user(buffer, aux, length); //this will copy your data to userspace
        

    printk(KERN_ALERT "Getting out from device_read");

    return length;
}

Upvotes: 1

user149341
user149341

Reputation:

Per your comment, the issue you're running into appears to be that your application is requesting to read data into a buffer that is larger than you have data to fill.

You will need to calculate the appropriate amount of data to copy (e.g, the smaller value of length and size_cbuffer_t(buf)), and use that value in the place of length.

Upvotes: 2

Related Questions