Device Control theory
1. The role of device control
Most drivers require the ability to control equipment in addition to the ability to provide read and write equipment. Change the baud rate, for example.
2. Function of Device control
Use the IOCTL system to invoke functions in user space to control the device.
int ioclt (int fd, unsigned long cmd, ...)
FD: Device file descriptor to control
CMD: Commands sent to the device
...: The third parameter is an optional parameter, whether the presence or absence is dependent on the control command
When an application uses the IOCLT system call, the driver responds with the following function:
1.2.6.36 the previous kernel
Long (*IOCLT) (struct inode *node, struct file *filp, unsigned int cmd, unsigned long arg)
2.2.6.36 after the kernel
Long (*unlocked_ioctl) (struct file *filp, unsigned int cmd, unsigned long arg)
Parameter cmd: commands passed down through the application IOCTL
Realization of equipment control
1. Defining commands
The command is an integer in its essence, but to make the integer more readable, we usually divide the integer into several segments: type (8 bits), ordinal, parameter pass direction, parameter length
Type (Types/magic number): Indicates which device the command belongs to.
Number (ordinal): A different command used to distinguish the same device.
Direction: The direction of the parameter pass, which can be _ioc_none (no data transfer), _ioc_read (reading data from the device), _ioc_write (writing data to the device)
Size: Parameter length
The Linux system provides the following macros to help define the command:
_io (type, number): command with no arguments
_ior (type, number, datatype): command to read parameters from the device
_iow (type, number, datatype): command to write parameters to the device
Example:
#define Mem_magic ' m '
#define Mem_set _iow (mem_magic, 0, int)
2. Operation implementation
The reality of the UNLOCKED_IOCLT function is usually a switch statement executed according to the command. However, when the command does not match the command supported by any one device, the-einval is returned.
Programming Model:
Switch (CMD) {
Case A:
Perform a corresponding operation
Case B:
Perform a corresponding operation of B
Default
Return-einval
}
Memdev.h
// Defining Commands #define Mem_magic ' M ' // device magic number #define mem_rst _io (mem_magic, 0) // restart command #define Mem_set _iow (mem_magic, 1, int) // set command
Memdev.c
#include <linux/init.h>#include<linux/module.h>#include<linux/cdev.h>#include<linux/fs.h>#include<asm/uaccess.h>#include"memdev.h"//Global VariablesstructCdev Memdev;//character Devicedev_t Devnum;//Device numberintregister0[5];//Device 0 Registerintregister1[5];//Device 1 Register//Positioning Equipmentloff_t Mem_lseek (structFile *filp, loff_t offset,intwhence) { //Set Locationloff_t Newpos; Switch(whence) { CaseSeek_set:newpos=offset; Break; CaseSeek_cur:newpos= Filp->f_pos +offset; Break; CaseSeek_end:newpos= (5*sizeof(int)) +offset; Break; default: Newpos=0; Break; } //Move PositionFilp->f_pos =Newpos; returnNewpos;}//Read Devicessize_t Mem_read (structFile *filp,Char__user *buf, size_t size, loff_t *PPOs) { //Get Address int*Base; Base= Filp->private_data + *PPOs; //reading DataCopy_to_user (BUF,Base, size); //Move PositionFilp->f_pos + =size; returnsize;}//Write Devicessize_t Mem_write (structFile *filp,Const Char__user *buf, size_t size, loff_t *PPOs) { //Get Address int*Base; Base= Filp->private_data + *PPOs; //Write DataCopy_from_user (Base, buf, size); //Move PositionFilp->f_pos + =size; returnsize;}
//Control equipment LongMem_ioctl (structFile *filp, unsignedintCMD, unsignedLongArg) { //Processing Commands Switch(cmd) { CaseMem_rst://Restart commandPrintk"Reset device\n"); Break; CaseMem_set://SET CommandPrintk"set ARG is%d\n", ARG); Break; default://Error naming return-EINVAL; } return 0;}//turn on the deviceintMem_open (structInode *node,structFile *Filp) { //get the secondary device number intSecnum; Secnum= MINOR (node->I_rdev); //Set Device Address if(Secnum = =0) {Filp->private_data =Register0; } if(Secnum = =1) {Filp->private_data =Register1; } return 0;}//turn off the deviceintMem_colse (structInode *node,structFile *Filp) { return 0;}//Device MethodstructFile_operations Memfops ={. Llseek=Mem_lseek,. Read=Mem_read,. Write=mem_write,. Unlocked_ioctl=mem_ioctl,. Open=Mem_open,. Release=Mem_colse};//Driver RegistrationStatic intMemdev_init () {//registering the device structureCdev_init (&memdev, &memfops); //registering a master device numberAlloc_chrdev_region (&devnum,0,2,"Memdev"); //Add Device StructureCdev_add (&memdev, Devnum,2); return 0;}//Driver LogoffStatic voidMemdev_exit () {//Unregister device StructureCdev_del (&Memdev); //Unregister the main device numberUnregister_chrdev_region (Devnum,2);}//Drive StatementModule_license ("GPL"); Module_author ("D"); Module_description ("Memdev"); Module_version ("v1.0"); Module_init (Memdev_init); Module_exit (memdev_exit) ;
Contorl.c
#include <sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<unistd.h>#include<sys/ioctl.h>#include"memdev.h"intMainintargcChar**argv) { //turn on the device intFD; FD= Open ("/dev/memdev0", O_RDWR); //set up your deviceIOCTL (FD, Mem_set,115200); //Restarting the deviceIOCTL (FD, Mem_rst); //turn off the deviceClose (FD); return 0;}
[Country EMBED strategy] [116] [Character device control technology]