Linux内核混杂设备驱动编程框架
混杂设备驱动定义:
- 混杂设备官方定义:非标准的字符设备。
- 混杂设备驱动本质还是字符设备驱动,只是混杂设备驱动的主设备号由Linux内核已经定义好,(为10)。各个混杂设备通过次设备号来区分。所以内核支持的混杂设备驱动管理的硬件个数为:2^20。
- 缺点:所以混杂设备本身不能再次通过次设备号来区分。
Linux内核描述混杂设备驱动的数据结构:
struct miscdevice{
int minor;
const char *name;
const struct file_operations *ops;
...
}
- minor:混杂设备的次设备号,主设备号为10。
- name:混杂设备文件名,内核来调用4个函数帮你创建设备文件。但是:三个保证还需自己完成。
- fops:给混杂设备驱动添加的硬件操作接口。
配套的函数:
//向内核注册一个混杂设备
misc_register(注册的混杂设备对象地址)
//从内核卸载混杂设备
misc_deregister(混杂设备对象地址)
案例1:利用混杂设备驱动框架实现LED驱动,操作接口采用ioctl实现开关某个灯。
案例2:利用混杂设备驱动,编写按键驱动,实现读取按键操作的状态:按下还是松开。
- mykey_test.c
int main()
{
int fd;
int state;
fd = open("/dev/mtbtn", O_RDWR);
if(fd < 0){
perror("open button device failed . \n");
return -1;
}
//采用轮询方式获取状态
while(1){
read(fd, &state, sizeof(state));
printf("按键状态——> %s\n", state ? "松开":"按下");
}
close(fd);
return 0;
}
- mykey_drv.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/gpio.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#inlcude <mach/platform.h>
//声明硬件数据结构
struct btn_resource{
char *name;
int 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)
{
//分配内核缓冲区
int kstate;
//获取按键状态保存到内核缓冲区,指定使用第一个设备设备(btn_info[0])
kstate = gpio_get_value(btn_info[0]);
//拷贝给用户
copy_to_user(buf, &kstate, count);
return count;
}
//定义初始化硬件操作接口对象
static struct file_operations btn_fops = {
.read = btn_read
};
//定义初始化混杂设备对象
static struct miscdevice btn_misc = {
.minor = MISC_MYNAMIC_MINOR,
.name = "mybtn",
.fops = &btn_fops
};
static int btn_init(void)
{
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);
}
misc_register(&btn_misc);
return 0;
}
static void btn_exit(void)
{
int i;
{
gpio_free(btn_info[i].gpio);
}
}
module_init(btn_init);
module_exit(btn_exit);
MODULE_LICENSE("GPL");