Why not get the offset to the read-write functions of my driver?

1

I'm programming a driver that performs reads and writes to memory locations that have been mapped (in driver open) with:

request_mem_region(0x62200000,0x0006C,secuencial);

contador = ioremap_nocache(0x62200000,0x0006C   );

where: 0x62200000,0x0006C is the memory location and size of a ipcore that has been instantiated in memory. "secuencial" is the name of the device driver.

contador is a void* (it's a pointer to the virtual address)

according to my reading and writing functions in the code of my device driver:

static ssize_t device_read(struct file *filp, char *buffer,size_t length, loff_t * offset)  

static ssize_t device_write(struct file *filp, char *buffer,size_t length, loff_t * offset) 

and my file operations:

static struct file_operations fops = {
    .read    = device_read,
    .write   = device_write,
    .open    = device_open,
    .release = device_release
};

from my program in c, I use a function from my library with:

read (fd_secuencial,buffer_lectura,199, offset_read);

write( fd_secuencial,  msg,  10, offset_write);

where the variables are:

loff_t offset_read=0x00000004;
loff_t offset_write=0x00000044;

and fd_secuencial is a file descriptor to the device driver obtained in the open:

fd_secuencial = open("/dev/secuencial", O_RDWR | O_NOCTTY | O_NONBLOCK);

buffer and msg are buffers to read/write the data.

The problem is that the offset never comes to my reading/writing functions in the driver,

I print with: printk(KERN_ALERT "Offset: %llu\n", *offset);

and offset is always 0....

what's wrong with my code? any ideas?

I changed the position to access the file from the reading function by

filp-> f_pos = integer_different_values​​. 

And no readings are taken to different memory locations mapped. That is, the "f_pos" changes, but not access the file as if it were a block of memory (which is the approach that came holding).

If I increase the memory location to which I access with "contador" achievement take readings correctly.

I'm suspecting that the function device_read / write is defined but loff_t * pos field is not implemented in the method of the function. If I call the function read from the application, with 5 parameters, the compiler gives no warning and the execution is normal (but obviously taking into account the first 3 parameters)

Thus, I can not pass from the application to the function device_read / write driver, offset as the 4th parameter.

The correct way to call the method is as follows:

loff_t offset = 16;
loff_t * off = &offset;

In this way, you pass the offset value to a pointer called off (which is requesting the function prototype)

thank you very much for any help!

c
linux
kernel
driver
linux-device-driver
asked on Stack Overflow Jun 29, 2013 by eduardosufan • edited Jul 3, 2013 by eduardosufan

1 Answer

1

You may implement a separate seek function with character devices as described in LDD3 here: http://tjworld.net/books/ldd3/#SeekingADevice.

You may use the llseek field of the file_operations struct to assign a seek function with the prototype:

loff_t (*llseek) (struct file *, loff_t, int);

The user application or API will then use the user-space function lseek() function to exercise it.

However if you are performing operations on registers that have side effects other than reading data from or writing data to your device, you should probably use the ioctl() interface and provide an API wrapper. See http://tjworld.net/books/ldd3/#TheIoctlMethod.

answered on Stack Overflow Jun 30, 2013 by Benjamin Leinweber • edited Jul 2, 2013 by Benjamin Leinweber

User contributions licensed under CC BY-SA 3.0