Linux driver

Linux driver

1. Classification of linux drivers

  • Character driven device: the transmission process of IO is based on characters without buffer. For example, I2C and SPI are character devices

  • Block device driver: the transmission process of IO is in blocks. Root storage is related to block devices, such as tf cards

  • Network device driver: accessed by socket.

Among them, it is most important to understand and master the concept of character device driver. Most of the problems encountered in practical work are character devices.

The drive is divided into four parts:

Header file

Inlet and outlet of drive module

Declaration information

Function realization

/*******step1 Include header file*************/
#include <linux/init. h> / * header file containing macro definition*/
#include <linux/module. h> / * contains the header file that initializes the load module*/
 
    
/*********step4 Function realization**************/
static int __init helloworld_init(void)
{
    printk("hello world\n");
    return 0;
}

static void __exit helloworld_exit(void)
{
    printk("End of the world!\n");
}
    
/*******step2 Inlet and outlet of drive module*********/   
module_init(helloworld_init);
module_exit(helloworld_exit);

/*******step3 Declaration information***********/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("xxxx");



2. Miscellaneous equipment drive

You can view it by entering the cat /proc/misc command. The primary equipment number of miscellaneous equipment is the same, but the secondary equipment number is different. The same main device number can save kernel resources. Equipment number is a way for computer to identify equipment. If the main device number is the same, it can be regarded as the same type of device, which can be viewed through the command cat /proc/devices. The master device number of all misc device drivers is 10, which is not allowed
The same device uses a different slave device number. If the main device number is the same, the resources of the kernel can be saved. More than 200 drivers using miscdevice framework can be found in the kernel.

There is a general idea and method for registering miscellaneous drive equipment, which is summarized into three steps:

  1. Fill miscdevice structure
  2. Fill file_operations structure
  3. Register miscellaneous equipment and generate equipment nodes

Write a simple miscellaneous device driver

Add header file

/*Register miscellaneous device header file*/
#include <linux/miscdevice.h>
/*Register the file structure of the device node*/
#include <linux/fs.h>

Fill miscdevice structure

struct miscdevice misc_dev ={
	.minor = MISC_DYNAMIC_MINOR,
	.name = "hello_misc",
	.fops = &misc_fops,
};

Fill file_operations structure

struct file_operations misc_fops = {
	.owner = THIS_MODULE
};

Register miscellaneous equipment and generate equipment nodes

/*The driver framework is required to drive the initialization function*/
static int __init misc_init(void)
{
	int ret;
	ret = misc_register(&misc_dev);
	if(ret < 0)
	{
		printk("misc registe is error\n");
	}
	printk("misc registe is succeed\n");
	return 0;
}
/*Driver framework is required to drive exit function*/
static void __exit misc_exit(void)
{
	misc_register(&misc_dev);
	printk("misc goodbye\n");
}

Miscellaneous driver instance

#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
 
#define DEVICE_NAME "led_test" / * the name of the device automatically created when registering the driver*/ 
#define IOCTL_GPIO_ON    1
#define IOCTL_GPIO_OFF  0
/* Used to specify the GPIO pin used by the LED */
static unsigned long gpio_table [] =
{
    S3C2410_GPB5,
    S3C2410_GPB6,
    S3C2410_GPB7,
    S3C2410_GPB8,
};
/* Used to specify the function of GPIO pin: output */
static unsigned int gpio_cfg_table [] =
{
    S3C2410_GPB5_OUTP,
    S3C2410_GPB6_OUTP,
    S3C2410_GPB7_OUTP,
    S3C2410_GPB8_OUTP,
};
 
static int s3c2440_leds_open(struct inode *inode,struct file *filp)/*open The function implements the led lamp configuration: output*/ 
{
    int i;
    for(i=0;i<4;i++)
    {
        s3c2410_gpio_cfgpin(gpio_table[i],gpio_cfg_table[i]);
    }
    return 0;
}
 
static int tq2440_gpio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)/*It realizes the control of led lamp*/ 
{
    if (arg > 4)
    {
        return -EINVAL;
    }
    switch(cmd)
    {
        case IOCTL_GPIO_ON:
            s3c2410_gpio_setpin(gpio_table[arg], 0); // Set the output level of the specified pin to 0 
            return 0;
        case IOCTL_GPIO_OFF:
            s3c2410_gpio_setpin(gpio_table[arg], 1);// Set the output level of the specified pin to 1 
            return 0;
        default:
            return -EINVAL;
    }
}
 
/*Driver framework required, file_operations contains the operations that can be performed on the device*/
static struct file_operations dev_fops = {
       .owner   =   THIS_MODULE,
       .ioctl   =   tq2440_gpio_ioctl,
       .open    =   s3c2440_leds_open,
};
 
/*The driver framework is required, and the driver information is packaged for the registration of the driver*/
static struct miscdevice misc = {   
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &dev_fops,
};
 
/*The driver framework is required to drive the initialization function*/
static int __init dev_init(void)
{
    int ret;
    ret = misc_register(&misc);
    printk (DEVICE_NAME" initialized\n");
    return ret;
}
 
/*Driver framework is required to drive exit function*/
static void __exit dev_exit(void)
{
    misc_deregister(&misc);
    printk (DEVICE_NAME" is over!\n");
}
/*The driver framework must initialize the entry function of the module*/
module_init(dev_init);
/*The driver framework is required, and the module ends the entry function*/
module_exit(dev_exit);
/*Driver framework required, general public license*/
MODULE_LICENSE("GPL");

Keywords: Linux Operation & Maintenance

Added by nicolam1 on Tue, 18 Jan 2022 02:18:36 +0200