Chinaunix首页 | 论坛 | 博客
  • 博客访问: 806943
  • 博文数量: 87
  • 博客积分: 2571
  • 博客等级: 少校
  • 技术积分: 726
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-19 15:04
个人简介

重新开始,做回自我,爱拼的男人最牛!

文章分类
文章存档

2021年(2)

2020年(3)

2019年(17)

2014年(1)

2011年(1)

2010年(63)

我的朋友

分类: LINUX

2010-04-02 20:35:53

//keyboard1.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include 
#include
#include 
#include
#include 
#define     BUTTON_IRQ1 IRQ_EINT5
#define     BUTTON_IRQ2 IRQ_EINT6
#define DEVICE_NAME "button"
static int buttonMajor=0;
#define     BUTTONMINOR 0
#define     MAX_BUTTON_BUF 16
   
#define BUTTONSTATUS_1      5
#define BUTTONSTATUS_2      6

static unsigned char buttonRead(void);
static int flag=0;
typedef struct {
    unsigned int buttonStatus;      //按键状态
    unsigned char buf[MAX_BUTTON_BUF]; //按键缓冲区
    unsigned int head,tail;         //按键缓冲区头和尾
    wait_queue_head_t wq;           //等待队列
} BUTTON_DEV;
static BUTTON_DEV buttondev;
#define BUF_HEAD    (buttondev.buf[buttondev.head])     //缓冲区头
#define BUF_TAIL    (buttondev.buf[buttondev.tail])     //缓冲区尾
#define INCBUF(x,mod)   ((++(x)) & ((mod)-1))       //移动缓冲区指针
static void (*buttonEvent)(void);
static void buttonEvent_dummy(void) {}
static void buttonEvent_1(void)
{
    if(buttondev.buttonStatus==BUTTONSTATUS_2) {
    BUF_HEAD=BUTTONSTATUS_2;
     }
    else {
    BUF_HEAD=BUTTONSTATUS_1;
     }
    buttondev.head=INCBUF(buttondev.head,MAX_BUTTON_BUF);
    flag=1;
    wake_up_interruptible(&(buttondev.wq));
    printk("buttonEvent_1\n");
}
 static irqreturn_t isr_button(int irq,void *dev_id,struct pt_regs *regs)
{
  
    printk("Occured key board Inetrrupt,irq=%d\n",irq-44);
    switch (irq) {
    case BUTTON_IRQ1:buttondev.buttonStatus=BUTTONSTATUS_1;
                break;
    case BUTTON_IRQ2:buttondev.buttonStatus=BUTTONSTATUS_2;
                break;
    default:break;
     }
   
    buttonEvent();
    return 0;
}
static int button_open(struct inode *inode,struct file *filp)
{
    int ret;
    buttondev.head=buttondev.tail=0;
    buttonEvent=buttonEvent_1;
    ret=request_irq(BUTTON_IRQ1,isr_button,SA_INTERRUPT,DEVICE_NAME,NULL);
  if(ret) {
    printk("BUTTON_IRQ1: could not register interrupt ret=%d\n",ret);
    return ret;
     }
    ret=request_irq(BUTTON_IRQ2,isr_button,SA_INTERRUPT,DEVICE_NAME,NULL);
    if(ret) {
    printk("BUTTON_IRQ2: could not register interrupt\n");
    return ret;
     }
   return 0;
}
static int button_release(struct inode *inode,struct file *filp)
{
    buttonEvent=buttonEvent_dummy;
    free_irq(BUTTON_IRQ1,NULL);
    free_irq(BUTTON_IRQ2,NULL);
    return 0;
}
static ssize_t button_read(struct file *filp,char *buffer,size_t count,loff_t *ppos)
{
    static unsigned char button_ret;
retry:
    printk("retry start\n");
    if(buttondev.head!=buttondev.tail) {
    button_ret=buttonRead();
    copy_to_user(buffer,(char *)&button_ret,sizeof(unsigned char));
    printk("the button_ret is 0x%x\n",button_ret);
    return sizeof(unsigned char);
     }
    else {
    if(filp->f_flags & O_NONBLOCK)
        return -EAGAIN;
    printk("sleep\n");
    //interruptible_sleep_on(&(buttondev.wq));//为安全起见,最好不要调用该睡眠函数
    wait_event_interruptible(buttondev.wq,flag);
    flag=0;
    printk("sleep_after\n");
    if(signal_pending(current))
         {
        printk("rturn -ERESTARTSYS\n");
        return -ERESTARTSYS;
          }
    goto retry;
     }
    return sizeof(unsigned char);
}
static struct file_operations button_fops= {
    .owner =   THIS_MODULE,
    .open   =   button_open,
    .read   =   button_read,
    .release    =   button_release,
};
 
