0

I'm trying to write a simple Raspberry Pi GPIO driver, with four switches connected to four of the GPIO pins, that reads each switch state. The problem is, I'm not sure how to write from kernel to user space, I'm not getting anything when I insert my device kernel module and try to read the device file with cat command. The device_read function is as follows:

static ssize_t gpio_driver_read(struct file *filp, char *buf, size_t len, loff_t *f_pos)
{
    /* Size of valid data in gpio_driver - data to send in user space. */
    int data_size = 0;

    /* Counter for 'for' loop. */
    int i;

    /* Print to kernel space. */
    printk(KERN_INFO "Reading active Switch state...\n");

    for (i = 0; i < 4; i = i+1)
    {
        printk(KERN_INFO "Loop number %d...\n", i);
        /* TODO: fill gpio_driver_buffer here. */
        if (i == 0 && mySwitches[0])
            sprintf(gpio_driver_buffer, "gpio_driver: gpio12 value: %d\n", GetGpioPinValue(GPIO_12));
        else if (i == 1 && mySwitches[1])
            sprintf(gpio_driver_buffer, "gpio_driver: gpio16 value: %d\n", GetGpioPinValue(GPIO_16));
        else if (i == 2 && mySwitches[2])
            sprintf(gpio_driver_buffer, "gpio_driver: gpio20 value: %d\n", GetGpioPinValue(GPIO_20));
        else if (i == 3 && mySwitches[3])
            sprintf(gpio_driver_buffer, "gpio_driver: gpio21 value: %d\n", GetGpioPinValue(GPIO_21));

        printk(KERN_INFO "%s\n", gpio_driver_buffer);

        /* Get size of valid data. */
        data_size = strlen(gpio_driver_buffer);

        printk(KERN_INFO "%d\n", data_size);


        /* Send data to user space. */
        if (copy_to_user(buf, gpio_driver_buffer, data_size) != 0)
        {
            return -EFAULT;
        }
    }

    return 0;
}

gpio_driver_buffer is an array of some default size (I put it to 80).
mySwitches is an array of 4 elements, each one with value 0 or 1 (I'm passing that as an argument when inserting the kernel module, 1 meaning I want to watch the state of the switch and 0 meaning I'm not watching the switch).
GetGpioPinValue is a function that returns switch state.

The problem is, when I try to read the device file with cat command, I'm not getting anything. However, as you can see, I kind of debugged the program with printk commands and everything is written correctly in kernel space. Where could the problem be?

red0ct
  • 4,840
  • 3
  • 17
  • 44
A6EE
  • 141
  • 1
  • 8
  • 1
    Can you include the code where you are creating the device file? Where are you expecting filep to be used? How is the user-space 'buf' provided? Is it supposed to be associated with the file you are cating? – charlesw Dec 17 '18 at 22:09
  • `return 0;` - you should return the number of bytes read. Right now your function reads zero bytes. – KamilCuk Jan 08 '19 at 08:27

2 Answers2

0

It doesn't look like you are ever writing to the actual file. Since you don't mention how you are generating the file, I'm assuming you are writing to an arbitrary file, not one created by the driver for /proc or something.

Review the post here: Read/write files within a Linux kernel module

You can try this:

int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = vfs_write(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}

Then call it instead of 'copy_to_user':

/* Send data to user space. */
        if (file_write(filep, 0, gpio_driver_buffer, data_size) != 0)
        {
            return -EFAULT;
        }
charlesw
  • 572
  • 6
  • 25
0

Have a look at the sample code here.

Sanchayan Maity
  • 637
  • 6
  • 19