Ejemplo n.º 1
0
static unsigned int init_lirc_timer(void)
{
    struct timeval tv, now;
    unsigned int level, newlevel, timeelapsed, newtimer;
    int count = 0;

    do_gettimeofday(&tv);
    tv.tv_sec++;                     /* wait max. 1 sec. */
    level = lirc_get_timer();
    do {
        newlevel = lirc_get_timer();
        if (level == 0 && newlevel != 0)
            count++;
        level = newlevel;
        do_gettimeofday(&now);
    } while (count < 1000 && (now.tv_sec < tv.tv_sec
                              || (now.tv_sec == tv.tv_sec
                                  && now.tv_usec < tv.tv_usec)));

    timeelapsed = ((now.tv_sec + 1 - tv.tv_sec)*1000000
                   + (now.tv_usec - tv.tv_usec));
    if (count >= 1000 && timeelapsed > 0) {
        if (default_timer == 0) {
            /* autodetect timer */
            newtimer = (1000000*count)/timeelapsed;
            printk(KERN_INFO "%s: %u Hz timer detected\n",
                   LIRC_DRIVER_NAME, newtimer);
            return newtimer;
        }  else {
            newtimer = (1000000*count)/timeelapsed;
            if (abs(newtimer - default_timer) > default_timer/10) {
                /* bad timer */
                printk(KERN_NOTICE "%s: bad timer: %u Hz\n",
                       LIRC_DRIVER_NAME, newtimer);
                printk(KERN_NOTICE "%s: using default timer: "
                       "%u Hz\n",
                       LIRC_DRIVER_NAME, default_timer);
                return default_timer;
            } else {
                printk(KERN_INFO "%s: %u Hz timer detected\n",
                       LIRC_DRIVER_NAME, newtimer);
                return newtimer; /* use detected value */
            }
        }
    } else {
        printk(KERN_NOTICE "%s: no timer detected\n", LIRC_DRIVER_NAME);
        return 0;
    }
}
Ejemplo n.º 2
0
static unsigned int init_lirc_timer(void)
{
	ktime_t kt, now, timeout;
	unsigned int level, newlevel, timeelapsed, newtimer;
	int count = 0;

	kt = ktime_get();
	/* wait max. 1 sec. */
	timeout = ktime_add_ns(kt, NSEC_PER_SEC);
	level = lirc_get_timer();
	do {
		newlevel = lirc_get_timer();
		if (level == 0 && newlevel != 0)
			count++;
		level = newlevel;
		now = ktime_get();
	} while (count < 1000 && (ktime_before(now, timeout)));
	timeelapsed = ktime_us_delta(now, kt);
	if (count >= 1000 && timeelapsed > 0) {
		if (default_timer == 0) {
			/* autodetect timer */
			newtimer = (1000000 * count) / timeelapsed;
			pr_info("%u Hz timer detected\n", newtimer);
			return newtimer;
		}
		newtimer = (1000000 * count) / timeelapsed;
		if (abs(newtimer - default_timer) > default_timer / 10) {
			/* bad timer */
			pr_notice("bad timer: %u Hz\n", newtimer);
			pr_notice("using default timer: %u Hz\n",
				  default_timer);
			return default_timer;
		}
		pr_info("%u Hz timer detected\n", newtimer);
		return newtimer; /* use detected value */
	}

	pr_notice("no timer detected\n");
	return 0;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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);

	
}
Ejemplo n.º 6
0
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;
}