2.linux内核混杂设备驱动
2.1.混杂设备定义
从软件实现角度去看,混杂设备本质还是字符设备
只是它的主设备号由内核已经定义好为10
各个混杂设备驱动通过次设备号来区分
2.2.linux内核描述混杂设备的结构体
struct miscdevice {
const char *name;
int minor;
const struct file_operations *fops;
...
};
功能:描述混杂设备属性
name:混杂设备文件名,并且由linux自动帮你创建,无需调用四个函数
minor:给混杂设备指定的次设备号,一般指定宏:MISC_DYNAMIC_MINOR
表示让linux内核帮你分配一个次设备号
fops:混杂设备的硬件操作接口
配套函数:
misc_register(&混杂设备对象)
功能:向内核注册一个混杂设备对象
misc_deregister(&混杂设备对象);
功能:从内核中卸载混杂设备对象
代码演示:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#include <mach/platform.h>
//声明描述按键硬件信息的结构体
struct btn_resource {
char *name; //按键的名称
int gpio; //按键的GPIO编号
};
//定义初始化按键的硬件信息对象
static struct btn_resource btn_info[] = {
{
.name = "KEY_UP",
.gpio = PAD_GPIO_A + 28
},
{
.name = "KEY_DOWN",
.gpio = PAD_GPIO_B + 9
}
};
static ssize_t btn_read(struct file *file,
char __user *buf,
size_t count,
loff_t *ppos) {
//1.分配内核缓冲区
int kstate;
//2.获取按键的状态拷贝到内核缓冲区
kstate = gpio_get_value(btn_info[0].gpio);
//结果:kstate = 1/0
//3.拷贝内核缓冲区到用户缓冲区
copy_to_user(buf, &kstate, count);
return count;
}
//定义初始化硬件操作接口对象
static struct file_operations btn_fops = {
.read = btn_read //读接口
};
//定义初始化混杂设备对象
static struct miscdevice btn_misc = {
.name = "mybtn", //自动创建设备文件/dev/mybtn
.minor = MISC_DYNAMIC_MINOR, //动态分配此设备号,主设备号10
.fops = &btn_fops //关联操作接口
};
static int btn_init(void) {
//1.申请GPIO资源,配置输入
int i;
for(i = 0; i < ARRAY_SIZE(btn_info); i++) {
gpio_request(btn_info[i].gpio, btn_info[i].name);
gpio_direction_input(btn_info[i].gpio);
}
//2.注册混杂设备驱动对象
misc_register(&btn_misc);
return 0;
}
static void btn_exit(void) {
//1.释放GPIO资源
int i;
for(i = 0; i < ARRAY_SIZE(btn_info); i++)
gpio_free(btn_info[i].gpio);
//2.卸载混杂设备驱动
misc_deregister(&btn_misc);
}
module_init(btn_init);
module_exit(btn_exit);
MODULE_LICENSE("GPL");