copy_to_user()
returns the number of bytes that couldn't be copied to user space. If the complete buffer could be copied, it returns 0.
Normally, if !=0, means that there was some sort of memory problem (writting past a legal memory address), so these situations should be detected and reported to the user.
static ssize_t device_read (struct file* filp, char *bufStoreData,
size_t bufCount, loff_t* curOffset)
{
size_t bytes_to_copy;
printk(KERN_INFO"reading from the device");
/* do stuff to get device data into virtual_device.data . Also
update virtual_device.datasize */
bytes_to_copy = (virtual_device.datasize <= bufCount)?
virtual_device.datasize : bufCount;
/* note that I'm not using bufCount, but an hypothetical field in
virtual_device that gives me how much data the device has ready
for the user. I choose the lower of both */
/* Also recall that if the number of bytes requested by the user is
less than the number of bytes the device has generated, then the
next read should return the remainder of the device data, so the
driver should carry the count of how many bytes have been copied
to the user and how many are left. This is not covered in this
example. */
ret = copy_to_user(bufStoreData,virtual_device.data, bytes_to_copy);
if (ret != 0)
return -EPERM; /* if copy was not successful, report it */
return bytes_to_copy;
}
When the user issues ret = read (fd, buffer, sizebuff);
it expects one of these things and should react accordingly:
ret
is equal to sizebuff
. That means that read
could return all the data the user requested. Nothing else to do here.
ret
is positive, but less than sizebuff
. That means that the read gave the user some data, but not as much as he requested. The user process must re-issue the read
syscall to retrieve the remaining data, if needed. Something like: ret = read (fd, buffer+ret, sizebuff-ret);
ret
is 0. This means that the device has no more data to send. It's the EOF
condition. User process should close the device.
ret
is < 0. This is an error condition. User process must check errno
and take appropiate measures.
Your device driver will have to return an appropiate value in device_read according to what happened to the device when it was read.
On the other hand, a process like cat
expects to read as much as 4096 bytes per read
call. If the device sends less than that, it will print the received data and will ask for more. cat
will only stop if it receives a signal (Ctrl-C
for example), or if a read
call returns an unrecoverable error (such as ENODEVICE
, which should be generated by your driver if such condition arises), or if reads 0 bytes (EOF
condition).
A rather silly device that returns "Hello, world"
to the user process. It employs some global data that must be reset in device_open
function. Note that if several processes are going to use your device at the same time, these global data must be turned into instance data (using file->private_data
). This device_read example shows how to deal with device buffers and user buffers, and how to keep track of bytes sent to the user, so the device never sends more data than it has, never sends more data than the user requests, and when the device runs out of data, it returns 0 to the user.
int curindx = 0; /* should be reset upon calling device_open */
static ssize_t device_read (struct file* filp, char *bufStoreData,
size_t bufCount, loff_t* curOffset)
{
size_t bytes_to_copy;
char device_data[]="Hello, world!
";
size_t remaindersize;
remaindersize = strlen(device_data) - curindx;
bytes_to_copy = (remaindersize <= bufCount)?
remaindersize : bufCount;
ret = copy_to_user(bufStoreData,device_data+curindx, bytes_to_copy);
if (ret != 0)
return -EPERM; /* if copy was not successful, report it */
curindx += bytes_to_copy;
return bytes_to_copy;
}