在上一贴成功点灯以后,笔者果断决定对代码进行修改,使其成为读取按键的程序。采用的是最笨的while循环查询的方法,希望对一起学习的新手们提供一定的借鉴,献丑了。
key.c:
- /*包含初始化宏定义的头文件,代码中的module_init和module_exit在此文件中*/
- #include
- /*包含初始化加载模块的头文件,代码中的MODULE_LICENSE在此头文件中*/
- #include
- /*三个字符设备函数*/
- #include
- /*MKDEV转换设备号数据类型的宏定义*/
- #include
- /*定义字符设备的结构体*/
- #include
- /*分配内存空间函数头文件*/
- #include
- /*包含函数device_create 结构体class等头文件*/
- #include
- #include //copy_to_user要包含这个
- #include
- #include //包含prink等函数
- #include //与c++相关的东西
- #include //Linux中申请GPIO的头文件
- /*自定义头文件*/
- #include "key.h"
- #include //不同平台使用的文件
- #include
- MODULE_LICENSE("Dual BSD/GPL");
- /*声明是开源的,没有内核版本限制*/
- MODULE_AUTHOR("XIE");
- /*声明作者*/
- static int key_gpios[] = {
- PAD_GPIO_C + 11,
- };
- #define KEY_NUM ARRAY_SIZE(key_gpios)
- int numdev_major = DEV_MAJOR;
- int numdev_minor = DEV_MINOR;
- static struct class *myclass;
- struct reg_dev *my_devices;
- /*打开操作*/
- static int chardevnode_open(struct inode *inode, struct file *file){
- printk(KERN_EMERG "chardevnode_open is success!n");
-
- return 0;
- }
- /*关闭操作*/
- static int chardevnode_release(struct inode *inode, struct file *file){
- printk(KERN_EMERG "chardevnode_release is success!n");
-
- return 0;
- }
- /*IO操作*/
- static long chardevnode_ioctl(struct file *file, unsigned int cmd, unsigned long arg){
- return 0;
- }
- ssize_t chardevnode_read(struct file *file, char __user *buf, size_t count, loff_t *f_ops){
- unsigned long key_val[KEY_NUM];
- int i;
- for(i = 0; i < KEY_NUM; i++){
- key_val[i] = gpio_get_value(key_gpios[i]);
- }
- /* 读出值后,将数据传给应用程序 */
- copy_to_user(buf, key_val, sizeof(key_val));
- return sizeof(key_val);
- }
- ssize_t chardevnode_write(struct file *file, const char __user *buf, size_t count, loff_t *f_ops){
- return 0;
- }
- loff_t chardevnode_llseek(struct file *file, loff_t offset, int ence){
- return 0;
- }
- struct file_operations my_fops = {
- .owner = THIS_MODULE,
- .open = chardevnode_open,
- .release = chardevnode_release,
- .unlocked_ioctl = chardevnode_ioctl,
- .read = chardevnode_read,
- .write = chardevnode_write,
- .llseek = chardevnode_llseek,
- };
- /*设备注册到系统*/
- static void reg_init_cdev(struct reg_dev *dev,int index){
- int err;
- int devno = MKDEV(numdev_major,numdev_minor+index);
- /*数据初始化*/
- cdev_init(&dev->cdev,&my_fops);
- dev->cdev.owner = THIS_MODULE;
-
-
- /*注册到系统*/
- err = cdev_add(&dev->cdev,devno,1);
- if(err){
- printk(KERN_EMERG "cdev_add %d is fail! %dn",index,err);
- }
- else{
- printk(KERN_EMERG "cdev_add %d is success!n",numdev_minor+index);
- }
- }
- static int gpio_init(void){
- int i=0,ret;
-
- for(i=0;i
- ret = gpio_request(key_gpios[i], "KEY");
- if (ret) {
- printk("%s: request GPIO %d for KEY failed, ret = %dn", DEVICE_NAME,i,ret);
- return -1;
- }
- else{
- gpio_direction_output(key_gpios[i], 1);
- }
- }
-
- return 0;
- }
- static int scdev_init(void)
- {
- int ret = 0,i;
- dev_t num_dev;
-
-
- printk(KERN_EMERG "numdev_major is %d!n",numdev_major);//主设备号
- printk(KERN_EMERG "numdev_minor is %d!n",numdev_minor);//次设备号
-
- if(numdev_major){
- num_dev = MKDEV(numdev_major,numdev_minor);//生成设备号
- ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME);//向系统申请设备号(已知设备号)
- }
- else{
- /*动态注册设备号*/
- ret = alloc_chrdev_region(&num_dev,numdev_minor,DEVICE_MINOR_NUM,DEVICE_NAME);//向系统申请设备号(动态申请)
- /*获得主设备号*/
- numdev_major = MAJOR(num_dev);
- printk(KERN_EMERG "adev_region req %d !n",numdev_major);
- }
- if(ret<0){
- printk(KERN_EMERG "register_chrdev_region req %d is failed!n",numdev_major);
- }
- myclass = class_create(THIS_MODULE,DEVICE_NAME);//创建设备类别文件
-
-
- my_devices = kmalloc(DEVICE_MINOR_NUM * sizeof(struct reg_dev),GFP_KERNEL);//分配内存
- if(!my_devices){
- ret = -ENOMEM;
- goto fail;
- }
- memset(my_devices,0,DEVICE_MINOR_NUM * sizeof(struct reg_dev));//将s中前n个字节用 ch 替换并返回 s 。
-
- /*设备初始化*/
- for(i=0;i
- my_devices[i].data = kmalloc(REGDEV_SIZE,GFP_KERNEL);//GFP_KERNEL是一个宏,分配内核空间
- memset(my_devices[i].data,0,REGDEV_SIZE);
- /*设备注册到系统*/
- reg_init_cdev(&my_devices[i],i);
-
- /*创建设备节点*/
- device_create(myclass,NULL,MKDEV(numdev_major,numdev_minor+i),NULL,DEVICE_NAME"%d",i);
- }
-
- ret = gpio_init();
- if(ret){
- printk(KERN_EMERG "gpio_init failed!n");
- }
-
- printk(KERN_EMERG "scdev_init!n");
- /*打印信息,KERN_EMERG表示紧急信息*/
- return 0;
- fail:
- /*注销设备号*/
- unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);
- printk(KERN_EMERG "kmalloc is fail!n");
-
- return ret;
- }
- static void scdev_exit(void)
- {
- int i;
- printk(KERN_EMERG "scdev_exit!n");
-
- /*除去字符设备*/
- for(i=0;i
- cdev_del(&(my_devices[i].cdev));//这个函数会干掉cdev_map 散列表及dev本身
- /*摧毁设备节点函数d*/
- device_destroy(myclass,MKDEV(numdev_major,numdev_minor+i));
- }
- /*释放设备class*/
- class_destroy(myclass);
- /*释放内存*/
- kfree(my_devices);
-
- /*释放GPIO*/
- for(i=0;i
- gpio_free(key_gpios[i]);
- }
- //释放设备号
- unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);
- }
- module_init(scdev_init);
- /*初始化函数*/
- module_exit(scdev_exit);
- /*卸载函数*/
key.h:
- #ifndef _CHAR_DRIVER_LEDS_H_
- #define _CHAR_DRIVER_LEDS_H_
- #ifndef DEVICE_NAME
- #define DEVICE_NAME "charGPIO"
- #endif
- #ifndef DEVICE_MINOR_NUM
- #define DEVICE_MINOR_NUM 1
- #endif
- #ifndef DEV_MAJOR
- #define DEV_MAJOR 0
- #endif
- #ifndef DEV_MINOR
- #define DEV_MINOR 0
- #endif
- #ifndef REGDEV_SIZE
- #define REGDEV_SIZE 3000
- #endif
- struct reg_dev
- {
- char *data;
- // unsigned long size;
- struct cdev cdev;
- };
- #endif
key_test.c:
- #include
- #include
- #include //各种系统api如read,write,sleep
- #include
- int main()
- {
- int fd,i;
- unsigned long key_val[1];
- char *lednode = "/dev/charGPIO0";
- /*O_RDWR只读打开,O_NDELAY非阻塞方式*/
- if((fd = open(lednode,O_RDWR|O_NDELAY))<0){
- printf("APP open %s failed!n",lednode);
- }
- else
- printf("APP open %s success!n",lednode);
- while(1)
- {
- read(fd,key_val,sizeof(key_val));
- if(key_val[0] == 0)
- printf("button0 is setn");
- else
- printf("waiting button0n");
- sleep(1);
- }
-
-
- close(fd);
- return 0;
- }
以上,由于是笔者是新手所以难免有疏漏或者不足,敬请各路大神指教咯
更多回帖