如何实现2410的io按键驱动功能

lionedwolf   2007-8-30 16:14 楼主
我用的是友善之臂的sbc2410开发板,里面自带了个buttons的按钮驱动程序,我们进行了一些改动,如下的程序。现在按下按键后,可在终端上打印出信息,但是不能象标准键盘那样实现io功能,能查的资料也有限,请问大家,如何能把键值传送给内核终端呢?
例如我设定buton 1 为  l
button 2为 s
按下这两个后能实现ls的功能,该如何实现呢?谢谢
                                                                                                                                          


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

//MODULE_LICENSE("GPL");

#define DEVICE_NAME        "buttons"
#define BUTTON_MAJOR 232
//#define KEY_A 1
//#define KEY_B 2

//static struct input_dev buttons_dev;


//static char kbmap[]={
//                KK_LEFT,KK_UP,KK_RGHT,KK_DOWN
//};

static struct key_info {
        int irq_no;
        unsigned int gpio_port;
        int key_no;
} key_info_tab[4] = {
        { IRQ_EINT1, GPIO_F1, 0x59 },
        { IRQ_EINT2, GPIO_F2, 0x60 },
        { IRQ_EINT3, GPIO_F3, 0x61 },
        { IRQ_EINT7, GPIO_F7, 0x62 },
};

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;
//        printk("\nthis is buttons_irq program\n");
        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;
        handle_scancode(key_value,0);
        tasklet_schedule(&keyboard_tasklet);
                                                                                                                                               
//        input_report_key(&buttons_dev,key_value,1);
//        input_sync(&buttons_dev);
        printk("button  [%d]press up\n\n",k->key_no);
//        printk("this is irq %d\n",k->key_no);

        } else {
               key_value = k->key_no;

        handle_scancode(key_value,1);
        tasklet_schedule(&keyboard_tasklet);
//        input_report_key(&buttons_dev,key_value,2);
//        input_sync(&buttons_dev);
        printk("button  [%d] press down \n\n",k->key_no);
//        printk("this is irq %d\n",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 sbc2410_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 sbc2410_buttons_select(
        struct file *file,
        struct poll_table_struct *wait)
{
        if (ready)
                return 1;
        poll_wait(file, &buttons_wait, wait);
        return 0;
}


static int sbc2410_buttons_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
        switch(cmd) {
        default:
                return -EINVAL;
        }
}
static struct file_operations sbc2410_buttons_fops = {
        owner:        THIS_MODULE,
        ioctl:  sbc2410_buttons_ioctl,
        poll: sbc2410_buttons_select,
        read: sbc2410_buttons_read,
};



static int s3c_kbd_translate(unsigned char scancode, unsigned *keycode, char raw_mode)
{
        int nResult = 1;
        printk("my translate \n");
        *keycode = (scancode & 0x7f);
        return 1;
}

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

//        buttons_dev.name="tcbbuttons";
//        set_bit(EV_KEY,buttons_dev.evbit);
//        set_bit(KEY_A,buttons_dev.keybit);
//        set_bit(KEY_B,buttons_dev.keybit);
//        input_register_device(&buttons_dev);

        ready = 0;
        ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &sbc2410_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, &sbc2410_buttons_fops, NULL);
        k_translate         = s3c_kbd_translate;
        return 0;
}

static void __exit s3c2410_kbd_exit(void)
{
        devfs_unregister(devfs_handle);
        free_irqs();
        unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);
//        input_unregister_device(&buttons_dev);

}

module_init(s3c2410_kbd_init);
module_exit(s3c2410_kbd_exit);
MODULE_LICENSE("GPL");

回复评论 (6)

自己在顶一下吧
现在很是郁闷
点赞  2007-8-31 08:43
你好,请问你的问题解决了吗?
我现在也是遇到这样的问题,不知道如何解决,请你加我qq123885032好吗?
希望能得到你的帮助,谢谢!
点赞  2008-2-20 09:00
你可以在应用层,写一个while(1),来不停的读取key的值,把得到的值放在一个buffer内,当有读到一个值是enter(值可以自己定义)的key时,调用exec族函数就可以了(popen也可以)。我看有的代码是这样实现的。。。
点赞  2008-2-20 17:25
以后需再关注,现在先帮你顶一下
点赞  2008-5-1 07:40

6楼 yun 

也在关注中... ...
点赞  2008-5-13 08:50
你可以用内核input层的接口来做按键驱动,在应用层读input_event这个结构就可以了
点赞  2008-6-22 17:16
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复