Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
388 views
in Technique[技术] by (71.8m points)

c - Can't read from linux character device

I am implementing an SPI driver for an accelerometer. The SPI part is done but I can't read values from userspace.

static char charDevMessage[CD_BUFFER_SIZE] = { 0 };
...
static ssize_t char_dev_read(struct file *filep, char *buffer, size_t len, loff_t *position)
{

    int error_count = 0;
    struct xyz_values xyz;
    size_t size_requested;

    xyz = adxl345_get_xyz();
    memset(charDevMessage, 0, CD_BUFFER_SIZE);
    sprintf(charDevMessage, "%d,%d,%d", xyz.x, xyz.y, xyz.z);
    printk(KERN_INFO "MOB: %s, requested size: %d
", charDevMessage, len);

    if (len >= CD_BUFFER_SIZE)
    {
        size_requested = CD_BUFFER_SIZE;
    }
    else
    {
        size_requested = len;
    }

    error_count = copy_to_user(buffer, charDevMessage, size_requested);      

    if (error_count == 0)          
    {
        printk(KERN_INFO "MOB: Sent %d characters to the user
", size_requested);
        return (size_requested = 0);      

    }
    else
    {
        printk(KERN_INFO "MOB: Failed to send %d characters to the user
", error_count);
        return -EFAULT;              

    }
}

The node has been created when I installed the driver. But when I tried cat or tried to read by python it returns an empty string.

dmesg says it has been sent to userspace successfully:

[ 3094.495972] MOB: SPI Character device has been opened 1 time(s)
[ 3094.506075] MOB: -349,-512,511 , requested size:49
[ 3094.514487] MOB: Sent 256 characters to the user
[ 3094.522646] MOB: Character device successfully closed
[ 3120.658568] MOB: SPI Character device has been opened 2 time(s)
[ 3120.668609] MOB: 0,0,0 , requested size:48
[ 3120.676392] MOB: Sent 256 characters to the user
[ 3120.684740] MOB: Character device successfully closed

What am I doing wrong?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You misaunderstood the concept of the .read function:

The reader (user space) sees only value returned by the .read and interpret it as a number of bytes which has been read.

As for the last parameter to the .read (position in your case), its interpretation is fully up to the driver's author. Value, pointed by position, is initialized to 0 by the kernel core when the file is opened. After that, kernel itself never modifies it.

If you want to always read from the beginning, you may just ignore position parameter:

return size_requested;

Or, semantically better, you may increment value, pointed by the position, so it will reflect total number of bytes read. But otherwise ignore it:

*position += size_requested;
return size_requested;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...