what is the meaning of this macro _IOR(MY_MACIG, 0, int)? - linux

i was going through ioctl sample programs to check how it communicates with kernel space. in program WRITE_IOCTL is used as command
#define WRITE_IOCTL _IOW(MY_MACIG, 1, int)
ioctl(fd, WRITE_IOCTL, "hello world")
I am not able to understand what is _IOW(MY_MACIG, 1, int).
here is the link from where i downloaded the program. please help me.
http://people.ee.ethz.ch/~arkeller/linux/multi/kernel_user_space_howto-4.html

As you may know, an ioctl should be unique, as explained in the Linux Device Drivers book:
The ioctl command numbers should be unique across the system in order
to prevent errors caused by issuing the right command to the wrong
device.Such a mismatch is not unlikely to happen, and a program might
find itself trying to change the baudrate of a non-serial-port input
stream, such as a FIFO or an audio device. If each ioctl number is
unique, the application gets an EINVAL error rather than succeeding in
doing something unintended.
Furthermore, an ioctl can require to write data to and/or read data from kernel space.
When one creates it's own driver that performs ioctls, he will need to describe all this in the ioctl command.
_IO, _IOW, _IOR, _IORW are helper macros to create a unique ioctl identifier and add the required R/W needed features (direction).
These can take the following params: magic number, the command id, and the data type that will be passed (if any)
The magic number is a unique number that will allow the driver to detect errors such as the one mentioned in the LDD book's quote.
The command id, is a way for your dirver to understand what command is needed to be called.
Last parameter (the type) will allow the kernel to understand the size to be copied.
hope this helps.
PS: you can have more details in Linux Device Drivers book (chapter 6)
https://lwn.net/images/pdf/LDD3/ch06.pdf

From http://www.circlemud.org/jelson/software/fusd/docs/node31.html:
The Linux header file /usr/include/asm/ioctl.h defines macros that must be used to create the ioctl command number. These macros take various combinations of three arguments:
type, an 8-bit integer selected to be specific to the device driver. type should be chosen so as not to conflict with other drivers that might be ``listening'' to the same file descriptor. (Inside the kernel, for example, the TCP and IP stacks use distinct numbers since an ioctl sent to a socket file descriptor might be examined by both stacks.)
number, an 8-bit integer command number. Within a driver, distinct numbers should be chosen for each different kind of ioctl command that the driver services
data_type, the name of a type used to compute how many bytes are exchanged between the client and the driver. This argument is, for example, the name of a structure.
The macros used to generate command numbers are:
_IO(int type, int number), used for a simple ioctl that sends nothing but the type and number, and receives back nothing but an (integer) retval
_IOR(int type, int number, data_type), used for an ioctl that reads data from the device driver. The driver will be allowed to return sizeof(data_type) bytes to the user
_IOW(int type, int number, data_type), similar to _IOR, but used to write data to the driver
_IORW(int type, int number, data_type), a combination of _IOR and _IOW. That is, data is both written to the driver and then read back from the driver by the client

Related

Should Linux character devices terminate read() with newline

POSIX defines a text file as:
A file that contains characters organized into one or more lines.
POSIX defines a line as
A sequence of zero or more non-newline characters plus a terminating newline character.
Given this, should the read() function of a Linux character device driver append '\n' to the user buffer when it reaches EOF/has no more data?
Concept of char drivers is analogous to a stream. In this light, read just returns whatever happens to be available next. Now what is available will usually be part of definition of the device whose driver it is. If the device returns newline character then so should the driver. Note that this means the device will return newline on all platforms, not just Linux.
In general, interpretating the bytes returned by read is a matter of higher level abstraction. In terms of policy vs mechanism, char driver can be thought of as providing mechanism, leaving policy to higher layers.
In classic Unix, the difference between character devices and block devices is that block devices support seek, which implies that they are addressable, in units of fixed sized disk blocks. Character devices do not support seek, they just deliver or accept a stream of characters.
In linux, a device driver is implemented as a struct, containing some flags and parameters plus a collection of function pointers, implementing the methods for read()/write()/etc. Block (disk) drivers will also implement seek(), and maybe even mmap().
Normally, device drivers do not interfere with the actual content being transferred, they only move bytes or blocks to/from the device, using the (hardware) protocol that the device needs (such as manipulating the internal control registers, inspecting status registers, ...)

