新路程------ 一个字符驱动(ioctl)

本文介绍了一个关于ioctl函数参数传递的问题实例,详细分析了在Linux设备驱动开发中如何正确使用ioctl进行用户空间与内核空间的数据交换,并给出了具体的代码实现。

注意事项,ioctl的函数参数,之前我用了static long newchar_ioctl(struct inode *inode, struct file *filep, 
unsigned long cmd, unsigned long arg),发生了可以调用到驱动的ioctl但是就是无法把ioctl的参数传到驱动中,要小心

还要就是对应的gpio没找对,因为没有ic的spec,这点也要注意才对

h文件如下:

#include <linux/fb.h>
#include <linux/ioctl.h>
#define NEWCHAR_IOC_MAGIC 'a'

struct matt{
  int gpio2_value;
  int gpio4_value;
  int gpio6_value;
};

#define GPIO_test  _IO(NEWCHAR_IOC_MAGIC, 0x01) 
#define GPIO_SET  _IOW(NEWCHAR_IOC_MAGIC, 0x02, struct matt)
#define GPIO_GET  _IOR(NEWCHAR_IOC_MAGIC, 0x03, unsigned long)
#define GPIO_m  _IOW(NEWCHAR_IOC_MAGIC, 0x04, int)

驱动c文件如下

#include <linux/types.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/nodemask.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
#include <linux/smsc911x.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/i2c.h>
#include <linux/i2c/pca953x.h>
#include <linux/ata.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/pmic_external.h>
#include <linux/pmic_status.h>
#include <linux/mxcfb.h>
#include <linux/pwm_backlight.h>
#include <linux/fec.h>
#include <linux/memblock.h>
#include <linux/gpio.h>
#include <linux/etherdevice.h>
#include <linux/regulator/anatop-regulator.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
#include <linux/mfd/max17135.h>
#include <sound/wm8962.h>
#include <sound/pcm.h>
#include <linux/power/sabresd_battery.h>


#include <mach/common.h>
#include <mach/hardware.h>
#include <mach/mxc_dvfs.h>
#include <mach/memory.h>
#include <mach/iomux-mx6sl.h>
#include <mach/imx-uart.h>
#include <mach/viv_gpu.h>
#include <mach/imx_rfkill.h>


#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>


#include "74vhc541.h"
#include <linux/types.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/io.h>
#include <linux/ipu.h>
#include <linux/mxcfb.h>
#include <linux/regulator/consumer.h>
#include <linux/spinlock.h>
#include <linux/fsl_devices.h>
#include <mach/hardware.h>
#include <mach/clock.h>




#define EIM_D182
#define EIM_D174
#define EIM_D218




#define matt_gpio2 IMX_GPIO_NR(1, 2)


#define DEVICE_NAME   "matt_test"
static char demo_buffer[20];  






static int MAJOR_DEV_NUM =1;
static int newchar_open(struct inode *inode, struct file *filep)
{
printk( "======== matt_open ");
gpio_free(EIM_D18);
gpio_free(EIM_D17);
gpio_free(EIM_D21);
/*gpio_request(EIM_D18, "EIM_D18");
gpio_direction_output(EIM_D18, 1);
__gpio_set_value(EIM_D18, 0);

gpio_request(EIM_D17, "EIM_D17");
gpio_direction_output(EIM_D17, 1);
__gpio_set_value(EIM_D17, 0);

gpio_request(EIM_D21, "EIM_D21");
gpio_direction_output(EIM_D21, 1);
__gpio_set_value(EIM_D21, 0);*/


     return 0;
}




static int newchar_release(struct inode *inode, struct file *filep)
{  





/*gpio_request(EIM_D17, "EIM_D17");
gpio_direction_output(EIM_D17, 1);
__gpio_set_value(EIM_D17, 0);

gpio_request(EIM_D21, "EIM_D21");
gpio_direction_output(EIM_D21, 1);
__gpio_set_value(EIM_D21, 0);*/


printk( "======== matt_release \n");


    return 0;
}


static ssize_t newchar_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)  
{  
    printk( "======== matt_read \n");
gpio_direction_output(EIM_D18, 0);
__gpio_set_value(EIM_D18, 0);
return 0;
}
ssize_t newchar_write (struct file *filp, char __user *buf, size_t count, loff_t *ppos) {


printk( "======== matt_write\n ");


    ssize_t retval = -ENOMEM;  
    loff_t pos = *ppos;  
    int i;
int dat=0;


    if (pos > 20)  
        goto out;  
    if (count > (256 - pos))   
        count = 256 - pos;    
    pos += count;  
    if (copy_from_user(demo_buffer+*ppos, buf, count)) {  
        retval = -EFAULT;  
        goto out;     
    }  


/* if(!gpio_is_valid(EIM_D18))
{
printk( "======== matt gpio invalid \n");
}
if(!gpio_request(EIM_D18, "EIM_D18"))
{
printk( "======== matt gpio_request success\n");
}*/

printk( "======== matt_demo_buffer[i]=%c\n ",demo_buffer[0]);

dat=gpio_get_value(matt_gpio2);
printk("matt-gpio_get_value1================%d\n",dat);
if(demo_buffer[0]=='a')
{
__gpio_set_value(matt_gpio2, 0);
dat=gpio_get_value(matt_gpio2);
printk("matt-gpio_get_value=================%d\n",dat);


}else{
__gpio_set_value(matt_gpio2, 1);
dat=gpio_get_value(matt_gpio2);
printk("matt-gpio_get_value=================%d\n",dat);
}

     /* for( i=0;i<7;i++)
      {
      __gpio_set_value(EIM_D18, 0);
printk( "======== matt_demo_buffer[i]=%c\n ",demo_buffer[i]);
      }*/
    *ppos = pos;  
    retval = count;  
out:  
    return retval; 
return 0;



}


