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) ...
- 09-15-2011 #1Just 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, ¶m); if(success<0){ printf("ioctl failed..\n"); exit(1); } printf("success=%d\n", success); close(fd); printf("file closed..\n"); }For compilation I do,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);
Makefile:Code:gcc Drivertest.c make -C /usr/src/linux-2.6.39-gentoo-r3 M=/root/ioctl modules insmod Driver.ko ./a.out
./a.out output:Code:obj-m:=Driver.o
dmesg:Code:base_ptr:3213795404, offset_ptr:3213795408, offset:1 command number=40083c01 file closed..
device create:Code:value of cmd=bf8ea044 Default case:
Am I doing something wrong?Code:mknod /dev/memory c 60 0
- 09-16-2011 #2Just 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
- 09-16-2011 #3Just 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 :
new syntax :Code:struct file_operations fops={ ioctl:device_ioctl ... ... };
I don't know if this has something to do with the code behavior.Code:struct file_operations fops={ .unlocked_ioctl = device_ioctl ... ... };
- 09-17-2011 #4Just 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()?"
- 09-21-2011 #5Linux Guru
- Join Date
- Apr 2009
- Location
- I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
- Posts
- 8,961
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!


Reply With Quote
