In the driver, the variable cmd that is passed on the IOCTL () function is the value that the application uses to differentiate the contents of the device driver request processing. In addition to distinguishing numbers, CMD contains several appropriate information that can help with processing. The size of CMD is 32 bits and is divided into 4 domains:
The Bit31~bit30 2-bit is a "read-and-write" area that distinguishes between a read command or a write command.
bit29~bit15 14 bits is the data size area, which represents the amount of memory transferred by the ARG variable in the IOCTL ().
The bit20~bit08 8-bit is the "magic number" (also known as the "magic number") area, which is used to differentiate from the IOCTL commands of other device drivers.
bit07~bit00 8-bit is the "difference ordinal" area, which is a command sequence ordinal that distinguishes commands.
The value in the "read-write zone" in the command code may be _ioc_none (0 value) indicating no data transfer, _ioc_read (read), _ioc_write (write), _ioc_read|_ioc_write (bidirectional).
The kernel defines the 4 macros _io (), _ior (), IOW (), and _IOWR () to assist in generating the above cmd. The following is an analysis of the implementation of _io (), other similar:
You can see the definition of _io () in asm-generic/ioctl.h :
#define _IO (TYPE,NR) _ioc (_ioc_none, (Type), (NR), 0)
then look at the definition of _IOC () :
#define _IOC (dir,type,nr,size) \
((dir) << _ioc_dirshift) | \
((type) << _ioc_typeshift) | \
((NR) << _ioc_nrshift) | \
((size) << _ioc_sizeshift))
As can be seen, the final result of _io () is a combination of the 4 parameter shifts in _IOC ().
then look at the definition of _ioc_dirshit :
#define _IOC_DIRSHIFT (_ioc_sizeshift+_ioc_sizebits)
definition of _ioc_sizeshift :
#define _IOC_SIZESHIFT (_ioc_typeshift+_ioc_typebits)
definition of _ioc_typeshif :
#define _IOC_TYPESHIFT (_ioc_nrshift+_ioc_nrbits)
definition of _ioc_nrshift :
#define _IOC_NRSHIFT 0
definition of _ioc_nrbits :
#define _IOC_NRBITS 8
definition of _ioc_typebits :
#define _IOC_TYPEBITS 8
by the definition above, the upward push gets :
Reference
_ioc_typeshift = 8
_ioc_sizeshift = 16
_ioc_dirshift = 30
Therefore, the (dir) << _ioc_dirshift) Table is dir moving to the left 30 bits, that is, moving to bit31~bit30 two bits, to obtain the direction (read and write) properties;
(size) << _ioc_sizeshift) bit left 16 bits get "data size" area;
(type) << _ioc_typeshift) shift left 8 to get "magic number Area";
(NR) << _ioc_nrshift) move left 0 bits (bit7~bit0).
In this way, the macro value of _io () is obtained.
These macros are used in the following formats :
- _io (magic number, radix);
- _ior (magic number, cardinality, variable type)
- _iow (magic number, cardinality, variable type)
- _IOWR (magic number, cardinality, variable type)
Magic Numbers (magic number)
The magic number range is 0~255. Typically, the English characters "a" ~ "Z" or "a" ~ "Z" are represented. The device driver obtains the magic number from the command passed in, and then compares it to the number of demons it handles, and if the same is handled, the difference is not processed. The magic number is the primary auxiliary state that denies misuse. The device driver can get the magic number by _ioc_type (CMD). Different device drivers are best to set different magic numbers, but not absolute, but also the number of magic numbers that can be used by other device drivers.
Number of base (serial number)
The cardinality is used to differentiate between various commands. Typically, the value is incremented from 0, which can be reused on the same device driver. For example, the same cardinality is used in the read and write commands, and device drivers can be distinguished because the device driver uses switch when differentiating commands and uses the command variable cmd value directly. The macro generated by creating a command is composed of multiple domains, so even the same cardinality is judged as a different command. To get the cardinality from the command, the device driver uses the following macro:
_IOC_NR (CMD)
Typically, the case value in switch uses the command itself.
Variable type
The variable type uses the ARG variable to specify the size of the data being transferred, but instead of substituting the input directly, it is substituting the variable or the type of the variable, because the sizeof () Compile command is already included in the use of the macro creation command. For example, the _ior () macro is defined as:
Reference
#define _ior (type,nr,size) _ioc (_ioc_read, (Type), (NR), (_ioc_typecheck (size)))
And the definition of _ioc_typecheck () is:
Reference
#define _ioc_typecheck (t) (sizeof (t))
The following macro functions are used by the device driver to obtain the corresponding value from the routed command:
_ioc_size (CMD)
_IO macro
The macro function does not have a variable that can be transferred, but is used to transfer commands. For example, the following conventions:
Reference
#define Test_drv_reset _io (' Q ', 0)
At this point, omit the ARG variable passed by the application or substitute 0. When you use the macro in your application, such as:
IOCTL (Dev, test_dev_reset, 0) or ioctl (Dev, test_drv_reset).
This is because the effective factor of the variable is the variable factor. When used only as a command, it is not necessary to determine the output or input of the data on the device. Therefore, it is not necessary for the device driver to perform the related processing of the device File open option.
_IOR macro
This function is used to create commands that read data from the device, such as the following conventions:
Reference
#define Test_dev_read _IRQ (' Q ', 1, int)
This indicates that the application reads data from the device to the size int. The following macro is used to determine the read and write status of the cmd command delivered to the device driver:
_ioc_dir (CMD)
When you run the macro, the type of the return value is as follows:
- _ioc_none: No attribute
- _ioc_read: Readable properties
- _ioc_write: Writable Properties
- _ioc_read | _ioc_write: Readable, writable property
When you use this command, the ARG variable value of the application's IOCTL () specifies the cache (struct) address when the data is read on the device driver.
_IOW macro
Used to create a command to write data on the device, the remainder is the same as _ior. Typically, when you use this command, the ARG variable value of the IOCTL () specifies the cache (struct) address when the data is written on the device driver.
_IOWR macro
The command used to create read and write data on the device. The remainder is the same as _ior. Typically, when you use this command, the ARG variable value of the IOCTL () specifies the cache (struct) address when the data is written or read on the device driver.
definition of _ior (), _iow (), Iorw ( ):
#define _ior (type,nr,size) _ioc (_ioc_read, (Type), (NR), (_ioc_typecheck (size)))
#define _IOW (type,nr,size) _ioc (_ioc_write, (Type), (NR), (_ioc_typecheck (size)))
#define _IOWR (type,nr,size) _ioc (_ioc_read|_ioc_write, (Type), (NR), (_ioc_typecheck (size)))
Usage and parsing of _io, _ior, _IOW, _IOWR macros in Linux kernel drivers