Hi,
I`ve written some ioctl`s to my simple char device. I created inside
the device some number called "secretTreasure" and programs using
ioctl function would set and get this number (manipulate it). So i
have two ioctl commands: IO_SET_TREASURE and IO_GET_TREASURE. First
one works very well, but second has some bugs. In my "demo
application" I just want to get this treasure to some output value not
as return value from function. This way works as well but I can`t
manage with output values. Here is the source code. At the beginning
my "first.h" file:
#ifndef FIRST_H
#define FIRST_H
/* header`s files */
#include <linux/ioctl.h>
/* some constants for my device drivers */
#define FIRST_MAJOR 250
#define FIRST_MAGIC 'E'
#define DEV_LICENSE "GPL"
#define SUCCESS 0
#define DEVICE_NAME "MyFirstDevice"
#define BUF_LEN 128
/* there is, our ioctls */
#define IO_SET_TREASURE _IOW(FIRST_MAGIC, 0, unsigned long)
#define IO_GET_TREASURE _IOR(FIRST_MAGIC, 1, unsigned long)
/* and name of device */
#define DEVICE_FILE_NAME "MyFirstDevice"
#endif
I think whole *.c file with code of device driver will be too big and
unnecessary, so I will paste only ioctl function:
static int FirstModule_Ioctl(struct inode* inode, struct file* file,
unsigned int number, unsigned long param)
{
int err = 0;
/* checking numbes to decode */
if (_IOC_TYPE(number) != FIRST_MAGIC) return -ENOTTY;
if (_IOC_NR(number) > 2) return -ENOTTY;
/* checking access mode */
if (_IOC_DIR(number) & _IOC_READ)
err = !access_ok(VERIFY_WRITE, (void __user *)param,
_IOC_SIZE(number));
else if (_IOC_DIR(number) & _IOC_WRITE)
err = !access_ok(VERIFY_READ, (void __user *)param,
_IOC_SIZE(number));
if (err)
return -EFAULT;
switch(number){
case IO_SET_TREASURE:
secretTreasure = param;
printk(KERN_INFO "New Secret Treasure has been set up as: %d\n",
secretTreasure);
break;
case IO_GET_TREASURE:
put_user(secretTreasure, (unsigned long *)param);
printk(KERN_INFO "Secret Treasure is: %d\n and param is: %d",
secretTreasure, param);
//return secretTreasure;
break;
}
return SUCCESS;
}
As You can see I commented "return secretTreasure". It works but i
don`t want solve my trouble in that way. Return value must be for
error-checking not for secret number. I was trying to use some
put_user() macro. Of course it didn`t help me. Here is my demo
program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include "first.h"
void ioctl_set_trs(int fd, unsigned long new_number)
{
int ret;
if((ret = ioctl(fd, IO_SET_TREASURE, new_number)) < 0)
{
printf("IOCTL (set_trs) failed: %d\n", ret);
perror("ioctl");
exit(-1);
}
}
void ioctl_get_trs(int fd)
{
int ret;
unsigned treasure;
if( (ret = ioctl(fd, IO_GET_TREASURE, treasure)) < 0)
{
printf("IOCTL failed: %d\n", ret);
perror("ioctl");
exit(-1);
}
printf("Here is secret number for You: %d and ret: %d\n", treasure,ret);
}
int main()
{
int fd, ret;
unsigned long new_treasure = 47;
fd = open("/dev/MyFirstDevice",0);
if(fd < 0){
printf("I can`t open %s\n", DEVICE_FILE_NAME);
perror("open");
exit(-1);
}
ioctl_set_trs(fd, new_treasure);
ioctl_get_trs(fd);
return 0;
}
When i fire up this application I can see this message: <<Here is
secret number for You: 0 and ret: 0>> Of course ret == 0 but why does
my param value equal to zero ? When i look at dmesg output there is
something like this:
"New Secret Treasure has been set up as: 47
Secret Treasure is: 47"
And this comes from IO_GET_TREASURE, so everything in kernel mode is
set properly but not in userspace. Thanks for any help
--
-----BEGIN GEEK CODE BLOCK-----
GCS d- s:- a--- C+++ P L+++>+++++ E---- W+ N+ o? K- w--- O- M- V? PS++
PE++ Y PGP++ t--- 5? X R tv-- b+ DI+ D- G++ e- h! !r(--) !z+
------END GEEK CODE BLOCK------
--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to [EMAIL PROTECTED]
Please read the FAQ at http://kernelnewbies.org/FAQ