Linux驱动开发--通过按键控制led灯
2013-06-10 20:53
453 查看
/*说明:通过OK6410开发板自带的user key 的前四个控制led的开关,对应的,按key1,led1亮,亲自验证无误*/
#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/cdev.h> #include <linux/fs.h>/*包含struct file_operations,MAJOR等*/ #include <linux/slab.h>/*kmalloc*/ #include <linux/device.h>/*class_creat,device_creat*/ #include <asm/io.h>/*ioread8...*/ #include <plat/gpio-cfg.h>/*s3c_gpio_cfgpin*/ #include <linux/gpio.h>/*gpio_set_value*/ #include <linux/interrupt.h>/*request_irq()*/ #include <linux/workqueue.h>/*work_struct*/ #define KEY_MAJOR 125 #define KEY_COUNT 4 #define DEVICE_NAME "key_led" int key_major=KEY_MAJOR; struct KEY{ int irq; unsigned long flags; char* name; }; static struct KEY key[]={ {IRQ_EINT(0),IRQF_TRIGGER_LOW,"key1"}, {IRQ_EINT(1),IRQF_TRIGGER_LOW,"key2"}, {IRQ_EINT(2),IRQF_TRIGGER_LOW,"key3"}, {IRQ_EINT(3),IRQF_TRIGGER_LOW,"key4"}, }; struct KEY_DEV{ struct cdev cdev; struct class* key_class; struct work_struct key_workstruct; int value; }; struct KEY_DEV *key_dev; int key_open(struct inode* inode,struct file* filp) { struct KEY_DEV* dev; dev=container_of(inode->i_cdev,struct KEY_DEV,cdev); filp->private_data=dev; return 0; } int key_release(struct inode* inode,struct file* filp) { return 0; } ssize_t key_read(struct file* filp,char __user *buf,size_t count,loff_t *f_pos) { return 0; } ssize_t key_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_pos) { return 0; } long key_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) { struct KEY_DEV *key_dev=filp->private_data; switch(cmd){ default: return -ENOTTY; } return 0; } struct file_operations key_fops={ .owner=THIS_MODULE, .open=key_open, .read=key_read, .write=key_write, .unlocked_ioctl=key_ioctl, .release=key_release, }; void init_led(void) { int i; s3c_gpio_cfgpin_range(S3C64XX_GPM(0),S3C64XX_GPM(3),S3C_GPIO_SFN(1)); for(i=0;i<4;i++){ gpio_set_value(S3C64XX_GPM(i),1); } for(i=0;i<4;i++){ s3c_gpio_setpull(S3C64XX_GPM(i),S3C_GPIO_PULL_NONE); } } void led_on(int led_no) { switch(led_no) { case 1: gpio_set_value(S3C64XX_GPM(0),0); break; case 2: gpio_set_value(S3C64XX_GPM(1),0); break; case 3: gpio_set_value(S3C64XX_GPM(2),0); break; case 4: gpio_set_value(S3C64XX_GPM(3),0); break; default: break; } } irqreturn_t key_interrupt(int irq,void* dev_id) { switch(irq){ case IRQ_EINT(0): key_dev->value=IRQ_EINT(0); schedule_work(&(key_dev->key_workstruct)); break; case IRQ_EINT(1): key_dev->value=IRQ_EINT(1); schedule_work(&(key_dev->key_workstruct)); break; case IRQ_EINT(2): key_dev->value=IRQ_EINT(2); schedule_work(&(key_dev->key_workstruct)); break; case IRQ_EINT(3): key_dev->value=IRQ_EINT(3); schedule_work(&(key_dev->key_workstruct)); break; default: schedule_work(&(key_dev->key_workstruct)); break; } return IRQ_HANDLED; } void do_workstruct(struct work_struct *work) { struct KEY_DEV* dev=container_of(work,struct KEY_DEV,key_workstruct); init_led(); switch(dev->value) { case IRQ_EINT(0): led_on(1); break; case IRQ_EINT(1): led_on(2); break; case IRQ_EINT(2): led_on(3); break; case IRQ_EINT(3): led_on(4); break; default: break; } printk("has key\n"); } static int __init key_init(void) { int result,i; dev_t devno; if(KEY_MAJOR){ devno=MKDEV(KEY_MAJOR,0); result=register_chrdev_region(devno,1,DEVICE_NAME); }else{ result=alloc_chrdev_region(&devno,0,1,DEVICE_NAME); key_major=MAJOR(devno); } if(result<0){ printk(KERN_WARNING "ERROR: can not register\n"); return result; } key_dev=kmalloc(sizeof(struct KEY_DEV),GFP_KERNEL); if(!key_dev){ result=-ENOMEM; goto fail; } memset(key_dev,0,sizeof(struct KEY_DEV)); cdev_init(&key_dev->cdev,&key_fops); key_dev->cdev.owner=THIS_MODULE; result=cdev_add(&key_dev->cdev,devno,1); if(result){ printk(KERN_WARNING "ERROR: can not add cdev\n"); goto fail; } key_dev->key_class= class_create(THIS_MODULE,"key_class"); if(IS_ERR(key_dev->key_class)){ printk("Err: failed increating class.\n"); return -1; } device_create(key_dev->key_class, NULL, devno,NULL,DEVICE_NAME); INIT_WORK(&(key_dev->key_workstruct),do_workstruct); for(i=0;i<KEY_COUNT;i++){ result=request_irq(key[i].irq,key_interrupt,key[i].flags,key[i].name,(void *)devno); if(result){ printk(KERN_ERR"request irq failed!\n"); return -1; } } return 0; fail: unregister_chrdev_region(devno,1); return result; } static void __exit key_exit(void) { dev_t devno=MKDEV(key_major,0); free_irq(IRQ_EINT(0),key_interrupt); if(key_dev){ cdev_del(&key_dev->cdev); kfree(key_dev); } device_destroy(key_dev->key_class,devno); class_destroy(key_dev->key_class); unregister_chrdev_region(devno,1); } MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("yixuaning <yixuaning@sina.com>"); module_init(key_init); module_exit(key_exit);
相关文章推荐
- tiny6410 Linux 按键控制LED驱动
- Linux驱动开发之S3C2440按键点亮LED
- Linux驱动开发之S3C2440按键点亮LED
- Linux驱动开发之S3C2440按键点亮LED
- Linux button按键驱动 多次中断控制相应LED灯亮灭闪
- linux驱动按键控制led灯
- linux驱动开发--字符设备:通过cdd_cdev结构中的led变量区分是哪个节点,private_data使用
- “手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动
- Linux驱动开发之六----按键驱动(中断方式)修改版
- 嵌入式Linux设备驱动开发之:按键驱动程序实例
- Linux驱动开发之四-----LED改进测试(增加自动创建设备节点)
- 按键控制led驱动
- micro2440利用LEDS与BUTTONS驱动实现按键控制led灯【开发总结】
- ARM开发之linux字符型驱动的编写----LED驱动为例
- 4412驱动-fifth_fasyn 控制led 蜂鸣器 按键
- 慢慢学Linux驱动开发,第九篇,tiny6410_LED驱动
- linux驱动开发“飞凌ok6410开发板之系列led驱动的开发”
- “手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动
- 第三个实验 通过中断方式让按键控股按键控制LED
- [置顶] ARM开发(4)基于STM32的矩阵键盘按键控制TM1629A LED显示