当前位置:编程学习 > C/C++ >>

特殊按键--休眠键驱动

这是一个关于休眠和关机的按键驱动。板子:pxa31X系列  内核:2.6.25
这个驱动用到了内核文件操作,内核线程,等待队列,异步通知,并介绍了一种调试驱动的方法。
[cpp]  
#include <linux/init.h>  
#include <linux/module.h>  
#include <linux/kernel.h>  
#include <linux/fs.h>  
#include <linux/syscalls.h>  
#include <linux/unistd.h>  
#include <linux/miscdevice.h>  
#include <linux/platform_device.h>  
#include <linux/uaccess.h>  
#include <linux/string.h>  
#include <asm/arch/pxa-regs.h>  
#include <asm/arch/pxa3xx-regs.h>  
#include <asm/arch/mfp-pxa300.h>  
#include <asm/arch/gpio.h>  
#include <asm/uaccess.h>    //用于内核线程  
#include <linux/irq.h>   
#include <linux/interrupt.h>  
#include <linux/ioctl.h>  
#include <linux/sched.h>  
#include <linux/kthread.h>  
#include <linux/errno.h>  
#include <linux/spinlock.h>  
#include <linux/mutex.h>  
#include <linux/wait.h>  
#include <asm/semaphore.h>  
  
#include "pmb.h"  
  
#define PB_DEVICE_NAME "william_pmb"              
  
//#define DEBUG  
#ifdef DEBUG  
    #define pr_debug(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)  
#else  
    #define pr_debug(fmt, arg...) printk(KERN_INFO fmt, ##arg)  
#endif  
/* 
用于调试驱动的一种方法。 
其中printk函数中的参数,定义于<linux/kernel.h>。 
#define KERN_EMERG  "<0>" /* system is unusable紧急事件消息,系统崩溃前提示,表示系统不可用*/  
#define KERN_ALERT  "<1>" /* action must be taken immediately 报告消息,表示必须马上采取措施*/  
#define KERN_CRIT   "<2>" /* critical conditions临界情况,通常用于涉及严重的硬件或软件操作失败*/  
#define KERN_ERR    "<3>" /* error conditions错误情况,驱动程序常用来报告硬件错误*/  
#define KERN_WARNING    "<4>" /* warning conditions警告,对可能出现问题的情况进行警告*/  
#define KERN_NOTICE "<5>" /* normal but significant condition正常但又重要的情况,常用于提醒与安全相关的消息*/  
#define KERN_INFO   "<6>" /* informational提示信息*/  
#define KERN_DEBUG  "<7>" /* debug-level messages调试级别消息*/  
*/  
  
/*硬件上的一些定义*/  
#define PECR_E0IS   (1 << 29) // EXT_WAKEUP<0> Interrupt Status  
#define PECR_E0IE   (1 << 28) // EXT_WAKEUP<0> Pin Interrupt Enable  
#define PECR_DIR0(1 << 4) //Direction for EXT_WAKEUP<0>: 0/1= input/output  
#define PECR_IVE0   (1 << 0)  //Input Value for EXT_WAKEUP<0>  
  
//Currently we have  
#define IRQ_WAKEUP0 PXA_IRQ(49) /* EXT_WAKEUP0 */  
#define IRQ_WAKEUP1 PXA_IRQ(50) /* EXT_WAKEUP1 */  
  
//一个重要的全局结构体  
static struct powerkey_t pwk;  
/* 
struct powerkey_t  
{    
    int ifopen;     //check if device is opened 
    unsigned int pressed;       //current key state     [0/1=release/press] 
    int event;  //event:        [0/1/2/3=narmal/sleep/deepsleep/wakeup] 
    wait_queue_head_t keywaitq;     //powerkey queue 
    struct tast_struct *p_thread; 
    int checkforsleep;      //check if which event for sleep 
    int ifhandshake;        //check if need to handshake with app[] 
    int handshake; 
    struct fasync_struct *pwrkey_async_queue; 
    int ifreleasehandshakecnt;      //0: you can release handshake. >0: can't release handshake   
}; 
*/  
  
static int pb_handshake(int sig,int mode);  
  
static int wakeup_init(void)  
{     
    PECR |= PECR_E0IE;  //enable wakeup0 interrupt  
    PECR &= ~PECR_DIR0; //as input  
    return 0;  
}  
  
static int disable_wakeup(void)  
{     
    PECR &= ~PECR_E0IE; //disable wakeup0 interrupt  
    return 0;  
}  
  
static int wakeup_ack_irq(void)  
{     
    PECR |= PECR_E0IS;  //interrupt state, write 1 to clear  
    return 0;  
}  
  
  
static int pb_sleep_exe(int sleep)  
{  
    int ret;  
    struct file *fd;  
    mm_segment_t old_fs;  
    //printk("%s\n",__FUNCTION__);  
      
    fd = filp_open("sys/power/state",O_RDWR,0);  
    if(IS_ERR(fd))  
    {  
        printk("Open sys/power/state fail,ret = %ld \n",IS_ERR(fd));  
        return -1;  
    }  
    old_fs = get_fs();  
    set_fs(KERNEL_DS);  
    switch(sleep)  
    {  
        case SLEEP_EVENT:  
            printk("sleep!\n");  
            ret = fd->f_op->write(fd,"mem",3,&fd->f_pos);  
            if(ret != 3)  
            {  
                printk("Write to sleep fail!\n");  
            }  
            //printk("sleep write ok!\n");  
            break;  
        case DEEPSLEEP_EVENT:  
            ret = fd->f_op->write(fd,"deepsleep",9,&fd->f_pos);  
            if(ret != 9)  
         
补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,