Modifying IOCTL function call (where is the definition of ioctl) to flip GPIO pins

I want to know as to where IOCTL is defined. I want to flip the state of a GPIO pin from within the IOCTL function call. I am using Yocto linux.
The ioctl requests are defined per driver. For the new chardev GPIO this is defined in <linux/gpio.h>.
The logic these values are encoded is in <asm/ioctl.h>. Please note, that this is platform dependent (e.g. MIPS is different than x86 and x86_64).
If you are interested, here is the logic ported to rust: https://docs.rs/nix/0.11.0/src/nix/sys/ioctl/linux.rs.html
However in practice you shouldn't need to convert these request codes on your own. You would just include <linux/gpio.h> and then you can use the defined IOCTL request codes like GPIOHANDLE_GET_LINE_VALUES_IOCTL. Here are some example implementations: https://github.com/torvalds/linux/tree/master/tools/gpio
ioctl is a c-language kernel function declared in <sys/ioctl.h>. See the linux manual page.
Here's a copy of the upper portion:
NAME
ioctl - control device
SYNOPSIS
#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);
DESCRIPTION
The ioctl() function manipulates the underlying device parameters of
special files. In particular, many operating characteristics of
character special files (e.g., terminals) may be controlled with
ioctl() requests. The argument fd must be an open file descriptor.
The second argument is a device-dependent request code. The third
argument is an untyped pointer to memory. It's traditionally char
*argp (from the days before void * was valid C), and will be so named
for this discussion.
An ioctl() request has encoded in it whether the argument is an in
parameter or out parameter, and the size of the argument argp in
bytes. Macros and defines used in specifying an ioctl() request are
located in the file <sys/ioctl.h>.

Designing a Linux char device driver so multiple processes can read

