Find the answer to your Linux question:
Results 1 to 5 of 5
Hi, I am writing a device driver with an ioctl in driver module. When I execute ioctl from user space and try to access the driver, the command number (cmd) ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Jul 2011
    Posts
    5

    Wrong command number is received by ioctl


    Hi, I am writing a device driver with an ioctl in driver module. When I execute ioctl from user space and try to access the driver, the command number (cmd) received my ioctl in driver is incorrect. Here is what I am doing:
    Code:
    //Drivertest.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <linux/ioctl.h>
    struct file_params{
    	int *base_reg_ptr;
    	int *off_reg_ptr;
    };
    #define WRITE_CMD _IOW(60, 1, struct file_params)
    
    int main(){
    	int fd, success=0, offset;
    	int dummy_arr[10];	
    	struct file_params param;
    	param.base_reg_ptr = &dummy_arr[0];
    	param.off_reg_ptr = &dummy_arr[1];
    	offset = param.off_reg_ptr - param.base_reg_ptr;
    	printf("base_ptr:%u, offset_ptr:%u, offset:%d\n", param.base_reg_ptr, param.off_reg_ptr, offset);
    	if((fd = open("/dev/memory", O_RDWR))==-1){
    		printf("Error opening the device\n");
    		exit(1);
    	}
    	printf("command number=%x\n", WRITE_CMD);
    	success=ioctl(fd, WRITE_CMD, &param);
    	if(success<0){
    		printf("ioctl failed..\n");
    		exit(1);
    	}
    	printf("success=%d\n", success);
    	close(fd);
    	printf("file closed..\n");
    }
    Code:
    //Driver.c
    
    #include<linux/fs.h>
    #include<asm/uaccess.h>
    #include<linux/module.h>
    #include<linux/init.h>
    #include<linux/kernel.h>
    #include<linux/types.h>
    #include<linux/fcntl.h>
    #include<asm/system.h>
    #include<linux/proc_fs.h>
    #include<linux/slab.h>
    #include<linux/ioctl.h>
    
    
    MODULE_LICENSE("Dual BSD/GPL");
    struct file_params{
    	int *base_reg_ptr;
    	int *off_reg_ptr;
    };
    #define WRITE_CMD _IOW(60, 1, struct file_params)
    
    int memory_major = 60;
    
    int device_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
    
    struct file_operations memory_fops={
    	.unlocked_ioctl= device_ioctl
    };
    
    
    
    int memory_init(void){
    	int result=0;
    	result=register_chrdev(memory_major, "memory", &memory_fops);
    	if(result<0){
    		printk("<1>Device registration failure..\n");
    		return result;
    	}
    	printk("Inserting memory module\n");
    	return 0;
    }
    
    void memory_exit(void){
    	unregister_chrdev(memory_major, "memory");
    	printk("<1>Removing memory module\n");
    }
    
    
    int device_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg){
    	int rc;
    	int offset=0;
    	struct file_params *obj_ptr = kmalloc(sizeof(struct file_params), GFP_KERNEL);
    	printk("<1>value of cmd=%x\n", cmd);
    	switch(cmd){
    		case WRITE_CMD:
    		rc=copy_from_user(obj_ptr, (const void*)arg, sizeof(struct file_params));
    		printk("<1>copy_from_user()=%d\n", rc);
    		offset=obj_ptr->off_reg_ptr - obj_ptr->base_reg_ptr;
    		printk("<1>base ptr:%u, offset ptr:%u, offset=%d\n", obj_ptr->base_reg_ptr, obj_ptr->off_reg_ptr, offset);
    		break;
    		default:
    		printk("<1>Default case:\n");
    		break;
    	}
    	return 1;
    }
    	
    module_init(memory_init);
    module_exit(memory_exit);
    For compilation I do,
    Code:
    gcc Drivertest.c
    make -C /usr/src/linux-2.6.39-gentoo-r3 M=/root/ioctl modules
    insmod Driver.ko
    ./a.out
    Makefile:
    Code:
    obj-m:=Driver.o
    ./a.out output:
    Code:
    base_ptr:3213795404, offset_ptr:3213795408, offset:1
    command number=40083c01
    file closed..
    dmesg:
    Code:
    value of cmd=bf8ea044
    Default case:
    device create:
    Code:
    mknod /dev/memory c 60 0
    Am I doing something wrong?

  2. #2
    Just Joined!
    Join Date
    May 2011
    Location
    Taiwan
    Posts
    5
    After I try your code, I reproduced the the same behavior as yours.

    I think the problem is due to the function prototype you use is int device_ioctl(struct inode* inode, struct file *filep, unsigned int cmd, unsigned long arg). You can correct it to be device_ioctl(struct file *filep, unsigned int cmd, unsigned long arg), then I guess the driver will work as your wish.
    Last edited by NonerKao; 09-16-2011 at 04:33 AM. Reason: some discovery

  3. #3
    Just Joined!
    Join Date
    Jul 2011
    Posts
    5
    Problem solved!! However I don't know why it happened. I compiled and run the code on Ubuntu-10.04 (kenrel 2.6.32-21), it worked. However when I ran it on Gentoo-Linux (kernel 2.6.38-2) it ran the way I posted in my last post.
    I also noticed the difference in the syntax of struct file_operations:
    old syntax :
    Code:
    struct file_operations fops={
      ioctl:device_ioctl
      ...
      ...
    };
    new syntax :
    Code:
    struct file_operations fops={
      .unlocked_ioctl = device_ioctl
      ...
      ...
    };
    I don't know if this has something to do with the code behavior.

  4. #4
    Just Joined!
    Join Date
    May 2011
    Location
    Taiwan
    Posts
    5
    For your information, search the key word "What is the difference between ioctl(), unlocked_ioctl() and compat_ioctl()?"

  5. #5
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,448
    There were significant kernel structure changes between 2.6.32 and 2.6.38 kernels. Any kernel module that has ioctl() calls such as yours, may need to be changed to support such changes. Wrapping the structure and related accesses with #ifdef/#endif may be appropriate so you can use the same code (recompiled) for the module on newer or older kernels.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •