linux下查询方式的按键驱动

From: http://blog.163.com/joshuachan@yeah/blog/static/1691840422011102845750569/ 
 
根据《Linux简单字符设备驱动编写方法》一文的步骤,用查询方式简单实现Mini2440开发板的按键驱动程序。

代码共分二个文件,驱动程序<btn_drv.c>和测试程序<btn_test.c>。

<btn_drv.c>

/* *************************************** * Name: btn_drv.c * Proj: 简单按键驱动程序查询方式实现(Mini2440) * Desc: 驱动程序 * Auth & Date: Joshua Chan 2011/11/28 * **************************************/ #include <linux/module.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/io.h> #include <linux/uaccess.h> /* 查询设备手册, 按键1~6对应GPG 0, 3, 5, 6, 7, 11 */ #define GPG_BASE 0x56000060 // 定义GPG起始物理地址 volatile unsigned long *gpgcon; // 定义GPGCON虚拟地址 volatile unsigned long *gpgdat; // 定义GPGDAT虚拟地址 /* 为file_operations结构定义open()函数 */ static int btn_open(struct inode *inode, struct file *file) { /* 用ioremap()将物理地址映射到虚拟地址 */ gpgcon = ioremap(GPG_BASE, 12); if (!gpgcon) { printk("ioremap() failed.\n"); return -1; } gpgdat = gpgcon + 1; /* 配置引脚为输入状态 */ *gpgcon &= ~((3 << 0*2) | (3 << 3*2) | (3 << 5*2) | (3 << 6*2) | (3 << 7*2) | (3 << 11*2)); return 0; } /* 为file_operations结构定义read()函数 */ static ssize_t btn_read(struct file *file, char __user *buff, size_t size, loff_t * loff) { unsigned long tmp; unsigned char s[6]; if (size != 6) { printk("Read size %d invalid.\n", size); return 0; } /* 读取GPGDAT数据, 并将按键状态写入buff */ tmp = *gpgdat; s[0] = tmp & (1 << 0) ? 1 : 0; s[1] = tmp & (1 << 3) ? 1 : 0; s[2] = tmp & (1 << 5) ? 1 : 0; s[3] = tmp & (1 << 6) ? 1 : 0; s[4] = tmp & (1 << 7) ? 1 : 0; s[5] = tmp & (1 << 11) ? 1 : 0; /* 将数据传回用户空间 */ copy_to_user(buff, s, 6); return sizeof(s); } /* 为file_operations结构准备release方法 */ static int btn_close(struct inode *inode, struct file *file) { iounmap(gpgcon); return 0; } /* 注册设备驱动前需先定义file_operations结构, 并填充操作方法 */ static struct file_operations btn_fops = { .owner = THIS_MODULE, .open = btn_open, .read = btn_read, .release = btn_close, }; static int major; // 定义主设备号 static struct class *btn_class; // 定义设备类 static struct device *btn_device; // 定义设备 /* 驱动入口函数 */ static int __init btn_init(void) { /* 注册设备驱动, 参数主设备号置0将自动分配设备号并返回 */ major = register_chrdev(0, "my_buttons", &btn_fops); if (major <= 0) { printk("register_chrdev() failed.\n"); return -1; } /* 自动生成设备文件前, 需生成设备类 */ btn_class = class_create(THIS_MODULE, "my_buttons"); if (IS_ERR(btn_class)) { printk("class_create() failed.\n"); unregister_chrdev(major, "my_buttons"); return -1; } /* 自动生成设备结点文件 */ btn_device = device_create(btn_class, NULL, MKDEV(major, 0), NULL, "my_buttons"); if (IS_ERR(btn_device)) { printk("device_create() failed.\n"); unregister_chrdev(major, "my_buttons"); class_destroy(btn_class); return -1; } return 0; } /* 模块出口函数 */ static void __exit btn_exit(void) { unregister_chrdev(major, "my_buttons"); device_unregister(btn_device); class_destroy(btn_class); } module_init(btn_init); module_exit(btn_exit); MODULE_LICENSE("GPL");


<btn_test.c>
/* ***************************************
 * Name: btn_test.c
 * Proj: 简单按键驱动程序查询方式实现(Mini2440)
 * Desc: 驱动测试程序
 * Auth & Date: Joshua Chan 2011/11/28
 * **************************************/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdbool.h>

int main(void)
{
    int fd, i;
    int count = 0;
    unsigned char s[6];

    /* 打开设备文件 */
    fd = open("/dev/my_buttons", O_RDONLY);
    if (fd < 0) {
        printf("Open buttons error.\n");
        return -1;
    }

    /* 循环方式查询并打印按键信息 */
    while (true) {
        i = read(fd, s, 6);
        if (i != sizeof(s)) {
            printf("Read buttons error.\n");
            return -1;
        }
        printf("%d: ", count++);
        for (i = 0; i < 6; i++) {
            printf("%s", s[i] ? "1" : "0");
        }

        putchar('\n');

        for (i = 0; i < 6; i++) {
            if (s[i] == 0)
                printf("Button %d is pressed.\n", i + 1);
        }

        sleep(1);
    }

    close(fd);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值