Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1254250
  • 博文数量: 404
  • 博客积分: 10011
  • 博客等级: 上将
  • 技术积分: 5382
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-03 16:29
文章存档

2010年(40)

2009年(140)

2008年(224)

我的朋友

分类: LINUX

2008-09-25 17:45:22

/*这段代码是一个用户模式下的DEMO,不是真正的驱动,它负责把按键的键值打印输出*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

int main(void)
{
    int buttons_fd;
    int key_value;

    buttons_fd = open("/dev/buttons", 0);
    if (buttons_fd < 0) {
        perror("open device buttons");
        exit(1);
    }

    for (;;) {
        fd_set rds;
        int ret;

        FD_ZERO(&rds);
        FD_SET(buttons_fd, &rds);

        ret = select(buttons_fd + 1, &rds, NULL, NULL, NULL);
        if (ret < 0) {
              perror("select");
              exit(1);
        }
        if (ret == 0) {
              printf("Timeout.\n");
        } else if (FD_ISSET(buttons_fd, &rds)) {
              int ret = read(buttons_fd, &key_value, sizeof key_value);
              if (ret != sizeof key_value) {
                  if (errno != EAGAIN)
                      perror("read buttons\n");
                  continue;
              } else {
                  printf("buttons_value: %d\n", key_value);
              }
                  
        }
    }

    close(buttons_fd);
    return 0;
}

/*下面是真正的驱动部分*/
#include
#include
#include
#include

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

#include

#define DEVICE_NAME     "buttons"
#define BUTTON_MAJOR 232

static struct key_info {
    int irq_no;
    unsigned int gpio_port;
    int key_no;
} key_info_tab[4] = {
    { IRQ_EINT1, GPIO_F1, 1 },
    { IRQ_EINT2, GPIO_F2, 2 },
    { IRQ_EINT3, GPIO_F3, 3 },
    { IRQ_EINT7, GPIO_F7, 4 },
};

static int ready = 0;
static int key_value = 0;

static DECLARE_WAIT_QUEUE_HEAD(buttons_wait);

static void buttons_irq(int irq, void *dev_id, struct pt_regs *reg)
{
    struct key_info *k;
    int i;
    int found = 0;
    int up;
    int flags;
    for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++) {
        k = key_info_tab + i;
        if (k->irq_no == irq) {
              found = 1;
              break;
        }
    }
    if (!found) {
        printk("bad irq %d in button\n", irq);
        return;
    }

    save_flags(flags);
    cli();
    set_gpio_mode_user(k->gpio_port, GPIO_MODE_IN);
    up = read_gpio_bit(k->gpio_port);
    set_external_irq(k->irq_no, EXT_BOTH_EDGES, GPIO_PULLUP_DIS);
    restore_flags(flags);
    if (up) {
          key_value = k->key_no + 0x80;
    } else {
          key_value = k->key_no;
    }
        ready = 1;
    wake_up_interruptible(&buttons_wait);
}

static int request_irqs(void)
{
    struct key_info *k;
    int i;
    for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++) {
        k = key_info_tab + i;
        set_external_irq(k->irq_no, EXT_BOTH_EDGES, GPIO_PULLUP_DIS);
        if (request_irq(k->irq_no, &buttons_irq, SA_INTERRUPT, DEVICE_NAME, &buttons_irq)) {
              return -1;
        }
        
    }
    return 0;
}

static void free_irqs(void)
{
    struct key_info *k;
    int i;
    for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++) {
        k = key_info_tab + i;
        free_irq(k->irq_no, buttons_irq);
    }
}

static int matrix4_buttons_read(struct file * file, char * buffer, size_t count, loff_t *ppos)
{
    static int key;
    int flags;
    int repeat;
    if (!ready)
          return -EAGAIN;
    if (count != sizeof key_value)
          return -EINVAL;
    save_flags(flags);
    if (key != key_value) {
        key = key_value;
        repeat = 0;
    } else {
        repeat = 1;
    }
    restore_flags(flags);

    if (repeat) {
        return -EAGAIN;
    }
    
    copy_to_user(buffer, &key, sizeof key);
    ready = 0;
    return sizeof key_value;
}

static unsigned int matrix4_buttons_select(
    struct file *file,
    struct poll_table_struct *wait)
{
    if (ready)
          return 1;
    poll_wait(file, &buttons_wait, wait);
    return 0;
}


static int matrix4_buttons_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
    switch(cmd) {
    default:
        return -EINVAL;
    }
}
static struct file_operations matrix4_buttons_fops = {
    owner:     THIS_MODULE,
    ioctl: matrix4_buttons_ioctl,
    poll: matrix4_buttons_select,
    read: matrix4_buttons_read,
};

static devfs_handle_t devfs_handle;
static int __init matrix4_buttons_init(void)
{
    int ret;

    ready = 0;
    ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &matrix4_buttons_fops);
    if (ret < 0) {
      printk(DEVICE_NAME " can't register major number\n");
      return ret;
    }
    
    ret = request_irqs();
    if (ret) {
        unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
        printk(DEVICE_NAME " can't request irqs\n");
        return ret;
    }
    devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
                  BUTTON_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR, &matrix4_buttons_fops, NULL);

    return 0;
}

static void __exit matrix4_buttons_exit(void)
{
    devfs_unregister(devfs_handle);
    free_irqs();
    unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
}

module_init(matrix4_buttons_init);
module_exit(matrix4_buttons_exit);
MODULE_LICENSE("GPL");

阅读(1023) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~