Basic process for writing Linux character device drivers

Source: Internet
Author: User
--- Brief introduction: Although the MISC simple character device driver in Linux is simple to use, it is not flexible. Only device files with the master device Number 10 can be created. Character device comparison --- overview

The driver of MISC simple character device in Linux is simple but not flexible.
Only device files with the master device Number 10 can be created.
Character devices are easy to understand and can meet the needs of most simple hardware devices.
Character devices are read by name in the file system. These are file systems.
A special file or a simple node called a device file or file system in
If you use ls in the/dev/directory to view the file, the file starting with C is displayed.
Crw -- w ---- 1 root tty 4, 0 April 14 11:05 tty0. The first number is the master
The second digit is the secondary device number.

--- Assign and release device numbers
1) when creating a character device driver, you must first obtain the device number.
The function is register_chrdev_region, which is declared in linux/fs. h:
Int register_chrdev_region (dev_t first, unsigned int count, char * name );
First is the start device number you want to assign. first is usually 0, count
Is the total number of consecutive devices you requested. If count is too large, it will overflow to the next
The master device number. Name is the name of the device, which appears in/proc/devices and sysfs.
If the operation succeeds, 0 is returned. if the operation fails, a negative error code is returned.
2) if you explicitly know that the device number is available, the previous method is feasible. Otherwise, we can use
The kernel dynamically allocates the device number int alloc_chrdev_region (dev_t * dev, unsigned int firstminor,
Unsigned int count, char * name );
Dev is an output-only parameter. The first number to be used in the firstminor request, count and name
(1) for new drivers, the best way is to perform dynamic allocation.
3) release the device number, void unregister_chrdev_region (dev_t first unsigned int count );

--- File operations

The file_operations struct, which is connected to multiple device operation functions. The
The function pointer points to the specific operation in the driver, and the pointer with no corresponding action is set to NULL.
1) the first member of fops is struct module * owner, which is usually set to THIS_MODULE.
Macro defined in linux/module. h. It is used to prevent the module from being detached when its operation is still in use.
2) loff_t (* llseek) (struct file *, loff_t, int); this method is used to change the current read/write position in the file.
Returns the new location.
3) ssize_t (* read) (struct file *, char _ user *, size_t, loff_t *); this function is used to extract files from the device
The number of bytes read after successful reading.
4) ssize_t (* write) (struct file *, const char _ user *, size_t, loff_t *); this function is used
The number of bytes written if data is successfully written.
5) int (* ioctl) (struct inode *, struct file *, unsigned int, unsigned long); ioctl system call provides
Method of issuing a device-specific command.
6) int (* open) (struct inode *, struct file *); the first operation on the device file to open the device file.
7) int (* release) (struct inode *, struct file *); release the file structure function pointer.
Generally, this struct is initialized as follows:
Struct file_operations fops = {
. Owner = THIS_MODULE,. llseek = xxx_llseek,. read = xxx_read,. write = xxx_write,
. Ioctl = xxx_ioctl,. open = xxx_open,. release = xxx_release };
PS: not all of the above file operation function pointers are described, but several common operations are introduced.

--- File structure

Struct file is defined in linux/fs. h and is the second most important data structure in the device driver.
The FILE pointer in the user space program does not matter. The former is in the kernel space, and the latter is in the user control.
The file structure represents an open file. (It is not specific to the device driver; each open file in the system
There is an associated struct file in the kernel space ). It is created when the kernel is open and can be passed to the file
Operation function. after the file is closed, the kernel releases the data structure.

1) mode_t f_mode. Determine the file read/write mode
2) loff_t f_ops. Current read/write location
3) unsigned int f_flags. File flag, O_RDONLY, O_NONBLOCK,
4) struct file_operations * f_op. Associated file operations
5) void * private_data. Open system call sets the pointer NULL to point to the allocated data.
6) struct dentry * f_dentry. The dentry structure of the directory entry associated with the file.

--- Inode structure

The inode structure is used internally by the kernel to represent files. It does not have the same structure as the file that represents the open file descriptor.
. The inode structure contains a large amount of information about files. As a general rule, this structure has only two
Driver code.
Dev_t I _rdev. For a node that represents a device file, this member contains the actual device number.
Struct cdev * I _cdev. The internal structure of the kernel, which represents a character device.

--- Character device registration

Before the kernel calls your device operations, you write the assignment and register one or more struct cdev.
Struct cdev * my_cdev = cdev_alloc (); my_cdev-> ops = & my_fops;
Or define it as static.
Initialize the defined cdev variable. you can use a special function or the above method.
Cdev_init (my_cdev, & my_fops); in fact, the above two lines of code are actually doing the work of this function.
Finally, tell the kernel the cdev.
Cdev_add (struct cdev * dev, dev_t num, unsigned int count );

