LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   fread can not pass the exact "count" ... (https://www.linuxquestions.org/questions/linux-newbie-8/fread-can-not-pass-the-exact-count-757507/)

intermilan 09-24-2009 10:29 AM

fread can not pass the exact "count" ...
 
I'm trying to read from a device from a user application using:

int* frame = (int*) malloc( 83 * sizeof(int));
FILE *ICAP;
ICAP = fopen("/dev/icap0", "w+b"); // The deivce is opened OK. "w+b" should mean "read and write, binary".
fread(frame, sizeof(int), 83, ICAP);


The device read operation is defined as:
static ssize_t hwicap_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)

However, inside the hwicap_read function, the value of count is 0x400, not 0x53 as I passed to fread.

Why "count" in the hwicap_read function can not get the value as fread is called?

AngTheo789 09-24-2009 11:18 AM

You should post the code fragment - maybe that reveals something. By the way, fread should return the actual value it did read, unregarded what you passed in count.

Wim Sturkenboom 09-24-2009 11:53 AM

There is a dedicated programming section here at LQ. Future programming related questions fit better in there.

The count in hwicap_read probably defines the max size of the buffer __user *buf and not the number of chars to read.

intermilan 09-25-2009 09:28 AM

Thanks for your reply.

The user application:

FILE *ICAP;
printf("Open ICAP ...\n");
ICAP = fopen("/dev/icap0", "r+b");
if (ICAP == NULL)
{
fprintf(stderr, "/dev/icap0 does not exist!\n");
return 1;
}

//read icap
int byte_read;
byte_read = fread(frame, sizeof(*frame), frame_to_read, ICAP);


Driver code: (I do not whether it is helpful)
static ssize_t
hwicap_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
struct hwicap_drvdata *drvdata = file->private_data;
ssize_t bytes_to_read = 0;
u32 *kbuf;
u32 words;
u32 bytes_remaining;
int status;

kbuf = (u32 *) get_zeroed_page(GFP_KERNEL);
printk("<1>\t Get new data from the ICAP\n");
if (!kbuf) {
status = -ENOMEM;
goto error;
}

words = ((count + 3) >> 2);
bytes_to_read = words << 2;

if (bytes_to_read > PAGE_SIZE)
bytes_to_read = PAGE_SIZE;

/* Ensure we only read a complete number of words. */
bytes_remaining = bytes_to_read & 3;
bytes_to_read &= ~3;
words = bytes_to_read >> 2;

printk("<1>\t\t Try to get configuration of %x words\n", words);

status = drvdata->config->get_configuration(drvdata,
kbuf, words);

/*test kernel buffer
int i;
for (i=0; i<words; i++)
printk("<1>\t\t kbuf data at offset %x is %x\n", i, kbuf[i]);
*/

/* If we didn't read correctly, then bail out. */
printk("<1>\t\t Get configuration with status %d\n",status);
if (status) {
free_page((unsigned long)kbuf);
goto error;
}
/* If we fail to return the data to the user, then bail out. */
printk("<1>\t\t Begin copy_to_user %x bytes\n", bytes_to_read);
if (copy_to_user(buf, kbuf, bytes_to_read)) {
free_page((unsigned long)kbuf);
status = -EFAULT;
goto error;
}
printk("<1>\t\t Finish copy_to_user\n");
memcpy(drvdata->read_buffer,
kbuf,
bytes_remaining);
drvdata->read_buffer_in_use = bytes_remaining;
free_page((unsigned long)kbuf);
}
error:
mutex_unlock(&drvdata->sem);
return status;
}


You mentioned " fread should return the actual value it did read, unregarded what you passed in count". However, this device can not return arbitrary bytes. Indeed, before the device read, there is a device write which tells the device how many bytes it should fetch out for next read, so I must control how many bytes to read out with a parameter (otherwise, the device is going to be an abnormal state. This seems weired, but it is a Xilinx FPGA core hooked up as a Linux device and it behaves like this). But it seems that I can't do it with count? Then what should I do?


Quote:

Originally Posted by AngTheo789 (Post 3695699)
You should post the code fragment - maybe that reveals something. By the way, fread should return the actual value it did read, unregarded what you passed in count.


Guttorm 09-25-2009 10:27 AM

Hi

The fopen/fread functions do buffered io, so it can read more to fill a buffer. Either use setvbuf to make it unbuffered, or use open/read instead.

intermilan 09-27-2009 10:02 PM

Thanks! This works!

Quote:

Originally Posted by Guttorm (Post 3696875)
Hi

The fopen/fread functions do buffered io, so it can read more to fill a buffer. Either use setvbuf to make it unbuffered, or use open/read instead.



All times are GMT -5. The time now is 10:26 AM.