static ssize_t gpio_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
printk( "======== matt gpio_show ");
}

static ssize_t gpio_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
printk( "======== matt gpio_store ");


return size;
}

//static DEVICE_ATTR(matt_gpio, 0664, gpio_show,gpio_store);

static long newchar_ioctl(struct file *filep, 
unsigned long cmd, unsigned long arg)
{
 long ret= 0;
int m=0;
printk("matt ioctl start+1\n");
ret = EINVAL;
struct matt *nc;
 nc=kzalloc(sizeof(struct matt), GFP_KERNEL);

printk("matt cmd=%ld\n",GPIO_test);
printk("matt cmd1=%ld\n",GPIO_SET);


printk("matt recive cmd=%ld\n",cmd);

switch(cmd)
{   
case GPIO_test:
{
printk("matt GPIO_test\n");    
}
break;

case GPIO_SET:
{
printk("matt GPIO_SET\n");

  if(copy_from_user(nc, (const char*)arg, sizeof(struct matt)) != 0)
  {
  printk("matt copy failure\n");
     return -EFAULT;


  }
  printk("matt gpio1=%d\n",nc->gpio2_value);
    printk("matt gpio2=%d\n",nc->gpio4_value);
 printk("matt gpio3=%d\n",nc->gpio6_value);
}
break;
case GPIO_GET:
{
printk("matt ioctl get\n");
}
break;
}
return ret;
}
struct file_operations newchar_fops = 
{
.owner = THIS_MODULE,
.unlocked_ioctl = newchar_ioctl,
.open = newchar_open,
.write =newchar_write,
.release = newchar_release,
.read = newchar_read,
};
static dev_t first; // Global variable for the first device number
static struct cdev c_dev; // Global variable for the character device structure
static struct class *cl; // Global variable for the device class


static int __init first_drv_init(void)
{
printk("======== cdevdemo_init "); 
 
     int ret;
/*
* Register btusb as a character device driver with linux OS and return
* ERROR on failure
*/
if ((cl = class_create(THIS_MODULE, DEVICE_NAME)) == NULL)
{
printk("matt erro1"); 
return 1;
}
if (alloc_chrdev_region(&first, 0, 1, DEVICE_NAME) < 0)
{
printk("matt erro2");
class_destroy(cl);
return 1;
}
if (device_create(cl, NULL, first, NULL, DEVICE_NAME) == NULL)
{
printk("matt erro3");
unregister_chrdev_region(first, 1);
class_destroy(cl);
return 1;
}
cdev_init(&c_dev, &newchar_fops);
if (cdev_add(&c_dev, first, 1) == -1)
{
printk("matt erro4");
device_destroy(cl, first);
unregister_chrdev_region(first, 1);
class_destroy(cl);
return 1;
}

//ret = device_create_file(&c_dev, &dev_attr_matt_gpio);


//matt
 if(!gpio_direction_output(matt_gpio2, 1))
{
printk( "======== matt gpio_direction_output success\n");


}
printk( "======== matt finish");  
return 0;  

}
void first_drv_exit(void)  
{  
    printk( "End cdevdemo");   
     device_destroy(cl, first);
    cdev_del(&c_dev);
    unregister_chrdev_region(first, 1);
    class_destroy(cl);  
}  


MODULE_LICENSE("Dual BSD/GPL");  
module_param(MAJOR_DEV_NUM, int, S_IRUGO);  
module_init(first_drv_init);  
module_exit(first_drv_exit);

测试文件如下


#include <linux/fb.h>
#include <stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include <linux/ioctl.h>
#include "74vhc541.h"
#define MXCFB_SET_GBL_ALPHA     _IOW('F', 0x21, struct mxcfb_gbl_alpha)
#define MXCFB_CSC_UP _IOW('F', 0x4D, int)
struct mxcfb_gbl_alpha {
int enable;
int alpha;
};

int main()
{
   
    int fd = 0;
    printf("start ioctl \n");
    unsigned long arg = 0;
    int x=25;
    //char* buffer=NULL;
   // buffer=(char*)malloc(100*sizeof(char));
  struct matt lisa={
    .gpio2_value=1,
    .gpio4_value=0,
    .gpio6_value=1,
};


struct mxcfb_gbl_alpha  kk={
.enable=5,
.alpha=5,
};
     printf("gpio2_value=%d\n",lisa.gpio2_value);
    fd = open("/dev/matt_test",O_RDWR);
    if (fd < 0)
    {
        printf("matt-Open Dev Mem0 Error!\n");
        return -1;
    }
   sleep(5);
    // x=read(fd,buffer,30);
   // x = write(fd, "bsdfghj", 7);  
    printf("matt-open success \n");
    printf("matt-GPIO_test=%d \n",GPIO_test);

  /* if (ioctl(fd, MXCFB_SET_GBL_ALPHA,&kk) < 0)
        {
            printf("matt fail\n");
            return -1;
    }
  sleep(5);*/

    if (ioctl(fd, GPIO_SET,&lisa) < 0)
        {
            printf("Call cmd MEMDEV_IOCSETDATA fail\n");
            return -1;
    }   
    close(fd);
    return 0;    
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值