/* The summary above describes the structure data related to the device file and how to register and destroy the device file.
The functions are basically described. The main thing is to design specific operation functions to implement specific

Logical operation */

The following code is excerpted from the Android deep exploration HAL and driver development-Li Ning LED driver

#include 
 
  #include 
  
   #include #include 
   
    #include 
    
     #include 
     
      #include 
      
       #deifne DEVICE_NAME "s3c6410_leds"#define DEVICE_COUNT 1#define S3C6410_LEDS_MAJOR 0#define S3C6410_LEDS_MINOR 234#define PARAM_SIZE 3static int major = S3C6410_LEDS_MAJOR;static int minor = S3C6410_LEDS_MINOR;static dev_t dev_number;static int leds_state = 1;static char *params[] = {"string1","string2","string3"};static iint param_size = PARAM_SIZE;static struct class *leds_class = NULL;static int s3c6410_leds_ioctl (struct file *file, unsigned int cmd, unsigned long arg){ switch (cmd) { unsigned tmp;case 0:case 1:if (arg > 4)return -EINVAL;tmp = ioread32 (S3C64XX_GPMDAT);if (cmd == 1)tmp &= (~(1 << arg));elsetmp |= (1 << arg);iowrite32 (tmp, S3C64XX_GPMDAT);return 0;default : return -EINVAL; }} static ssize_t s3c6410_leds_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos){ unsigned tmp = count; unsigned long i = 0; memset(mem, 0, 4); if (count > 4)tmp = 4; if (copy_from_user (mem, buf, tmp) )return -EFAULT; else{ for( i=0; i<4; i++){ tmp = ioread32(S3C64XX_GPMDAT); if (mem[i] == '1') tmp &= (~(1 << i)); else tmp |= (1 << i); iowrite32(tmp, S3C64XX_GPMDAT);}return count; }}static struct file_operations dev_fops = {.owner = THIS_MODULE, .unlocked_ioctl = s3c6410_leds_ioctl, .write = s3c6410_leds_write};static struct cdev leds_cdev;static int leds_create_device(void){ int ret = 0; int err = 0; cdev_init (&leds_cdev, &dev_fops); leds_cdev.owner = THIS_MODULE; if (major > 0) { dev_number = MKDEV(major,minor);err = register_chrdev_region(dev_number, DEVICE_COUNT, DEVICE_NAME);if (err < 0){ printk(KERN_WANRING "register_chrdev_region error\n"); return err} } else{ err = alloc_chrdev_region(&leds_cdev.dev, 10, DEVICE_COUNT, DEVICE_NAME);if(err < 0){printk (KERN_WARNING "alloc_chrdev_region error\n");return err;}major = MAJOR(leds_cdev.dev);major = MINOR(leds_cdev.dev);dev_number = leds_cdev.dev; } ret = cdev_add(&leds_cdev,dev_number, DEVICE_COUNT); leds_class = class_create (THIS_MODULE, DEVICE_NAME); device_create (leds_class, NULL, dev_number, NULL, DEVICE_NAME); return ret;}static void leds_init_gpm(int leds_default){ int tmp = 0; tmp = ioread32(S3C64XX_GPMCON); tmp &= (~0xffff); tmp |= 0x1111; iowrite32(tmp,S3C64XX_GPMCON); tmp = ioread32(S3C64XX_GPMPUD); tmp &= (~0XFF); tmp |= 0xaa; iowrite32(tmp,S3C64XX_GPMPUD); tmp = ioread32(S3C64XX_GPMDAT); tmp &= (~0xf); tmp |= leds_default; iowrite32(tmp, S3C64XX_GPMDAT); }static leds_init( void){ int ret; ret = leds_create_device(); leds_init_gpm (~leds_state); printk(DEVICE_NAME"\tinitialized\n"); return ret;}static void leds_destroy_device(void){device_destroy(leds_class, dev_number);if(leds_class)class_destroy(leds_class);unregister_chrdev_region(dev_number, DEVICE_NAME);}static void leds_exit(void){ leds_destroy_device(); printk(DEVICE_NAME"\texit\n");}module_init(leds_init);module_exit(leds_exit);module_param(leds_state, int, S_IRUGO|S_IWUSR);module_param_array(params, charp, ?m_size, S_IRUGO|S_IWUSR);MODULE_LICENSE("GPL");MODULE_AUTHOR("lining");
      
     
    
   
  
 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.