resultsway
resultsway

Reputation: 13330

ioctl - invalid argument

I have

#define IOCTL_ALLOC_MSG _IO(MAJOR_NUM, 0) 
#define IOCTL_DEALLOC_MSG _IO(MAJOR_NUM, 1)

in a header file.

and in the driver file I wrote:

struct file_operations memory_fops = {
  unlocked_ioctl: device_ioctl,
  open: memory_open,
  release: memory_release
};


int memory_init(void) {
  int result;

  /* Registering device */
  result = register_chrdev(MAJOR_NUM, "memory", &memory_fops);
  if (result < 0) {
    printk("<1>memory: cannot obtain major number %d\n", MAJOR_NUM);
    return result;
  }

  allocfunc();

  printk("<1>Inserting memory module\n");
  return 0;

}

int device_ioctl(struct inode *inode,   /* see include/linux/fs.h */
         struct file *file, /* ditto */
         unsigned int ioctl_num,    /* number and param for ioctl */
         unsigned long ioctl_param)
{
    /* 
     * Switch according to the ioctl called 
     */
    printk ( "<l> inside ioctl \n" );
    switch (ioctl_num) {
    case IOCTL_ALLOC_MSG:
        allocfunc();
        break;
    case IOCTL_DEALLOC_MSG:
        deallocfunc();
        break;
    }

    return 0;
}

I created the character file like

mknod /dev/memory c 60 0

the app call fails

int main(int argc, char *argv[]) {
    FILE * memfile;

    /* Opening the device parlelport */
    memfile=fopen("memory","r+");
    if ( memfile <0) {
        printf ( " cant open file \n");
        return -1;
    }

    /* We remove the buffer from the file i/o */
    int ret_val;
    if ( argc > 1 ) {
        if ( strcmp (argv[1], "mem" ) ==0 ) {


            ret_val = ioctl(memfile, IOCTL_ALLOC_MSG);

            if (ret_val < 0) {
                printf("ioctl failed. Return code: %d, meaning: %s\n", ret_val, strerror(errno));
                return -1;
            }
        }

when i run the app i get "ioctl failed. Return code: -1, meaning: Invalid argument" in : strerror(errno)

printk:

Inserting memory module

fyi, I experimented with "/dev/memory" "memory" different names and major number combinations - but in vain.

Upvotes: 0

Views: 20462

Answers (2)

rodrigo
rodrigo

Reputation: 98496

You are passing a FILE* to the ioctl() function, while it expects a file descriptor, that is an int.

It should at the very least generate a big warning saying that you are converting a pointer to integer without a cast, doesn't it?

There are two obvious solutions:

  1. Use the fileno() function to get the file descriptor from the FILE*. It should be something like ioctl(fileno(memfile), IOCTL_ALLOC_MSG).
  2. Use open() instead of fopen(). This one is the preferred solution if you are writing low level code, as you avoid the additional abstraction layer that FILE* imposes (all the buffering stuff and so).

Upvotes: 5

Greg A. Woods
Greg A. Woods

Reputation: 2792

I'm going to postulate that changing fopen("memory") to fopen("/dev/memory1") will fix the initial problem with your code.

@SunEric also points out in a comment on your question that you have a call to allocFunc() in your driver's initialization function (memory_init()), and yet that seems to be what you want your IOCTL_ALLOC_MSG to do. That may well be the next problem you need to straighten out.

Upvotes: 0

Related Questions