七、【misc】杂项驱动模型

一、杂项设备驱动设计步骤

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;
}

  

  

posted @ 2021-12-12 16:31  轻轻的吻  阅读(191)  评论(0)    收藏  举报