static int __init lirc_parallel_init(void) { pport = parport_find_base(io); 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); parport_put_port(pport); 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); #ifdef LIRC_TIMER if (debug) out(LIRC_PORT_DATA, tx_mask); timer = init_lirc_timer(); #if 0 /* continue even if device is offline */ if (timer == 0) { is_claimed = 0; parport_release(pport); parport_unregister_device(ppdevice); return -EIO; } #endif if (debug) out(LIRC_PORT_DATA, 0); #endif is_claimed = 0; parport_release(ppdevice); skip_init: driver.minor = lirc_register_driver(&driver); if (driver.minor < 0) { printk(KERN_NOTICE "%s: register_chrdev() failed\n", LIRC_DRIVER_NAME); parport_unregister_device(ppdevice); return -EIO; } printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n", LIRC_DRIVER_NAME, io, irq); return 0; }
static int __init lirc_parallel_init(void) { int result; result = platform_driver_register(&lirc_parallel_driver); if (result) { pr_notice("platform_driver_register returned %d\n", result); return result; } lirc_parallel_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0); if (!lirc_parallel_dev) { result = -ENOMEM; goto exit_driver_unregister; } result = platform_device_add(lirc_parallel_dev); if (result) goto exit_device_put; pport = parport_find_base(io); if (pport == NULL) { pr_notice("no port at %x found\n", io); result = -ENXIO; goto exit_device_put; } ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME, pf, kf, lirc_lirc_irq_handler, 0, NULL); parport_put_port(pport); if (ppdevice == NULL) { pr_notice("parport_register_device() failed\n"); result = -ENXIO; goto exit_device_put; } if (parport_claim(ppdevice) != 0) goto skip_init; is_claimed = 1; out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); #ifdef LIRC_TIMER if (debug) out(LIRC_PORT_DATA, tx_mask); timer = init_lirc_timer(); #if 0 /* continue even if device is offline */ if (timer == 0) { is_claimed = 0; parport_release(pport); parport_unregister_device(ppdevice); result = -EIO; goto exit_device_put; } #endif if (debug) out(LIRC_PORT_DATA, 0); #endif is_claimed = 0; parport_release(ppdevice); skip_init: driver.dev = &lirc_parallel_dev->dev; driver.minor = lirc_register_driver(&driver); if (driver.minor < 0) { pr_notice("register_chrdev() failed\n"); parport_unregister_device(ppdevice); result = -EIO; goto exit_device_put; } pr_info("installed using port 0x%04x irq %d\n", io, irq); return 0; exit_device_put: platform_device_put(lirc_parallel_dev); exit_driver_unregister: platform_driver_unregister(&lirc_parallel_driver); return result; }
static ssize_t lirc_write(struct file *filep, const char __user *buf, size_t n, loff_t *ppos) { int count; unsigned int i; unsigned int level, newlevel; unsigned long flags; int counttimer; int *wbuf; ssize_t ret; if (!is_claimed) return -EBUSY; count = n / sizeof(int); if (n % sizeof(int) || count % 2 == 0) return -EINVAL; wbuf = memdup_user(buf, n); if (IS_ERR(wbuf)) return PTR_ERR(wbuf); #ifdef LIRC_TIMER if (timer == 0) { /* try again if device is ready */ timer = init_lirc_timer(); if (timer == 0) { ret = -EIO; goto out; } } /* adjust values from usecs */ for (i = 0; i < count; i++) { __u64 helper; helper = ((__u64) wbuf[i])*timer; do_div(helper, 1000000); wbuf[i] = (int) helper; } local_irq_save(flags); 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 (check_pselecd && (in(1) & LP_PSELECD)) { lirc_off(); local_irq_restore(flags); ret = -EIO; goto out; } } 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 (check_pselecd && (in(1) & LP_PSELECD)) { local_irq_restore(flags); ret = -EIO; goto out; } } while (counttimer < wbuf[i]); i++; } local_irq_restore(flags); #else /* place code that handles write without external timer here */ #endif ret = n; out: kfree(wbuf); return ret; }
static void lirc_lirc_irq_handler(void *blah) { struct timeval tv; static struct timeval lasttv; static int init; long signal; int data; unsigned int level, newlevel; unsigned int timeout; if (!is_open) return; if (!is_claimed) return; #if 0 /* disable interrupt */ disable_irq(irq); out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN)); #endif if (check_pselecd && (in(1) & LP_PSELECD)) return; #ifdef LIRC_TIMER if (init) { do_gettimeofday(&tv); signal = tv.tv_sec - lasttv.tv_sec; if (signal > 15) /* really long time */ data = PULSE_MASK; else data = (int) (signal*1000000 + tv.tv_usec - lasttv.tv_usec + LIRC_SFH506_DELAY); rbuf_write(data); /* space */ } else { if (timer == 0) { /* * wake up; we'll lose this signal, but it will be * garbage if the device is turned on anyway */ timer = init_lirc_timer(); /* enable_irq(irq); */ return; } init = 1; } timeout = timer/10; /* timeout after 1/10 sec. */ signal = 1; level = lirc_get_timer(); do { newlevel = lirc_get_timer(); if (level == 0 && newlevel != 0) signal++; level = newlevel; /* giving up */ if (signal > timeout || (check_pselecd && (in(1) & LP_PSELECD))) { signal = 0; pr_notice("timeout\n"); break; } } while (lirc_get_signal()); if (signal != 0) { /* adjust value to usecs */ __u64 helper; helper = ((__u64) signal)*1000000; do_div(helper, timer); signal = (long) helper; if (signal > LIRC_SFH506_DELAY) data = signal - LIRC_SFH506_DELAY; else data = 1; rbuf_write(PULSE_BIT|data); /* pulse */ } do_gettimeofday(&lasttv); #else /* add your code here */ #endif wake_up_interruptible(&lirc_wait); /* enable interrupt */ /* enable_irq(irq); out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN); */ }
static void irq_handler(void *blah) { struct timeval tv; static struct timeval lasttv; static int init; long signal; int data; unsigned int level, newlevel; unsigned int timeout; if (!is_open) return; if (!is_claimed) return; #if 0 disable_irq(irq); out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN)); #endif if (check_pselecd && (in(1) & LP_PSELECD)) return; #ifdef LIRC_TIMER if (init) { do_gettimeofday(&tv); signal = tv.tv_sec - lasttv.tv_sec; if (signal > 15) data = PULSE_MASK; else data = (int) (signal*1000000 + tv.tv_usec - lasttv.tv_usec + LIRC_SFH506_DELAY); rbuf_write(data); } else { if (timer == 0) { timer = init_lirc_timer(); return; } init = 1; } timeout = timer/10; signal = 1; level = lirc_get_timer(); do { newlevel = lirc_get_timer(); if (level == 0 && newlevel != 0) signal++; level = newlevel; if (signal > timeout || (check_pselecd && (in(1) & LP_PSELECD))) { signal = 0; printk(KERN_NOTICE "%s: timeout\n", LIRC_DRIVER_NAME); break; } } while (lirc_get_signal()); if (signal != 0) { __u64 helper; helper = ((__u64) signal)*1000000; do_div(helper, timer); signal = (long) helper; if (signal > LIRC_SFH506_DELAY) data = signal - LIRC_SFH506_DELAY; else data = 1; rbuf_write(PULSE_BIT|data); } do_gettimeofday(&lasttv); #else #endif wake_up_interruptible(&lirc_wait); }
static ssize_t lirc_write(struct file *filep, const char *buf, size_t n, loff_t *ppos) { int count; unsigned int i; unsigned int level, newlevel; unsigned long flags; lirc_t counttimer; if (!is_claimed) return -EBUSY; if (n % sizeof(lirc_t)) return -EINVAL; count = n / sizeof(lirc_t); if (count > WBUF_SIZE || count % 2 == 0) return -EINVAL; if (copy_from_user(wbuf, buf, n)) return -EFAULT; #ifdef LIRC_TIMER if (timer == 0) { /* try again if device is ready */ timer = init_lirc_timer(); if (timer == 0) return -EIO; } /* adjust values from usecs */ for (i = 0; i < count; i++) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) unsigned long long helper; helper = ((unsigned long long) wbuf[i])*timer; do_div(helper, 1000000); wbuf[i] = (lirc_t) helper; #else wbuf[i] = (lirc_t) (((double) wbuf[i])*timer/1000000); #endif } local_irq_save(flags); 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 (check_pselecd && (in(1) & LP_PSELECD)) { lirc_off(); local_irq_restore(flags); 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 (check_pselecd && (in(1) & LP_PSELECD)) { local_irq_restore(flags); return -EIO; } } while (counttimer < wbuf[i]); i++; } local_irq_restore(flags); #else /* place code that handles write without external timer here */ #endif return n; }