本系列导航
(一)初识Linux驱动
(二)Linux设备驱动的模块化编程
(三)写一个完整的Linux驱动程序访问硬件并写应用程序进行测试
(四)Linux设备驱动之多个同类设备共用一套驱动
(五)Linux设备驱动模型介绍
(六)Linux驱动子系统-I2C子系统
(七)Linux驱动子系统-SPI子系统
(八)Linux驱动子系统-PWM子系统
(九)Linux驱动子系统-Light子系统
(十)Linux驱动子系统-背光子系统
(十一)Linux驱动-触摸屏驱动
1. 应用场景
比如我们的设备上有很多一样的usb接口,这些usb接口都需要有驱动才能工作,那么是每个usb都一套单独的驱动程序么?显然不是的,这些usb接口属于同一类设备,用户对他们的操作方法完全一致,只不过不是同一个设备,所以他们可以复用同一套驱动代码,在代码中去判断用户要操作哪个设备,然后去open/read/write这个设备。
2. 如何区分不同的设备
前面说过,每个设备都有一个唯一的标识符–设备号,那么对于同一类设备,它们的主设备号是一样的,次设备号是不一样的,用来区分它们,当用户想要操作哪个具体的设备,就会打开这个设备对应的设备文件(inode结构体),并自动在内核中创建对应的file结构体,这个file结构体中就保存了用户操作的所有信息,最终会传给我们的内核驱动,驱动再根据这个file结构体和inode结构体来判断用户具体要操作的哪个设备,然后去read/write这个具体的设备。
案例:
hanp@hanp:/dev/usb$ ls -l
crw------- 1 root root 180, 0 3月 11 17:29 hiddev0
crw------- 1 root root 180, 1 3月 11 17:29 hiddev1
我的主机下面的两个usb设备,他们共用了一套usb驱动,但是他们的设备号是不一样的(180,0)和(180,1),主设备号都是180表示都属于同一类设备(usb设备),次设备号分别是0和1,表示这是两个不同的设备。
3. 代码实现
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#define NUM_OF_DEVICES 2
int major = 255;
/* 两个设备,所以有两套结构体 */
/* 设备0对应的设备结构体是hello_dev[0], 设备1对应的设备结构体是hello_dev[1] */
struct hello_device {
dev_t devno;
struct cdev cdev;
char data[128];
char name[16];
}hello_dev[NUM_OF_DEVICES];
struct class * hello_class;
const char DEVNAME[] = "hello_device";
int hello_open(struct inode * ip, struct file * fp)
{
printk("%s : %d\n", __func__, __LINE__);
/* 获取用户打开的设备对应的设备结构体 hello_dev[0] 或者 hello_dev[1] */
struct hello_device * dev = container_of(ip->i_cdev, struct hello_device, cdev);
/* open的时候,通过container_of能够获取到用户要打开的那个设备的设备结构体,所有需要把这个结构体通过file指针的
* private_data参数传递给read/write */
fp-><