当前位置:  技术问答>linux和unix

加载混杂字符设备驱动在/dev/下没有出现设备文件,请帮忙分析我程序!

    来源: 互联网  发布时间:2016-12-12

    本文导语:  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #define DEVICE_NAME         "buttons"    //设备名称                 #define KEY_TIMER_DELAY1    (HZ/50)     ...

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define DEVICE_NAME         "buttons"    //设备名称
               
#define KEY_TIMER_DELAY1    (HZ/50)             //按键按下去抖延时20毫秒        
#define KEY_TIMER_DELAY2    (HZ/10)             //按键抬起去抖延时100毫秒
#define KEY_DOWN            0                   //按键按下                    
#define KEY_UP              1                   //按键抬起                
#define KEY_UNCERTAIN       2                   //按键不确定    

#define KEY_COUNT           4                   //4个按键                    

static volatile int ev_press = 0;                //按键按下产生标志
static volatile int key_status[KEY_COUNT];       //记录4个按键的状态    
static struct timer_list key_timers[KEY_COUNT];  //定义4个按键去抖动定时器
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);    //定义并初始化等待队列

//组织硬件资源结构体
struct button_irq_desc    
{
    int irq;            //中断号
    int pin;            //引脚
    int pin_setting;    //引脚配置
    char *name;         //按键名称,注意这个名称,在后面的一个现象中会出现
};

//定义6个按键资源结构体数组
static struct button_irq_desc button_irqs[] =
 {
    {IRQ_EINT0 , S3C2410_GPF0 , S3C2410_GPF0_EINT0 , "KEY0"},
    {IRQ_EINT2, S3C2410_GPF2 , S3C2410_GPF2_EINT2 , "KEY1"},
    {IRQ_EINT3, S3C2410_GPF3 , S3C2410_GPF3_EINT3 , "KEY2"},
    {IRQ_EINT4, S3C2410_GPF4 , S3C2410_GPF4_EINT4 , "KEY3"},
  
};

static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
 //获取当前按键资源的索引
    int key = (int)dev_id;

    if(key_status[key] == KEY_UP)
    {
        //设置当前按键的状态为不确定
        key_status[key] = KEY_UNCERTAIN;

        //设置当前按键按下去抖定时器的延时并启动定时器
        key_timers[key].expires = jiffies + KEY_TIMER_DELAY1;
        add_timer(&key_timers[key]);
    }

    return IRQ_RETVAL(IRQ_HANDLED);
}

static void buttons_timer(unsigned long arg)
{
    //获取当前按键资源的索引
    int key = arg;

    //获取当前按键引脚上的电平值来判断按键是按下还是抬起
    int up = s3c2410_gpio_getpin(button_irqs[key].pin);

    if(!up)//低电平,按键按下
    {
        if(key_status[key] == KEY_UNCERTAIN)
        {
            //标识当前按键状态为按下
key_status[key] = KEY_DOWN;

            //标识当前按键已按下并唤醒等待队列
            ev_press = 1;
            wake_up_interruptible(&button_waitq);
        }

        //设置当前按键抬起去抖定时器的延时并启动定时器
        key_timers[key].expires = jiffies + KEY_TIMER_DELAY2;
        add_timer(&key_timers[key]);
    }
    else//高电平,按键抬起
    {
        //标识当前按键状态为抬起
        key_status[key] = KEY_UP;
    }
}

static int buttons_open(struct inode *inode, struct file *file)
{
    int i;
    int ret;

    for(i = 0; i = 0; i--)
        {
            //释放已注册成功的中断
            disable_irq(button_irqs[i].irq);
            free_irq(button_irqs[i].irq, (void *)i);
        }

        return -EBUSY;
    }

    return 0;
}

static int buttons_close(struct inode *inode, struct file *file)
{
    int i;

    //释放4个定时器和中断
    for(i = 0; i f_flags & O_NONBLOCK)
        {
            //应用程序若采用非阻塞方式读取则返回错误
            return -EAGAIN;
        }
        else
        {
            //以阻塞方式读取且按键按下没有产生,让等待队列进入睡眠
            wait_event_interruptible(button_waitq, ev_press);
        }
    }

    //1为按键按下产生,并清除标识为0,准备给下一次判断用
    ev_press = 0;

    //将内核中的按键状态数据拷贝到用户空间给应用程序使用
    ret = copy_to_user(buf, (void *)key_status, min(sizeof(key_status), count));

    return ret ? -EFAULT : min(sizeof(key_status), count);
}

