📄 lirc_parallel.c
字号:
schedule(); current->state=TASK_INTERRUPTIBLE; } } remove_wait_queue(&lirc_wait,&wait); current->state=TASK_RUNNING; return(count ? count:result);}#ifdef KERNEL_2_2static ssize_t lirc_write(struct file *filep,const char *buf,size_t n, loff_t *ppos)#elsestatic int lirc_write(struct inode *node,struct file *filep,const char *buf, int n)#endif{ int result,count; unsigned int i; unsigned int level,newlevel; unsigned long flags; lirc_t counttimer; #ifdef KERNEL_2_2 if(!is_claimed) { return(-EBUSY); }#endif if(n%sizeof(lirc_t)) return(-EINVAL); result=verify_area(VERIFY_READ,buf,n); if(result) return(result); count=n/sizeof(lirc_t); if(count>WBUF_SIZE || count%2==0) return(-EINVAL); #ifdef KERNEL_2_2 copy_from_user(wbuf,buf,n);#else memcpy_fromfs(wbuf,buf,n); /* if(check_region(io,LIRC_PORT_LEN)!=0) return(-EBUSY); */#endif #ifdef LIRC_TIMER if(timer==0) /* try again if device is ready */ { timer=init_lirc_timer(); if(timer==0) return(-EIO); } /* ajust values from usecs */ for(i=0;i<count;i++) { wbuf[i]=(lirc_t) (((double) wbuf[i])*timer/1000000); } save_flags(flags);cli(); i=0; while(i<count) { level=lirc_get_timer(); counttimer=0; lirc_on(); do { newlevel=lirc_get_timer(); if(level==0 && newlevel!=0) counttimer++; level=newlevel; if(in(1)&LP_PSELECD) { lirc_off(); restore_flags(flags); /* sti(); */ return(-EIO); } } while(counttimer<wbuf[i]);i++; lirc_off(); if(i==count) break; counttimer=0; do { newlevel=lirc_get_timer(); if(level==0 && newlevel!=0) counttimer++; level=newlevel; if(in(1)&LP_PSELECD) { restore_flags(flags); /* sti(); */ return(-EIO); } } while(counttimer<wbuf[i]);i++; } restore_flags(flags); /* sti(); */#else /* place code that handles write without extarnal timer here */#endif return(n);}#ifdef KERNEL_2_2static unsigned int lirc_poll(struct file *file, poll_table * wait){ poll_wait(file, &lirc_wait,wait); if (rptr!=wptr) return(POLLIN|POLLRDNORM); return(0);}#elsestatic int lirc_select(struct inode *node,struct file *file,int sel_type, select_table *wait){ if(sel_type!=SEL_IN) return 0; if(rptr!=wptr) return(1); select_wait(&lirc_wait,wait); return(0);}#endifstatic int lirc_ioctl(struct inode *node,struct file *filep,unsigned int cmd, unsigned long arg){ int result; unsigned long features=LIRC_CAN_SEND_PULSE|LIRC_CAN_REC_MODE2,mode; switch(cmd) { case LIRC_GET_FEATURES:# ifdef KERNEL_2_2 result=put_user(features,(unsigned long *) arg); if(result) return(result); # else result=verify_area(VERIFY_WRITE,(unsigned long*) arg, sizeof(unsigned long)); if(result) return(result); put_user(features,(unsigned long *) arg);# endif break; case LIRC_GET_SEND_MODE:# ifdef KERNEL_2_2 result=put_user(LIRC_MODE_PULSE,(unsigned long *) arg); if(result) return(result); # else result=verify_area(VERIFY_WRITE,(unsigned long *) arg, sizeof(unsigned long)); if(result) return(result); put_user(LIRC_MODE_PULSE,(unsigned long *) arg);# endif break; case LIRC_GET_REC_MODE:# ifdef KERNEL_2_2 result=put_user(LIRC_MODE_MODE2,(unsigned long *) arg); if(result) return(result); # else result=verify_area(VERIFY_WRITE,(unsigned long *) arg, sizeof(unsigned long)); if(result) return(result); put_user(LIRC_MODE_MODE2,(unsigned long *) arg);# endif break; case LIRC_SET_SEND_MODE:# ifdef KERNEL_2_2 result=get_user(mode,(unsigned long *) arg); if(result) return(result);# else result=verify_area(VERIFY_READ,(unsigned long *) arg, sizeof(unsigned long)); if(result) return(result); mode=get_user((unsigned long *) arg);# endif if(mode!=LIRC_MODE_PULSE) return(-EINVAL); break; case LIRC_SET_REC_MODE:# ifdef KERNEL_2_2 result=get_user(mode,(unsigned long *) arg); if(result) return(result);# else result=verify_area(VERIFY_READ,(unsigned long *) arg, sizeof(unsigned long)); if(result) return(result); mode=get_user((unsigned long *) arg);# endif if(mode!=LIRC_MODE_MODE2) return(-ENOSYS); break; default: return(-ENOIOCTLCMD); } return(0);}static int lirc_open(struct inode* node,struct file* filep){#ifndef KERNEL_2_2 int result;#endif if(MOD_IN_USE) { return(-EBUSY); }#ifdef KERNEL_2_2 if(!lirc_claim()) { return(-EBUSY); } pport->ops->enable_irq(pport);#else result=request_irq(irq,irq_handler,SA_INTERRUPT, LIRC_DRIVER_NAME,NULL); switch(result) { case -EBUSY: printk(KERN_NOTICE "%s: IRQ %u busy\n",LIRC_DRIVER_NAME,irq); return(-EBUSY); case -EINVAL: printk(KERN_NOTICE "%s: bad irq number or handler\n", LIRC_DRIVER_NAME); return(-EINVAL); } /* enable interrupt */ out(LIRC_PORT_IRQ,LP_PINITP|LP_PSELECP|LP_PINTEN);#endif /* init read ptr */ rptr=wptr=0; lost_irqs=0; MOD_INC_USE_COUNT; is_open=1; return(0);}#ifdef KERNEL_2_2static int lirc_close(struct inode* node,struct file* filep)#elsestatic void lirc_close(struct inode* node,struct file* filep)#endif{#ifdef KERNEL_2_2 if(is_claimed) { is_claimed=0; parport_release(ppdevice); }#else free_irq(irq,NULL); /* disable interrupt */ /* FIXME out(LIRC_PORT_IRQ,LP_PINITP|LP_PSELECP); */#endif is_open=0; MOD_DEC_USE_COUNT;#ifdef KERNEL_2_2 return(0);#endif}static struct file_operations lirc_fops = {#ifdef KERNEL_2_2 llseek: lirc_lseek,#else lseek: lirc_lseek,#endif read: lirc_read, write: lirc_write,#ifdef KERNEL_2_2 poll: lirc_poll,#else select: lirc_select,#endif ioctl: lirc_ioctl, open: lirc_open, release: lirc_close};#ifdef MODULE#if LINUX_VERSION_CODE >= 0x020200MODULE_AUTHOR("Christoph Bartelmus");MODULE_DESCRIPTION("Infrared receiver driver for parallel ports.");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endifMODULE_PARM(io, "i");MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)");MODULE_PARM(irq, "i");MODULE_PARM_DESC(irq, "Interrupt (7 or 5)");EXPORT_NO_SYMBOLS;#endif#ifdef KERNEL_2_2int pf(void *handle);void kf(void *handle);static struct timer_list poll_timer;static void poll_state(unsigned long ignored);static void poll_state(unsigned long ignored){ printk(KERN_NOTICE "%s: time\n", LIRC_DRIVER_NAME); del_timer(&poll_timer); if(is_claimed) return; kf(NULL); if(!is_claimed) { printk(KERN_NOTICE "%s: could not claim port, giving up\n", LIRC_DRIVER_NAME); init_timer(&poll_timer); poll_timer.expires=jiffies+HZ; poll_timer.data=(unsigned long) current; poll_timer.function=poll_state; add_timer(&poll_timer); }}int pf(void *handle){ pport->ops->disable_irq(pport); is_claimed=0; return(0);}void kf(void *handle){ if(!is_open) return; if(!lirc_claim()) return; pport->ops->enable_irq(pport); /* this is a bit annoying when you actually print...*/ /* printk(KERN_INFO "%s: reclaimed port\n",LIRC_DRIVER_NAME); */}#endif/*********************************************************************** ****************** init_module()/cleanup_module() ****************** ***********************************************************************/int init_module(void){#ifdef KERNEL_2_2 pport=parport_enumerate(); while(pport!=NULL) { if(pport->base==io) { break; } pport=pport->next; } if(pport==NULL) { printk(KERN_NOTICE "%s: no port at %x found\n", LIRC_DRIVER_NAME,io); return(-ENXIO); } ppdevice=parport_register_device(pport,LIRC_DRIVER_NAME, pf,kf,irq_handler,0,NULL); if(ppdevice==NULL) { printk(KERN_NOTICE "%s: parport_register_device() failed\n", LIRC_DRIVER_NAME); return(-ENXIO); } if(parport_claim(ppdevice)!=0) goto skip_init; is_claimed=1; out(LIRC_LP_CONTROL,LP_PSELECP|LP_PINITP);#else if(check_region(io,LIRC_PORT_LEN)!=0) { printk(KERN_NOTICE "%s: port already in use\n",LIRC_DRIVER_NAME); return(-EBUSY); } request_region(io,LIRC_PORT_LEN,LIRC_DRIVER_NAME);#endif#ifdef LIRC_TIMER# ifdef DEBUG out(LIRC_PORT_DATA,LIRC_PORT_DATA_BIT);# endif timer=init_lirc_timer();# if 0 /* continue even if device is offline */ if(timer==0) {# ifdef KERNEL_2_2 is_claimed=0; parport_release(pport); parport_unregister_device(ppdevice);# else release_region(io,LIRC_PORT_LEN);# endif return(-EIO); } # endif# ifdef DEBUG out(LIRC_PORT_DATA,0);# endif#endif #ifdef KERNEL_2_2 is_claimed=0; parport_release(ppdevice); skip_init:#endif if(register_chrdev(LIRC_MAJOR, LIRC_DRIVER_NAME, &lirc_fops)<0) { printk(KERN_NOTICE "%s: register_chrdev() failed\n",LIRC_DRIVER_NAME);#ifdef KERNEL_2_2 parport_unregister_device(ppdevice);#else release_region(io,LIRC_PORT_LEN);#endif return(-EIO); } printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n",LIRC_DRIVER_NAME,io,irq); return(0);} void cleanup_module(void){ if(MOD_IN_USE) return;#ifdef KERNEL_2_2 parport_unregister_device(ppdevice);#else release_region(io,LIRC_PORT_LEN);#endif unregister_chrdev(LIRC_MAJOR,LIRC_DRIVER_NAME);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -