ioctl
Not a Typewriter
“In computing, Not a typewriter or
ENOTTYis an error code defined in theerrno.hfound on many Unix systems. This code is now used to indicate that an invalidioctl(input/output control) number was specified in anioctlsystem call.”
NuttX
In ioctl() implementations in NuttX, -ENOTTY is always returned
if the ioctl() command is not recognized. You will often see driver
ioctl() implement ions with a general structure similar to the following:
int driver_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
int ret;
switch (cmd)
{
...
default:
ret = -ENOTTY;
break;
}
}
return ret;
}
Note that -ENOTTY is returned internally in NuttX.
This will subsequently be used to set the errno value to ENOTTY
and to return -1 to indicate the error condition.
ERRORS
These are the return values from a Linux ioctl() call:
EBADFfd is not a valid file descriptor.EFAULTargp references an inaccessible memory area.EINVALrequest or argp is not valid.ENOTTYfd is not associated with a character special device.ENOTTYThe specified request does not apply to the kind of object that the file descriptor fd references.
Reference: https://www.man7.org/linux/man-pages/man2/ioctl.2.html.
Linux Explanation
On Jun 27 Linus Torvalds wrote:
“The correct error code for “I don’t understand this ioctl” is ENOTTY. The naming may be odd, but you should think of that error value as a “unrecognized ioctl number, you’re feeding me random numbers that I don’t understand and I assume for historical reasons that you tried to do some tty operation on me”. … The EINVAL thing goes way back, and is a disaster. It predates Linux itself, as far as I can tell. You’ll find lots of man-pages that have this line in it:
EINVAL Request or argp is not valid.
and it shows up in POSIX etc. And sadly, it generally shows up _before_ the line that says
ENOTTY The specified request does not apply to the kind of object that the descriptor d references.
so a lot of people get to the EINVAL, and never even notice the ENOTTY.
(..)
At least glibc (and hopefully other C libraries) use a _string_ that makes much more sense: strerror(ENOTTY) is “Inappropriate ioctl for device”.”
How is this useful?
Knowing that no error occurred but the ioctl() command was not recognized
is a useful piece of information.
Suppose, for example, I have nfds open character drivers in an array fd[].
Then I could do something like this:
int do_command(FAR int *fd, int nfds, int cmd)
{
int ret;
int i;
/* Try all file descriptors */
for (i = 0; i < nfds; i++)
{
ret = ioctl(fd[i], cmd, 0ul); /* No argument in this example */
if (ret < 0)
{
int errcode = errno;
/* Try the next file descriptor if this one return ENOTTY */
if (errcode != ENOTTY)
{
/* Other errors, including EINVAL, are fatal */
return -errcode
}
}
else if (ret >= 0)
{
return OK; /* Success! */
}
}
return -ENOENT;
}