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 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; }