Chinaunix首页 | 论坛 | 博客
  • 博客访问: 541943
  • 博文数量: 83
  • 博客积分: 4136
  • 博客等级: 中校
  • 技术积分: 886
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-19 21:14
文章分类

全部博文(83)

文章存档

2013年(1)

2011年(25)

2010年(57)

分类: LINUX

2010-12-20 08:56:41

一个IOCTL的misc混杂类型设备驱动,来点亮mini2440开发板的led

首先是驱动程序如下:

#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>

#include "rainleddrv.h"
#define DEVICE_NAME "ledmiscdev"
//struct miscdevice miscdev;

char *led_mem = NULL;

static int misc_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
    int err = 0;
    unsigned int val = 0;
    int ret = 0;

    //以下命令都是惯例,记住即可
    if (_IOC_TYPE(cmd) != LED_IOC_MAGIC)
        return -EINVAL; //检测是不是同一个命令
       if (_IOC_NR(cmd) > LED_IOC_MAX)
       return -EINVAL;//检测命令数是不是超过最大的

    if(_IOC_DIR(cmd) & _IOC_READ) //检测是否可读
        err = !access_ok(VERIFY_WRITE,(void __user*)arg,_IOC_SIZE(cmd));
    else if(_IOC_DIR(cmd) & _IOC_WRITE)//检测是否可写
        err = !access_ok(VERIFY_READ,(void __user*)arg,_IOC_SIZE(cmd));

    if (err) //如果出错则处理
        return -EINVAL;

    //以上命令都是惯例,记住即可
    
    switch(cmd)
    {
    case LED_IOC_PRT:
        printk("<0>CMD IS LED_IOCPRT!\n");
       // ret = __get_user (val,(unsigned int *)arg);
       // printk ("<0>on cmd %x is %d\n",cmd,val);
        //iowrite32(val,io_mem+4);
        break;


    case LED_IOCSET_ON:
        printk("<0>CMD IS LED_IOCSET_ON!\n");
        ret = __get_user(val,(unsigned int *)arg);
        printk ("<0>on cmd %x is %d\n",cmd,val);
        iowrite32(val,led_mem+4);
        break;
    case LED_IOCSET_OFF:
        printk("<0>CMD IS LED_IOCSET_OFF!\n");
        ret = __get_user (val,(unsigned int *)arg);
        printk ("<0>on cmd %x is %d\n",cmd,val);
        iowrite32(val,led_mem+4);
        break;
    default:
        return -EINVAL;
        
    }
    return ret;
}

static const struct file_operations miscops =
{
    .owner = THIS_MODULE,
    .ioctl = misc_ioctl,
};

static struct miscdevice misc =
{
    .minor = 30,
    .name = DEVICE_NAME,
    .fops = &miscops,
};


static int miscdev_init(void)
{
    int result;
    unsigned int cmd;

    result = misc_register(&misc);
    printk("<0>misc device driver inited!\n");

    //申请IO内存
    if(request_mem_region(rGPBCON,8,DEVICE_NAME)==NULL)
    {
        printk("<0>request mem err!\n");
    }
    if ((led_mem = (char*)ioremap(rGPBCON,8)) == NULL)
    {
        printk("<0>led mem err!\n");
        return -1;
    }

     cmd &= ~((3<<10)|(3<<12)|(3<<14)|(3<<16));
     cmd |= (1<<10)|(1<<12)|(1<<14)|(1<<16);
     iowrite32(cmd,led_mem);
     cmd = LED_OFF;
     iowrite32(cmd,led_mem+4);
    
    return 0;

    
}

static void miscdev_exit()
{
     iounmap(led_mem);
     release_mem_region(rGPBCON,8);
     misc_deregister(&misc);
}

module_init(miscdev_init);
module_exit(miscdev_exit);
MODULE_LICENSE("GPL");


然后它包含的头文件如下:

#ifndef _RAINLEDDRV_H_
#define _RAINLEDDRV_H__

#include <linux/ioctl.h>


//定义命令
#define LED_IOC_MAX 2 //定义最大命令数目是 3

#ifndef LED_IOC_MAGIC
#define LED_IOC_MAGIC 'k' //定义幻数
#endif
//定义命令
#ifndef LED_IOC_PRT
#define LED_IOC_PRT _IO(LED_IOC_MAGIC,0)
#endif

#ifndef LED_IOCSET_ON
#define LED_IOCSET_ON _IOW(LED_IOC_MAGIC,1,unsigned int)
#endif

#ifndef LED_IOCSET_OFF
#define LED_IOCSET_OFF _IOW(LED_IOC_MAGIC,2,unsigned int)
#endif

#define LED_ON ~(0x0000000f<<5)
#define LED_OFF 0x0000000f<<5
#define rGPBCON (0x56000010)    //Port B control
#define rGPBDAT (0x56000014)    //Port B data
#define rGPBUP (0x56000018)    //Pull-up control B






#endif


再最后是应用程序:

#include <stdio.h>
#include <string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

#include "rainleddrv.h"

int main(int argc, char *argv[])
{
    int fd = 0;
    int cmd = 0;
    int arg = 0;
    if(argc!=2)
    {
        printf("参数不够!\n");
        return -1;
    }


    if((fd = open("/dev/ledmiscdev",O_RDWR))<0)
    {
        printf("device open failed !\n");
        //出错处理
        return -1;
    }
    
    if(!strcmp(argv[1],"on"))
    {
        printf("cmd is on\n");
        cmd = LED_IOCSET_ON;
        arg = LED_ON;
    }
    else if(!strcmp(argv[1],"off"))
    {
        printf("cmd is off\n");
        cmd = LED_IOCSET_OFF;
        arg = LED_OFF;
    }
    if (!strcmp(argv[1],"pt"))
    {
        printf("cmd is print\n");
        cmd = LED_IOC_PRT;
// arg = LED_ON;
    }
    
    if (ioctl(fd,cmd,&arg) < 0)
    {
        printf("IOctl err !\n");
        return -1;
    }
    
    close(fd);
    return 0;
}

应用程序同样要包含上面的头文件。
阅读(1800) | 评论(0) | 转发(1) |
0

上一篇:C99中struct的高级用法

下一篇:ADS1.2注册码

给主人留下些什么吧!~~