Beispiel #1
0
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);

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