zoukankan      html  css  js  c++  java
  • 六、【ioctl】应用程序和驱动程序中的ioctl

    1、接口函数介绍

    很多设备除了读和写之外,还需要驱动提供其它操作能力,例如:获取LCD尺寸、修改串口波特率

    (应用层)函数原型:

    #include <sys/ioctl.h>
     int ioctl(int fd, unsigned long request, ...);
    

    (driver)提供接口函数

    struct file_operations {
    	.....
    	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
    	long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
    	......
    	}
    	
    

    2.6.36之后的内核版本只支持unlocked_ioctl,之前的一些过渡版本两者都支持,更早的版本只支持compat_ioctl

    long (*unlocked_ioctl) (struct file * filp, unsigned int cmd , unsigned long arg); 

    参数:

    • filp:指向打开的文件信息结构体。
    • cmd:驱动提供给应用程序的命令字。
    • arg:应用程序与驱动之间传递的参数。

    2、命令字的组成

    (1)bit解释

    • bit[31:30]:参数传递的方向。应用--->驱动、驱动--->应用、应用<--->驱动、不需要参数.
    • bit[29:16]:参数的大小,用数据类型表示大小char int struct xxx。
    • bit[15:8]:魔数/幻数,用于区分不同驱动的命令字,一般设置为某个字符的ASCII码。
    • bit[7:0]:命令字的序号。

    (2)内核中提供的生成命令字的宏

    #define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
    #define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
    #define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
    #define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
    _IO---生成没有参数传递的命令字。 _IOR--生成应用从驱动获取参数的命令字。 _IOW--生成应用给驱动传递参数的命令字。 _IOWR--生成双向传参的命令字。 

    参数:

    • type:魔数/幻数,用于区分不同驱动的命令字,一般设置为某个字符的ASCII码
    • nr:命令字的序号
    • size:参数的大小,用数据类型表示大小char int struct xxx

    例如: 

    #define BEEP_ON _IO('B',0)
    #define BEEP_OFF _IO('B',1)
    
    #define LED_ON _IOW('L',0,unsigned int)
    #define LED_OFF _IOW('L',1,unsigned int)
    

    3、例程(实现beep)

    beep_drv.c

    #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/ioctl.h>
    static struct cdev beep;
    static dev_t dev;
    static struct class *beep_cls=NULL;
    static struct device * beep_dev=NULL;
    static struct resource *beep_res  = NULL;
    static void __iomem *GPIOCBASE = NULL;
    static void __iomem *GPIOCOUT = NULL;
    static void __iomem *GPIOCOUTENB= NULL;
    static void __iomem *GPIOCALTFN0 = NULL;
    static void __iomem *GPIOCALTFN1 = NULL;
    
    #define BEEP_ON  _IO('B',0)
    #define BEEP_OFF   _IO('B',1)
    
    static  int beep_open(struct inode* inode,struct file *filp)
    {
        printk(KERN_INFO"beep_open\n");
        return 0;
    }
    
    static  int beep_close(struct inode* inode,struct file *filp)
    {
        printk(KERN_INFO"beep_close\n");
        return 0;
    }
    
    static ssize_t beep_write(struct file *filp, const char __user *user, size_t  size, loff_t *oft)
    {
    
        printk(KERN_INFO"beep_write\n");
         return size;
    }
    
    static long beep_ioctl (struct file *filp, unsigned int cmd, unsigned long  arg)
    {
          switch(cmd)
          {
          		case BEEP_ON:
    				writel(readl(GPIOCOUT)|((0x01<<14)),GPIOCOUT);
    				break;
    		case BEEP_OFF:
    				writel(readl(GPIOCOUT)&(~(0x01<<14)),GPIOCOUT);
    		default:
    			return -ENOIOCTLCMD;			
          }
    	 return 0; 
    }
    struct file_operations fops=
    {
    	.open = beep_open,
    	.release = beep_close,
    	.write = beep_write,
    	.unlocked_ioctl = beep_ioctl,
    };
    
    static int __init  beep_init(void)
    {
          int ret;
           printk(KERN_INFO"beep_init\n");
    	ret = alloc_chrdev_region(&dev, 0, 1,"beep_chrdev");
    	if(ret!=0)
    	{
    		printk(KERN_INFO"register char dev failed\n");
    		goto alloc_chrdev_region_err;
    	}
    	beep.owner = THIS_MODULE;
    	cdev_init(&beep,&fops);
    	ret=cdev_add(&beep, dev, 1);
    	if(ret!=0)
    	{
    		printk(KERN_INFO"add char device failed\n");
    		goto cdev_add_err;
    	}
    	beep_cls = class_create(THIS_MODULE, "beep_class");
    	if(IS_ERR(beep_cls))
    	{
    		printk(KERN_INFO"class create failed\n");
    		ret = -EBUSY;
    		goto class_create_err;
    	}
    	beep_dev= device_create(beep_cls, NULL,dev, NULL, "beep_dev");
    	if(IS_ERR(beep_dev))
    	{
    		printk(KERN_INFO"device create failed\n");
    		ret = -ENOMEM;
    		goto device_create_err;
    	}
    	beep_res = request_mem_region(0xc001c000,0x68,"beep_iomem");
    	if(beep_res==NULL)
    	{
    		printk(KERN_INFO"request memory region failed\n");
    		ret = -EBUSY;
    		goto request_mem_region_err;
    	}
    	GPIOCBASE = ioremap(0xc001c000,0x68);
    	if(GPIOCBASE==NULL)
    	{
    		printk(KERN_INFO"ioremap failed");
    		ret = -EBUSY;
    		goto ioremap_err;
    	}
    	GPIOCOUT = GPIOCBASE+0x00;
    	GPIOCOUTENB = GPIOCBASE+0x04;
    	GPIOCALTFN0 = GPIOCBASE+0x20;
    	GPIOCALTFN1 = GPIOCBASE+0x24;
    	//beep
    	writel(readl(GPIOCOUTENB)|(0x01<<14),GPIOCOUTENB);
    	writel(readl(GPIOCALTFN0) &(~(0x03<<28)),GPIOCALTFN0);
    	writel(readl(GPIOCALTFN0) |(1<<28),GPIOCALTFN0);
    	writel(readl(GPIOCOUT)&(~(0x01<<14)),GPIOCOUT);
    
    
    	return 0;
    ioremap_err:
    	   release_mem_region(0xc001c000,0x68);
    request_mem_region_err:
    	device_destroy(beep_cls , dev);
    device_create_err:
    	class_destroy(beep_cls);
    class_create_err:
    	cdev_del(&beep);
    cdev_add_err:
    	unregister_chrdev_region(dev,1);
    alloc_chrdev_region_err:
    		return 0;
    }
    
    static void __exit beep_exit(void)
    {
        printk(KERN_INFO"xxxx__exit\n");
           //取锟斤拷映锟斤拷
        iounmap(GPIOCBASE);
        //锟酵凤拷IO锟节达拷
        release_mem_region(0xc001c000,0x68);
        device_destroy(beep_cls , dev);
        class_destroy(beep_cls);
        cdev_del(&beep); 
        unregister_chrdev_region(dev, 1);
    }
    module_init(beep_init);
    module_exit(beep_exit);
    MODULE_AUTHOR("yqf");
    MODULE_DESCRIPTION("beep driver program");
    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 BEEP_ON _IO('B',0)
    #define BEEP_OFF _IO('B',1)
    
    int main()
    {
        int fd;
        char buff[2]={0};
        fd = open("/dev/beep_dev",O_RDWR);
        if(fd<0)
        {
            perror("open bepp dev error!");        
        }
        while(1)
        {
            ioctl(fd,BEEP_ON);
            sleep(1);
            ioctl(fd,BEEP_OFF);
             sleep(1);
        }
        
         close(fd);
    }
    

      

      

      

     

        

      

  • 相关阅读:
    SpringMVC 下载本地文件
    Spring MVC 自定义转换器
    Struts,Hibernate,Spring经典面试题
    SpingMVC 执行的流程
    SpringMVC 应用配置
    SpringMVC特点
    Struts2学习
    mysql免安装配置
    mysql免安装版设置密码
    《金色梦乡》金句摘抄(六)
  • 原文地址:https://www.cnblogs.com/yuanqiangfei/p/15676593.html
Copyright © 2011-2022 走看看