Getting ENOTTY on ioctl for a Linux Kernel Module

6.1k views Asked by At

I have the following chardev defined:

.h

#define MAJOR_NUM 245
#define MINOR_NUM 0
#define IOCTL_MY_DEV1 _IOW(MAJOR_NUM, 0, unsigned long)
#define IOCTL_MY_DEV2 _IOW(MAJOR_NUM, 1, unsigned long)
#define IOCTL_MY_DEV3 _IOW(MAJOR_NUM, 2, unsigned long)

module .c

static long device_ioctl(
                  struct file*   file,
                  unsigned int   ioctl_num,
                  unsigned long  ioctl_param)
{
    ...
}

static int device_open(struct inode* inode, struct file* file)
{
    ...
}

static int device_release(struct inode* inode, struct file* file)
{
    ...
}

struct file_operations Fops = {
    .open=device_open,
    .unlocked_ioctl= device_ioctl,
    .release=device_release
};

static int __init my_dev_init(void)
{
    register_chrdev(MAJOR_NUM, "MY_DEV", &Fops);
    ...
}
module_init(my_dev_init);

My user code

ioctl(fd, IOCTL_MY_DEV1, 1);

Always fails with same error: ENOTTY

Inappropriate ioctl for device

I've seen similar questions: i.e

Linux kernel module - IOCTL usage returns ENOTTY

Linux Kernel Module/IOCTL: inappropriate ioctl for device

But their solutions didn't work for me

1

There are 1 answers

0
Luis Colorado On

ENOTTY is issued by the kernel when your device driver has not registered a ioctl function to be called. I'm afraid your function is not well registered, probably because you have registered it in the .unlocked_ioctl field of the struct file_operations structure.

Probably you'll get a different result if you register it in the locked version of the function. The most probable cause is that the inode is locked for the ioctl call (as it should be, to avoid race conditions with simultaneous read or write operations to the same device)

Sorry, I have no access to the linux source tree for the proper name of the field to use, but for sure you'll be able to find it yourself.

NOTE

I observe that you have used macro _IOW, using the major number as the unique identifier. This is probably not what you want. First parameter for _IOW tries to ensure that ioctl calls get unique identifiers. There's no general way to acquire such identifiers, as this is an interface contract you create between application code and kernel code. So using the major number is bad practice, for two reasons:

  • Several devices (in linux, at least) can share the same major number (minor allocation in linux kernel allows this) making it possible for a clash between devices' ioctls.
  • In case you change the major number (you configure a kernel where that number is already allocated) you have to recompile all your user level software to cope with the new device ioctl ids (all of them change if you do this)

_IOW is a macro built a long time ago (long ago from the birth of linux kernel) that tried to solve this problem, by allowing you to select a different character for each driver (but not dependant of other kernel parameters, for the reasons pointed above) for a device having ioctl calls not clashing with another device driver's. The probability of such a clash is low, but when it happens you can lead to an incorrect machine state (you have issued a valid, working ioctl call to the wrong device)

Ancient unix (and early linux) kernels used different chars to build these calls, so, for example, tty driver used 'T' as parameter for the _IO* macros, scsi disks used 'S', etc.

I suggest you to select a random number (not appearing elsewhere in the linux kernel listings) and then use it in all your devices (probably there will be less drivers you write than drivers in the kernel) and select a different ioctl id for each ioctl call. Maintaining a local ioctl file with the registered ioctls this way is far better than trying to guess a value that works always.

Also, a look at the definition of the _IO* macros should be very illustrative :)