Linux驱动开发--通过按键控制led灯

2019-07-12 23:49发布

/*说明:通过OK6410开发板自带的user key 的前四个控制led的开关,对应的,按key1,led1亮,亲自验证无误*/#include #include #include #include #include /*包含struct file_operations,MAJOR等*/ #include /*kmalloc*/ #include /*class_creat,device_creat*/ #include /*ioread8...*/ #include /*s3c_gpio_cfgpin*/ #include /*gpio_set_value*/ #include /*request_irq()*/ #include /*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 "); } 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 "); 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 "); goto fail; } key_dev->key_class= class_create(THIS_MODULE,"key_class"); if(IS_ERR(key_dev->key_class)){ printk("Err: failed increating class. "); return -1; } device_create(key_dev->key_class, NULL, devno,NULL,DEVICE_NAME); INIT_WORK(&(key_dev->key_workstruct),do_workstruct); for(i=0;icdev); 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 "); module_init(key_init); module_exit(key_exit);