一、杂项设备驱动设计步骤
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; }