按键驱动(等待队列+设备树+属性文件)

来源:互联网 发布:辣鸡软件表情 编辑:程序博客网 时间:2024/05/18 15:31

吐舌头驱动:

#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/version.h>#include <linux/platform_device.h>#include <asm/io.h>#include <linux/fs.h>#include <linux/of.h>#include <linux/cdev.h>#include <linux/slab.h>#include <linux/interrupt.h>#include <asm/uaccess.h> #include <linux/wait.h>#include <linux/sched.h>#include <linux/spinlock.h>#include <linux/device.h>//--------------------------------------------------------------------------------// 查看 exynos4412-origen.dts // --> #include "exynos4412.dtsi" // 查看 exynos4412.dtsi // --> #include "exynos4x12.dtsi" // 查看 exynos4x12.dtsi// -->#include "exynos4.dtsi"//  #include "exynos4x12-pinctrl.dtsi"// 查看 exynos4x12-pinctrl.dtsi/* -->  gpx1: gpx1 {gpio-controller;#gpio-cells = <2>;interrupt-controller;interrupt-parent = <&gic>;interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,         <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;#interrupt-cells = <2>;};我们看到gpx1的中断控制父节点是gic(generic interrupt controller)查看 exynos4.dtsi --> #include "skeleton.dtsi"目标出现:------------------>gic: interrupt-controller@10490000 {compatible = "arm,cortex-a9-gic";#interrupt-cells = <3>;interrupt-controller;reg = <0x10490000 0x1000>, <0x10480000 0x100>;};查阅exynos4412手册-->0x1048_0000 GIC_controller0x1049_0000 GIC_distributor--------------------------------------------------------------------------------*/// 26 58 – EINT[10] External Interrupt// 25 57 – EINT[9]  External Interrupt/*DTSmykey{compatible = "btn2";interrupt-parent = <&gpx1>; // 父节点gpx1interrupts = <1 2>, <2 2>; // 锁定25, 26号中断<0 25 0>,<0 26 0>};*/MODULE_LICENSE("Dual BSD/GPL");MODULE_DESCRIPTION("key driver example!");#define NAME  _IOW('K', 0, int)#define VALU  _IOW('K', 1, int)struct key{dev_t num;int count; int irq_num;int key_val;int press_flag;spinlock_t lock;char key_name[10];struct cdev cdev_key;struct class *class;struct device *device;struct resource *res;struct timer_list btn_timer;wait_queue_head_t r_wq;}btn;void btnserver_func(unsigned long arg){spin_lock(&btn.lock);btn.press_flag = 1;spin_unlock(&btn.lock);wake_up_interruptible(&btn.r_wq); // 唤醒等待队列上的休眠进程printk("btn pressed: %d!\n", btn.count++);}irqreturn_t btn_int_handler(int n, void *dev){// 定时器去抖mod_timer(&btn.btn_timer, jiffies+50);return IRQ_HANDLED;}static int key_open(struct inode *inodp, struct file *filp){printk("key open call \n");strcpy(btn.key_name, "xxdk");btn.key_val = 'A';return 0;}ssize_t key_read (struct file *filp, char __user *buf, size_t size, loff_t *pos){if(!btn.press_flag) {wait_event_interruptible(btn.r_wq,  btn.press_flag != 0);printk("something happened\n");} if(btn.press_flag){printk("report to user.\n");if(copy_to_user(buf, btn.key_name, 10)) {printk("copy to user fail1\n");return -EINVAL;}spin_lock(&btn.lock);btn.press_flag = 0;spin_unlock(&btn.lock);}return 0;}static long key_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){char buf[10] = {0};int val = 0;int ret;switch(cmd){// 重置按键名称case NAME:ret = copy_from_user((void*)buf, (void*)arg, strlen((char*)arg));if(ret){printk("copy from user fail1\n");return -EINVAL;}printk("set btn name: %s\n", buf);memset(btn.key_name, 0, 10);strcpy(btn.key_name, buf);break;// 配置按键键值case VALU:ret = copy_from_user((void*)&val, (void*)arg, 4);if(ret){printk("copy from user fail1\n");return -EINVAL;}printk("set btn valu: %d\n", val);btn.key_val = val;break;}return 0;}static int key_release(struct inode *inodep, struct file *filep){printk("btn closed\n");return 0;}struct file_operations key_ops = {.owner = THIS_MODULE,.open = key_open,.read = key_read,.unlocked_ioctl  = key_ioctl,.release = key_release};#ifdef CONFIG_OFstruct of_device_id key_table[] = {{ .compatible = "key" },{ }};#endifint key_probe(struct platform_device *pdev);int key_remove(struct platform_device *pdev);struct platform_driver key_driver = {.probe = key_probe,.remove = key_remove,.driver = {.name = "key",.of_match_table = of_match_ptr(key_table)}};static ssize_t key_name_show(struct device_driver *driver, char *buf){printk("show btn name to user.\n");return scnprintf(buf, ARRAY_SIZE(btn.key_name), "%s\n", btn.key_name);}static ssize_t key_name_store(struct device_driver *driver,   const char *buf, size_t count){printk("store btn from user: %s\n", buf);memset(btn.key_name, 0, ARRAY_SIZE(btn.key_name));strncpy(btn.key_name, buf, count);return count;}static DRIVER_ATTR(btnname, 0666, key_name_show, key_name_store);int key_probe(struct platform_device *pdev){int ret = 0;printk("key probe !\n");//1. 配置定时器setup_timer(&btn.btn_timer, btnserver_func, 0);add_timer(&btn.btn_timer);//2. 解析中断号btn.res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);btn.irq_num = btn.res->start;printk("irqnum: %#x\n", btn.res->start);//3. 申请中断资源ret = request_irq(btn.irq_num, btn_int_handler, (btn.res->flags&IRQF_TRIGGER_MASK) | IRQF_DISABLED, "btn", NULL);//4. 申请设备号ret = alloc_chrdev_region(&btn.num, 0, 1, "btn");if(ret){printk("devnum alloc fail!\n");return ret;}printk("num: %d\n", MAJOR(btn.num));//5. init cdev opscdev_init(&btn.cdev_key,  &key_ops);btn.cdev_key.owner = THIS_MODULE;//register cdev into kernelret = cdev_add(&btn.cdev_key, btn.num, 1);if(ret){printk("add cdev fail!\n");goto cdev_add_out;}//6. btn.class = class_create(THIS_MODULE, "btn");btn.device = device_create(btn.class, NULL, btn.num, NULL, "btn%d", 0);//7. ret = driver_create_file(&key_driver.driver, &driver_attr_btnname);init_waitqueue_head(&btn.r_wq);spin_lock_init(&btn.lock);return 0;cdev_add_out:unregister_chrdev_region(btn.num, 1);return ret;}int key_remove(struct platform_device *pdev){printk("key module release\n");driver_remove_file(&key_driver.driver, &driver_attr_btnname);del_timer(&btn.btn_timer);//unregister cdev from kernelcdev_del(&btn.cdev_key);//release dev numunregister_chrdev_region(btn.num, 1); free_irq(btn.irq_num, NULL);device_del(btn.device);class_destroy(btn.class);return 0;}static int xkey_init(void){printk("module install\n");//add into platform busplatform_driver_register(&key_driver);return 0;}static void xkey_exit(void){printk("module release\n");//del from platform busplatform_driver_unregister(&key_driver);}module_init(xkey_init);module_exit(xkey_exit);
吐舌头测试:

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#define NAME  _IOW('K', 0, int)#define VALU  _IOW('K', 1, int)#define DEV_PATH "/dev/btn0"int main(int argc, char **argv){int fd, val;char buf[10] = {0};fd = open(DEV_PATH, O_RDWR);if(-1 == fd) {perror("open");return -1;}#if 0printf("please input btn name: ");scanf("%s", buf);ioctl(fd, NAME, buf);printf("please input btn valu: ");fflush(stdin);scanf("%d", &val);ioctl(fd, VALU, &val);#endifwhile(1) {//sleep(1);printf("btn fetch process------------>\n");read(fd, buf, 10);printf("get button pressed: %s\n", buf);}close(fd);return 0;}



0 0
原创粉丝点击