static int __init s3c2410_button_init(void)
{
    int ret;
    set_irq_type(BUTTON_IRQ1,IRQT_FALLING);
    set_irq_type(BUTTON_IRQ2,IRQT_FALLING);
    buttonEvent=buttonEvent_dummy;
   
    ret=register_chrdev(0,DEVICE_NAME,&button_fops);
    if(ret<0) {
    printk("button: can't get major number\n");
    return ret;
     }
    buttonMajor=ret;
#ifdef CONFIG_DEVFS_FS
devfs_mk_cdev(MKDEV(buttonMajor,BUTTONMINOR),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,DEVICE_NAME);
#endif
    //buttondev.head=buttondev.tail=0;
    buttondev.buttonStatus=BUTTONSTATUS_1;
    init_waitqueue_head(&(buttondev.wq));
    printk(DEVICE_NAME" initialized\n");
    return 0;
}
static unsigned char buttonRead(void)
{
    unsigned char button_ret;
    button_ret=BUF_TAIL;
    buttondev.tail=INCBUF(buttondev.tail,MAX_BUTTON_BUF);
    return button_ret;
}
   
static void __exit s3c2410_button_eixt(void)
{
#ifdef CONFIG_DEVFS_FS
    devfs_remove(DEVICE_NAME);
   
#endif
    unregister_chrdev(buttonMajor,DEVICE_NAME);
    printk("\nbutton remove\n");
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kision");
MODULE_DESCRIPTION ("the first char device driver");
module_init(s3c2410_button_init);
module_exit(s3c2410_button_eixt);

//keyboard2.c
#include
#include
#include
#include
#include         /* for in_interrupt */
#include
#include
#include               /* for udelay */
#include
#include
#include
#include
#include
#include
//linux在初始化的时候已经把每个中断向量的地址准备好
#define IRQ_KEY_UP IRQ_EINT19
#define IRQ_KEY_DOWN IRQ_EINT11
#define IRQ_KEY_LEFT IRQ_EINT2
#define IRQ_KEY_RIGHT IRQ_EINT8
#define IRQ_KEY_SPACE IRQ_EINT21
#define IRQ_KEY_ALT IRQ_EINT22
#define IRQ_KEY_ENTER  IRQ_EINT23
      //
#define Keypad_MAJOR 97//定义键盘设备号
typedef struct devfs_entry *devfs_handle_t;
 devfs_handle_t dev_handle;             /* register handle to store device fs */
static  int Keycode = 0;
static unsigned char haveData = 0;
static DECLARE_WAIT_QUEUE_HEAD(keypad);// 经过宏展开后就是定义了一个keypad等待队列头变量,核心运行过程中,经常会因为某些条件不满足而需要挂起当前线程,直至条件满足了才继续执行
//static unsigned char spiRead();
//static void keyboard_Init();
static void KEY_interrupt(int nr, void *devid, struct pt_regs *regs);
ssize_t keypad_read (struct file * file ,char * buf, size_t count, loff_t * f_ops)
{
      interruptible_sleep_on(&keypad);//挂起程序
      copy_to_user(buf, &Keycode, sizeof Keycode);
      haveData = 0;
      return 1;
}

ssize_t keypad_open (struct inode * inode ,struct file * file)
{
      printk("s3c2410:device open operation!\n");
      return 0;
}
struct file_operations Keypad_ops ={
      open:       keypad_open,
      read:       keypad_read,
     // poll:       keypad_select,
};
 
//中断处理函数
static void KEY_interrupt(int nr, void *devid, struct pt_regs *regs)
{
switch(nr)
{
case IRQ_KEY_UP:
  Keycode=0x1013;
  break;
case IRQ_KEY_DOWN:
  Keycode=0x1015;
  break;
case IRQ_KEY_LEFT:
  Keycode=0x1012;
  break;
case IRQ_KEY_RIGHT:
  Keycode=0x1014;
  break;
case IRQ_KEY_SPACE:
  Keycode=0x1003;
  break;
case IRQ_KEY_ALT:
  Keycode=0x1023;
  break;
case IRQ_KEY_ENTER:
  Keycode=0x1005;
  break;
default: break;
}
 haveData = 1;
 wake_up_interruptible(&keypad);//唤醒程序
}
static int __init keypad_init(void)//键盘初始化程序
{
 int ret = -ENODEV;
        set_irq_type(IRQ_KEY_UP,IRQT_RISING);
//请求中断
        set_irq_type(IRQ_KEY_DOWN,IRQT_RISING);
//请求中断
        set_irq_type(IRQ_KEY_LEFT,IRQT_RISING);
//请求中断
        set_irq_type(IRQ_KEY_RIGHT,IRQT_RISING);
//请求中断
        set_irq_type(IRQ_KEY_SPACE,IRQT_RISING);
//请求中断
       set_irq_type(IRQ_KEY_ALT,IRQT_RISING);
//请求中断
        set_irq_type(IRQ_KEY_ENTER,IRQT_RISING);
//请求中断
 ret = devfs_register_chrdev(Keypad_MAJOR, "Keypad", &Keypad_ops);
  //字符设备注册,主设备号,设备名,函数关联结构体
 if( ret < 0 ){
             printk (" Keypad: init_module failed with %d\n", ret);
             return ret;
    }
 ret = request_irq(IRQ_KEY_UP, KEY_interrupt, SA_INTERRUPT,
                      "Keypad", NULL);// 注册中断服务程序,把中断向量和中断服务程序对应起来。
 if (ret) {
     devfs_unregister_chrdev(Keypad_MAJOR, "Keypad");//取消注册
              printk(KERN_INFO "request Keypad IRQ failed (%d)\n", IRQ_KEY_UP);
           return ret;
    }
   
    ret = request_irq(IRQ_KEY_DOWN, KEY_interrupt, SA_INTERRUPT,
                      "Keypad", NULL);// 注册中断服务程序,把中断向量和中断服务程序对应起来。
 if (ret) {
     devfs_unregister_chrdev(Keypad_MAJOR, "Keypad");//取消注册
              printk(KERN_INFO "request Keypad IRQ failed (%d)\n", IRQ_KEY_DOWN);
           return ret;
    }
  ret = request_irq( IRQ_KEY_LEFT, KEY_interrupt, SA_INTERRUPT,
                      "Keypad", NULL);// 注册中断服务程序,把中断向量和中断服务程序对应起来。
 if (ret) {
     devfs_unregister_chrdev(Keypad_MAJOR, "Keypad");//取消注册
              printk(KERN_INFO "request Keypad IRQ failed (%d)\n",  IRQ_KEY_LEFT);
           return ret;
    }
   
     ret = request_irq(IRQ_KEY_RIGHT, KEY_interrupt, SA_INTERRUPT,
                      "Keypad", NULL);// 注册中断服务程序,把中断向量和中断服务程序对应起来。
 if (ret) {
     devfs_unregister_chrdev(Keypad_MAJOR, "Keypad");//取消注册
              printk(KERN_INFO "request Keypad IRQ failed (%d)\n",  IRQ_KEY_RIGHT);
           return ret;
    }
   
     ret = request_irq(IRQ_KEY_SPACE, KEY_interrupt, SA_INTERRUPT,
                      "Keypad", NULL);// 注册中断服务程序,把中断向量和中断服务程序对应起来。
 if (ret) {
     devfs_unregister_chrdev(Keypad_MAJOR, "Keypad");//取消注册
              printk(KERN_INFO "request Keypad IRQ failed (%d)\n",  IRQ_KEY_SPACE);
           return ret;
    }
   
     ret = request_irq(IRQ_KEY_ALT, KEY_interrupt, SA_INTERRUPT,
                      "Keypad", NULL);// 注册中断服务程序,把中断向量和中断服务程序对应起来。
 if (ret) {
     devfs_unregister_chrdev(Keypad_MAJOR, "Keypad");//取消注册
              printk(KERN_INFO "request Keypad IRQ failed (%d)\n", IRQ_KEY_ALT);
           return ret;
    }
   
     ret = request_irq(IRQ_KEY_ENTER, KEY_interrupt, SA_INTERRUPT,
                      "Keypad", NULL);// 注册中断服务程序,把中断向量和中断服务程序对应起来。
 if (ret) {
     devfs_unregister_chrdev(Keypad_MAJOR, "Keypad");//取消注册
              printk(KERN_INFO "request Keypad IRQ failed (%d)\n", IRQ_KEY_ENTER);
           return ret;
    }
      
    dev_handle = devfs_register( NULL, "Keypad", DEVFS_FL_DEFAULT,
                                 Keypad_MAJOR, 0, S_IFCHR, &Keypad_ops, NULL);
//登记设备入口点,获得文件句柄
    return ret;
}
int spiWrite(u8 Keycode)
{
 ZLGCSEN();
 ZLGMO();
 udelay(60);
 
 while((SPSTA1 & 0x01)== 0);
  SPTDAT1 = Keycode;//数据寄存器
 while((SPSTA1 & 0x01)== 0);
 
 ZLGCSDIS();
 
 return 0;
}
 
static unsigned char spiRead(void)
{
 unsigned char code;
 
 ZLGCSEN();
 ZLGMO();
 udelay(60);
 
 while((SPSTA1 & 0x01)== 0);
  SPTDAT1 = 0x15;
 while((SPSTA1 & 0x01)== 0);
 
 udelay(30);
 
 ZLGMI();
 SPTDAT1 = 0xff;//状态寄存器
 while((SPSTA1 & 0x01)== 0);
 
 ZLGCSDIS();
 ZLGMO();
 code = SPSTA1; //状态寄存器
 return code;
}
static void spi_Init()//spi外围串口初始化程序
{
 // Setup IO port for SPI interface & Keyboard
 
 // Setup EINT1 (KBDINT)
     GPFCON &= ~(0x3 << 2);   // Clear GPF1
     GPFCON |= (0x2 << 2);    // Set GPF1 to EINT1 for Keyboard interrupt
     EXTINT0 &= ~(0x7 << 4);     // Clear EINT1
     EXTINT0 |= (0x2 << 4);      // fallig edge triggered for EINT1
 // setup SPI interface
 GPGCON &= ~((0x3 << 10) | (0x3 << 12) | (0x3 << 14));   // Clear GPG5,6,7
     GPGCON |= ((0x3 << 10) | (0x3 << 12) | (0x3 << 14));   
    
 // setup _SS signal(nSS_KBD)
     GPBCON &= ~(0x3 << 12);         // Clear GPB6
     GPBCON |= (0x01 << 12);       // Set Port GPB6 to output for nSS signal
   
    ZLGCSDIS();            // Set /SS high
 // setup Dir signal (KEYBOARD)  CPU->7289
     GPBCON &= ~(0x3 << 0);         // Clear GPB0
     GPBCON |= (0x01 << 0);       // Set Port GPB0 to output for _PWR_OK signal
 
 ZLGMO();
       
 // Setup SPI registers
     SPCON1 = (0<<5)|(0X01 << 4)|(0X01 << 3)|(0x0<<2)|(0<<1);
       
 // Developer MUST change the value of prescaler properly whenever value of PCLK is changed.
     SPPRE1 = 255;     // 99.121K = 203M/4/2/(255+1) PCLK=50.75Mhz FCLK=203Mhz        SPICLK=99.121Khz
 spiWrite(0xa4);    //send init command
     printk("Key Pad Init complete:\n");
 }
 

/*static int keypad_select(struct file *file, struct poll_table_struct *wait)
{
 if(haveData)
  return 1;
 return 0;
}*/
int __init sw4_init_module()
{
      int ret = -ENODEV;
      ret = keypad_init();//键盘初始化
      if (ret)
         return ret;
      return 0;
}
void __exit sw4_cleanup_module()
{
  
         free_irq(IRQ_KBD, NULL);// 释放中断
         devfs_unregister_chrdev( Keypad_MAJOR, "Keypad" );//注销设备号
         devfs_unregister( dev_handle );//注销设备文件句柄
   return;
}
module_init(sw4_init_module);//内核特殊的宏,指明次函数为模块
module_exit(sw4_cleanup_module);
MODULE_LICENSE("GPL");//采用GPL软件许可证
 
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lzz2005/archive/2008/12/08/3479098.aspx
阅读(1168) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~