user1361391
user1361391

Reputation: 65

linux programming: write to device file

I wrote this:

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <mtd/mtd-user.h>
#include <errno.h>

int main( void )
{
        int fd;
        char buf[4]="abc";

        fd = open("/dev/mtd0", O_RDWR);
        lseek(fd, 1, SEEK_SET);
        write(fd, &buf, 4);
        close(fd);
        perror("perror output:");

        return 0;
}

The file /dev/mtd0 is created using nandsim kernel module, and run

mtdinfo /dev/mtd0

got meaningful output.After i run my program, it's output:

perror output:: Invalid argument

If there is any error in my program?

Upvotes: 4

Views: 21156

Answers (5)

Gaston
Gaston

Reputation: 629

You may have to write an entire page and not only 4 bytes.

You can confirm this by typing the command dmesg in shell. Then you should see the following Kernel message:

nand_do_write_ops: Attempt to write not page aligned data

Then replace the code to write in the mtd by:

char buf[2048]="abcdefghij";                      //Ajust size according to 
                                                  //mtd_info.writesize
mtd_info_t mtd_info;                              // the MTD structure

if (ioctl(fd, MEMGETINFO, &mtd_info) != 0) {...   // get the device info

memset(buf+10, 0xff, mtd_info.writesize - 10);    //Complete buf with 0xff's

if (write(fd, &buf, mtd_info.writesize) < 0) {... // write page

Also consider to check bad blocks (ioctl(fd, MEMGETBADBLOCK, ...) and erase blocks (ioctl(fd, MEMERASE, ...) before you write.

Hope this helps.

Upvotes: 1

angelo
angelo

Reputation: 1

The trouble is in this line:

if (write(fd, &buf, 4) < 0) {

The second parameter to the write call has to be a pointer, "buf" is already a pointer, referencing it with the "&" you obtain a pointer to a pointer that is wrong: the correct call is:

if (write(fd, (void*)buf, 4) < 0) {

Upvotes: 0

Kristof Provost
Kristof Provost

Reputation: 26322

Yes, there is a problem. Your use of perror() is wrong.

You should first check if a system call indicates a problem before calling perror. The man page is quite explicit on the subject:

Note that errno is undefined after a successful library call: this call
may  well  change  this  variable, even though it succeeds, for example
because it internally used some other  library  function  that  failed.
Thus,  if  a failing call is not immediately followed by a call to per‐
ror(), the value of errno should be saved.

You should be checking the return codes of each system, and only call perror if they fail. Something like this:

fd = open("/dev/mtd0", O_RDWR);
if (fd < 0) {
    perror("open: ");
    return 1;
}
if (lseek(fd, 1, SEEK_SET) < 0) {
    perror("lseek: ");
    return 1;
}
if (write(fd, &buf, 4) < 0) {
    perror("write: ");
    return 1;
}
close(fd);

Upvotes: 2

Viktor Latypov
Viktor Latypov

Reputation: 14467

Maybe this helps ?

http://forums.freescale.com/t5/Other-Microcontrollers/Can-t-write-new-uboot-to-mtd0-in-linux-on-MPC8313E-RDB/td-p/34727

It all has to deal with access rights.

And as Jakub and Mat say, check the error code for each API call.

Upvotes: 1

Jakub Oboza
Jakub Oboza

Reputation: 5421

You should have something like this

if(-1 == write(fd, &buf, 4)){
  perror("perror output:");
}
close(fd);

because perror shows last error.

http://www.cplusplus.com/reference/clibrary/cstdio/perror/

and more about perror http://www.java-samples.com/showtutorial.php?tutorialid=597

Upvotes: 2

Related Questions