一、杂项设备驱动设计步骤
1、定义一个杂项设备结构体
struct miscdevice {
int minor; //次设备号
const char *name; //设备名和设备文件名一致
const struct file_operations *fops; //文件操作集合
struct list_head list;
struct device *parent;
struct device *this_device;
const char *nodename;
umode_t mode;
};
2、杂项设备的注册和注销
(1)注册
int misc_register(struct miscdevice * misc)
(2)注销
int misc_deregister(struct miscdevice *misc)
二、使用杂项设备模型写led流水灯驱动
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/types.h>
#include <linux/gpio.h>
#include <cfg_type.h>
#include <linux/miscdevice.h>
#define LED_ON _IOW('L',0,unsigned long)
#define LED_OFF _IOW('L',1,unsigned long)
struct led_gpio_t{
unsigned int gpio;
char gpio_name[20];
};
static struct led_gpio_t led_gpioC[]=
{
{PAD_GPIO_C+17,"D8_GPIOC17"},
{PAD_GPIO_C+7,"D9_GPIOC7"},
{PAD_GPIO_C+8,"D10_GPIOC8"},
};
static long led_ioctl(struct file *flip, unsigned int cmd, unsigned long arg)
{
if(arg>10||arg<7)
{
return -EINVAL;
}
switch(cmd)
{
case LED_ON:
gpio_set_value(led_gpioC[arg-8].gpio,0);
break;
case LED_OFF:
gpio_set_value(led_gpioC[arg-8].gpio,1);
break;
default:
return -ENOIOCTLCMD;
}
return 0;
}
struct file_operations led_misc_fops=
{
.unlocked_ioctl = led_ioctl,
};
static struct miscdevice led_misc={
.minor = MISC_DYNAMIC_MINOR, //表示由系统分配次设备号
.name = "led_misc",
.fops = &led_misc_fops,
};
static int __init led_init(void)
{
int ret,i;
printk(KERN_INFO"led_init\n");
ret = misc_register(&led_misc);
if(ret < 0)
{
printk(KERN_INFO"led misc register fail.\n");
goto misc_register_err;
}
for(i=0;i<3;i++)
{
ret = gpio_request(led_gpioC[i].gpio, led_gpioC[i].gpio_name);
if(ret < 0)
{
printk(KERN_INFO"gpio_request fail.\n");
goto gpio_request_err;
}
}
for(i=0;i<3;i++)
{
gpio_direction_output(led_gpioC[i].gpio, 1);
}
return 0;
gpio_request_err:
while(i--)
{
gpio_free(led_gpioC[i].gpio);
}
misc_register_err:
return 0;
}
static void __exit led_exit(void)
{
int i;
printk(KERN_INFO"xxxx__exit\n");
for(i=0;i<3;i++)
{
gpio_free(led_gpioC[i].gpio);
}
misc_deregister(&led_misc);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
main.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ioctl.h>
#define LED_ON _IOW('L',0,unsigned long)
#define LED_OFF _IOW('L',1,unsigned long)
int main()
{
int fd,ret;
char buff[2]={0};
fd = open("/dev/led_misc",O_RDWR);
if(fd<0)
{
perror("open led_misc error!");
}
while(1)
{
ioctl(fd,LED_ON,8);
sleep(1);
ioctl(fd,LED_OFF,8);
ioctl(fd,LED_ON,9);
sleep(1);
ioctl(fd,LED_OFF,9);
ioctl(fd,LED_ON,10);
sleep(1);
ioctl(fd,LED_OFF,10);
}
close(fd);
return 0;
}