//驱动程序中的轮询,用于应用程序中的轮询查询是否可对设备进行访问
static unsigned int buttons_poll(struct file *file, struct poll_table_struct *wait)
{
    unsigned int mask = 0;

    //添加等待队列到等待队列表中(poll_table)
 poll_wait(file, &button_waitq, wait);

    if(ev_press)
    {
        //标识数据可以获得
        mask |= POLLIN | POLLRDNORM;
    }

    return mask;
}

//设备操作列表
static struct file_operations buttons_fops =
 {
    .owner        = THIS_MODULE,
    .open         = buttons_open,
    .release      = buttons_close,
    .read         = buttons_read,
    .poll         = buttons_poll,
};

static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &buttons_fops,
};

static int __init button_init(void)
{
    int ret;
    //注册字符设备
    ret = misc_register(&misc);
    printk(DEVICE_NAME"module install successful!n");
    if(ret 

    
 
 

您可能感兴趣的文章:

  • 加载混杂设备
  • 相同设备分别加载不同驱动
  • 怎样调整X Window显示的分辨率?怎样加载USB接口的设备?
  • 加载驱动后,为什么有时在dev下不能自动显示设备文件?
  • usbhid妨碍了系统自动加载我的usb驱动程序,求教解决 (主要是加载后设备的驱动被认作usbhid)
  • 内核模块加载成功,但设备号申请不到
  • 2.4内核编译好的.o虚拟设备怎么在2.6下加载啊
  • 如何使Solaris不加载一个设备的驱动?
  • 如何实现插上USB存储设备后,系统自动加载
  • 在RedHat下如何加载USB设备,如优盘(100P)。。。
  • 什么HID设备加载的总是usbhid?(我认为是有难度的问题)
  • i2c设备加载驱动后没有执行probe
  • 很奇怪:fedora 8 用rc.local自动加载设备驱动程序失败?
  • Solaris下手动加载网卡设备驱动
  • I2C总线上字符设备驱动加载不成功,probe函数没有执行。
  • 加载驱动后/dev目录下的设备文件为什么打不开
  • 请教加载光驱错误(无效块设备)问题?
  • 设备驱动的Hello.ko 的驱动加载问题
  • 怎么样加载新的spi设备
  • 设备驱动编译无措,加载insmod不上(无错误提示)
  • DM9000驱动在友善mini2440开发板上加载成功,但启动设备时出现 WARNING: no IRQ resource flags set.
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • Linux下c函数dlopen实现加载动态库so文件代码举例
  • 请教一下Linux的动态库加载方式(是启动加载还是运行加载?)
  • Linux下指定运行时加载动态库路径及shell下执行程序默认路径
  • 在线等待!请文中怎么使用WebLogc的类加载器加载一个类?
  • struts+spring+hibernate+jquery实现分页功能的几个基本类介绍(异步加载)
  • driver的静态加载和动态加载占用内存问题
  • 可执行程序加载动态库 和 动态库加载动态库 的动态库初始化的问题
  • vmware下加载了一个虚拟软驱镜像,如果设置第一启动项为软驱的话,软驱能正常加载运行。但如果我第一启动项不设为软驱,正常启动fedora12的话。
  • 问问lib加载的问题
  • linux生成(加载)动态库静态库和加载示例方法
  • 使用非root用户加载模块出错
  • linux网卡驱动加载异常
  • 要写一个Linux下的elf加载器需要哪些知识?
  • js/css文件加载管理 uetjs
  • 如何加载硬盘?
  • 为何每次重启都要重新加载驱动模块?
  • JS文件加载优化 ControlJS
  • 无刷新动态加载数据与滚动条加载适合评论的jquery代码
  • jQuery数据延迟加载插件 DataLazyLoad
  • 问个动态库加载的问题
  • 浏览器窗口滚动加载数据采用异步形式从后台加载数据


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3