I notice that for serial devices, e.g. /dev/ttyUSB0, multiple processes can open the device but only one process gets the bytes (whichever reads them first).
However, for the Linux input API, e.g. /dev/input/event0, multiple processes can open the device, and all of the processes are able to read the input events.
My current goal:
I'd like to write a driver for several multi-position switches (e.g. like a slider switch with 3 or 4 possible positions), where apps can get a notification of any switch position changes. Ideally I'd like to use the Linux input API, however it seems that the Linux input API has no support for the concept of multi-position switches. So I'm looking at making a custom driver with similar capabilities to the Linux input API.
Two questions:
From a driver design point-of-view, why is there that difference in behaviour between Linux input API and Linux serial devices? I reckon it could be useful for multiple processes to all be able to open one serial port and all listen to incoming bytes.
What is a good way to write a Linux character device driver so that it's like the Linux input API, so multiple processes can open the device and read all the data?
The distinction is partly historical and partly due to the different expectation models.
The event subsystem is designed for unidirectional notification of simple events from multiple writers into the system with very little (or no) configuration options.
The tty subsystem is intended for bidirectional end-to-end communication of potentially large amounts of data and provides a reasonably flexible (albeit fairly baroque) configuration mechanism.
Historically, the tty subsystem was the main mechanism of communicating with the system: you plug your "teletype" into a serial port and bits went in and out. Different teletypes from different vendors used different protocols and thus the termios interface was born. To make the system perform well in a multi-user context, buffering was added in the kernel (and made configurable). The expectation model of the tty subsystem is that of a point-to-point link between moderately intelligent endpoints who will agree on what the data passing between them will look like.
While there are circumstances where "single writer, multiple readers" would make sense in the tty subsystem (GPS receiver connected to a serial port, continually reporting its position, for instance), that's not the main purpose of the system. But you can easily accomplish this "multiple readers" in userspace.
The event system on the other hand, is basically an interrupt mechanism intended for things like mice and keyboards. Unlike teletypes, input devices are unidirectional and provide little or no control over the data they produce. There is also little point in buffering the data. Nobody is going to be interested in where the mouse moved ten minutes ago.
I hope that answers your first question.
For your second question: "it depends". What do you want to accomplish? And what is the "longevity" of the data? You also have to ask yourself whether it makes sense to put the complexity in the kernel or if it wouldn't be better to put it in userspace.
Getting data out to multiple readers isn't particularly difficult. You could create a receive buffer per reader and fill each of them as the data comes in. Things get a little more interesting if the data comes in faster than the readers can consume it, but even that is mostly a solved problem. Look at the network stack for inspiration!
If your device is simple and just produces events, maybe you just want to be an input driver?
Your second question is a lot more difficult to answer without knowing more about what you want to accomplish.
Update after you added your specific goal:
When I do position switches, I usually just create a character device and implement poll and read. If you want to be fancy and have a lot of switches, you could do mmap but I wouldn't bother.
Userspace just opens your /dev/foo and reads the current state and starts polling. When your switches change state, you just wake up the readers and they they'll read again. All your readers will wake up, they'll all read the new state and everyone will be happy.
Be careful to only wake up readers when your switches are 'settled'. Many position switches are very noisy and they'll bounce around a fair bit.
In other words: I would ignore the input system altogether for this. As you surmise, position switches are not really "inputs".
How a character device handles these kinds of semantics is completely up to the driver to define and implement.
It would certainly be possible, for example, to implement a driver for a serial device that will deliver all read data to every process that has the character driver open. And it would also be possible to implement an input device driver that delivers events to only one process, whichever one is queued up to receive the latest event. It's all a matter of coding the appropriate implementation.
The difference is that it all comes down to a simple question: "what makes sense". For a serial device, it's been decided that it makes more sense to handle any read data by a single process. For an input device, it's been decided that it makes more sense to deliver all input events to every process that has the input device open. It would be reasonable to expect that, for example, one process might only care about a particular input event, say pointer button #3 pressed, while another process wants to process all pointer motion events. So, in this situation, it might make more sense to distribute all input events to all concerned parties.
I am ignoring some side issues, for simplicity, like in the situation of serial data being delivered to all reading processes what should happen when one of them stops reading from the device. That's also something that would be factored in, when deciding how to implement the semantics of a particular device.
What is a good way to write a Linux character device driver so that it's like the Linux input API, so multiple processes can open the device and read all the data?
See the .open member of struct file_operations for the char device. Whenever userspace opens the device, then the .open function is called. It can add the open file to a list of open files for the device (and then .release removes it).
The char device data struct should most likely use a kernel struct list_head to keep a list of open files:
struct my_dev_data {
...
struct cdev cdev;
struct list_head file_open_list;
...
}
Data for each file:
struct file_data {
struct my_dev_data *dev_data;
struct list_head file_open_list;
...
}
In the .open function, add the open file to dev_data->file_open_list (use a mutex to protect these operations as needed):
static int my_dev_input_open(struct inode * inode, struct file * filp)
{
struct my_dev_data *dev_data;
dev_data = container_of(inode->i_cdev, struct my_dev_data, cdev);
...
/* Allocate memory for file data and channel data */
file_data = devm_kzalloc(&dev_data->pdev->dev,
sizeof(struct file_data), GFP_KERNEL);
...
/* Add open file data to list */
INIT_LIST_HEAD(&file_data->file_open_list);
list_add(&file_data->file_open_list, &dev_data->file_open_list);
...
file_data->dev_data = dev_data;
filp->private_data = file_data;
}
The .release function should remove the open file from dev_data->file_open_list, and release the memory of file_data.
Now that the .open and .release functions maintain the list of open files, it is possible for all open files to read data. Two possible strategies:
A separate read buffer for each open file. When data is received, it is copied into the buffers of all open files.
A single read buffer for the device, but a separate read pointer for each open file. Data can be freed from the buffer once it has been read through all open files.
Serial to input/event
You could try to look into serial mouse driver source code.
This seem to be what you're searching for: from a TTYSx build a input/event device.
Simplier: creating a server, instead of a driver.
Historically, the 1st character device I remember is /dev/lp0.
To be able to write on it from many source, without overlap or other conflict,
a LPR server was wrotten.
To share a device, you have to
open this device in exclusive (rw) mode.
Create a socket (un*x or TCP) to listen on
redirect request from socket's clients to the device and maybe
store device status (from reading device's answers)
send device status to socket's clients when required.

What is the difference between register_chrdev_region and alloc_chrdev_region to allocate device numbers?

I want to know the difference between these two functions:
int register_chrdev_region(dev_t first, unsigned int count, char *name);
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
See here for details on these two functions.
Registration is only really useful if you know in advance which major number you want to start with. With registration, you tell the kernel what device numbers you want (the start major/minor number and count) and it either gives them to you or not (depending on availability).
With allocation, you tell the kernel how many device numbers you need (the starting minor number and count) and it will find a starting major number for you, if one is available, of course.
Partially to avoid conflict with other device drivers, it's considered preferable to use the allocation function, which will dynamically allocate the device numbers for you.
From the link given above:
Some major device numbers are statically assigned to the most common devices. A list of those devices can be found in Documentation/devices.txt within the kernel source tree. The chances of a static number having already been assigned for the use of your new driver are small, however, and new numbers are not being assigned. So, as a driver writer, you have a choice: you can simply pick a number that appears to be unused, or you can allocate major numbers in a dynamic manner.
Picking a number may work as long as the only user of your driver is you; once your driver is more widely deployed, a randomly picked major number will lead to conflicts and trouble.
Thus, for new drivers, we strongly suggest that you use dynamic allocation to obtain your major device number, rather than choosing a number randomly from the ones that are currently free. In other words, your drivers should almost certainly be using alloc_chrdev_region rather than register_chrdev_region.
The disadvantage of dynamic assignment is that you can't create the device nodes in advance, because the major number assigned to your module will vary. For normal use of the driver, this is hardly a problem, because once the number has been assigned, you can read it from /proc/devices.
There's a related, but not technically duplicate, question here.
To put in simple terms:
You use register_chrdev_region when you have the device ID for your character driver with you and you want to inform the VFS that reserve this device ID (basically the Major Number) for your driver.
dev_t mydev;
mydev = MKDEV(MAJORNO, MINORNO);//you have already decided on a static majorno and minorno
register_chrdev_region(mydev, count, CHAR_DEV_NAME)
//**here you are supplying the device ID in mydev**
You use alloc_chrdev_region when you are asking the VFS to give you a free device ID (which is basically the major number) for your character driver.
dev_t mydev;
//you are asking VFS for the device ID
alloc_chrdev_region(&mydev, start_minor_no, count, CHAR_DEV_NAME)
//**Here you get the device ID in mydev**.
As per the LDD3 Document,
When setting up a character device is to obtain one or more device numbers to work with. The necessary function for this task is,
int register_chrdev_region(dev_t first, unsigned int count, char *name);
(or)
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor,
unsigned int count, char *name);
Note that, register_chrdev_region works well if you know ahead of time exactly which device numbers you want. Often, however, you will not know which major numbers your device will use; there is a constant effort within the Linux kernel development community to move over to the use of dynamicly-allocated device numbers. The kernel will happily allocate a major number for you on the fly, but you must request this allocation by using a alloc_chrdev_region. Basically its a dynamic Allocation of the Major number.
Thus, for new drivers, we strongly suggest that you use dynamic allocation to obtain your major device number, rather than choosing a number randomly from the ones that are currently free. In other words, your drivers should almost certainly be using alloc_chrdev_region rather than register_chrdev_region.

How to get the parity bit from characters received by serial port?

I am writing a driver for a device that is connected by serial port. Unfortunately, the 9th data bit indicates whether the character should be interpreted as command or as data.
Using the built-in parity check does not work for me because an error is indicated by an additional character (NUL). And then I don't know wheter I received two data bytes or one with an parity error.
Is there a way to get this parity bit elsewhere?
EDIT: Apparently, this problem also exists on Windows (see http://gilzu.com/?p=6). It ended up with rewriting the serial driver. Is this also my only option on Linux?
As I see it, you should be able to use PARMRK as is, assuming that the \377 \0 pattern is unlikely to appear in your input. otherwise, yes, you may modify your serial driver to prepend the parity (or rather, if this byte had a parity error) to each byte. I'd go with the former, though.

Resources