Ejemplo n.º 1
0
static void it87_timeout(unsigned long data) 
{
	/* if last received signal was a pulse, but receiving stopped
	   within the 9 bit frame, we need to finish this pulse and
	   simulate a signal change to from pulse to space. Otherwise
	   upper layers will receive two sequences next time. */
	
	unsigned long flags;
	unsigned long pulse_end;
	
	/* avoid interference with interrupt */
 	spin_lock_irqsave(&timer_lock, flags);
	if (last_value) {
		/* determine 'virtual' pulse end: */
	 	pulse_end = delta(&last_tv, &last_intr_tv);
#ifdef DEBUG_SIGNAL
		printk(KERN_DEBUG LIRC_DRIVER_NAME
		       ": timeout add %d for %lu usec\n",
		       last_value,
		       pulse_end);
#endif
		add_read_queue(last_value,
			       pulse_end);
		last_value = 0;
		last_tv=last_intr_tv;
	}
	spin_unlock_irqrestore(&timer_lock, flags);		
}
Ejemplo n.º 2
0
Archivo: sir_ir.c Proyecto: mdamt/linux
/* SECTION: Hardware */
static void sir_timeout(unsigned long data)
{
	/*
	 * if last received signal was a pulse, but receiving stopped
	 * within the 9 bit frame, we need to finish this pulse and
	 * simulate a signal change to from pulse to space. Otherwise
	 * upper layers will receive two sequences next time.
	 */

	unsigned long flags;
	unsigned long pulse_end;

	/* avoid interference with interrupt */
	spin_lock_irqsave(&timer_lock, flags);
	if (last_value) {
		/* clear unread bits in UART and restart */
		outb(UART_FCR_CLEAR_RCVR, io + UART_FCR);
		/* determine 'virtual' pulse end: */
		pulse_end = min_t(unsigned long,
				  ktime_us_delta(last, last_intr_time),
				  IR_MAX_DURATION);
		dev_dbg(&sir_ir_dev->dev, "timeout add %d for %lu usec\n",
			last_value, pulse_end);
		add_read_queue(last_value, pulse_end);
		last_value = 0;
		last = last_intr_time;
	}
	spin_unlock_irqrestore(&timer_lock, flags);
	ir_raw_event_handle(rcdev);
}
Ejemplo n.º 3
0
static void it87_interrupt(int irq,
			   void * dev_id,
			   struct pt_regs * regs)
{
	unsigned char data;
	struct timeval curr_tv;
	static unsigned long deltv;
	unsigned long deltintrtv;
	unsigned long flags, hw_flags;
	int iir, lsr;
	int fifo = 0;

	iir = inb(io + IT87_CIR_IIR);

	switch (iir & IT87_CIR_IIR_IID) {
	case 0x4:
	case 0x6:
		lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO |
						    IT87_CIR_RSR_RXFBC);
		fifo = lsr & IT87_CIR_RSR_RXFBC;
#ifdef DEBUG_SIGNAL
		printk(KERN_DEBUG LIRC_DRIVER_NAME
		       "iir: 0x%x fifo: 0x%x\n", iir, lsr);
#endif
	
		/* avoid interference with timer */
		spin_lock_irqsave(&timer_lock, flags);
		spin_lock_irqsave(&hardware_lock, hw_flags);
		do {
			del_timer(&timerlist);
			data = inb(io + IT87_CIR_DR);
#ifdef DEBUG_SIGNAL
			printk(KERN_DEBUG LIRC_DRIVER_NAME
			       ": data=%.2x\n",
			       data);
#endif
			do_gettimeofday(&curr_tv);
			deltv = delta(&last_tv, &curr_tv);
			deltintrtv = delta(&last_intr_tv, &curr_tv);
#ifdef DEBUG_SIGNAL
			printk(KERN_DEBUG LIRC_DRIVER_NAME
			       ": t %lu , d %d\n",
			       deltintrtv,
			       (int)data);
#endif
			/* if nothing came in last 2 cycles,
			   it was gap */
			if (deltintrtv > TIME_CONST * 2) {
				if (last_value) {
#ifdef DEBUG_SIGNAL
					printk(KERN_DEBUG LIRC_DRIVER_NAME ": GAP\n");
#endif
					/* simulate signal change */
					add_read_queue(last_value,
						       deltv-
						       deltintrtv);
					last_value = 0;
					last_tv.tv_sec = last_intr_tv.tv_sec;
					last_tv.tv_usec = last_intr_tv.tv_usec;
					deltv = deltintrtv;
				}
			}
			data = 1;
			if (data ^ last_value) {
				/* deltintrtv > 2*TIME_CONST,
				   remember ? */
				/* the other case is timeout */
				add_read_queue(last_value,
					       deltv-TIME_CONST);
				last_value = data;
				last_tv = curr_tv;
				if(last_tv.tv_usec>=TIME_CONST) {
					last_tv.tv_usec-=TIME_CONST;
				}
				else {
					last_tv.tv_sec--;
					last_tv.tv_usec+=1000000-
						TIME_CONST;
				}
			}
			last_intr_tv = curr_tv;
			if (data) {
				/* start timer for end of sequence detection */
				timerlist.expires = jiffies + IT87_TIMEOUT;
				add_timer(&timerlist);
			}
			outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) |
			     IT87_CIR_RCR_RXACT,
			     io + IT87_CIR_RCR);
			if (it87_RXEN_mask) {
				outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, 
				     io + IT87_CIR_RCR);
			}
			fifo--;
		}
		while (fifo != 0);
		spin_unlock_irqrestore(&hardware_lock, hw_flags);
		spin_unlock_irqrestore(&timer_lock, flags);
		break;

	default:
		/* not our irq */
#ifdef DEBUG_SIGNAL
		printk(KERN_DEBUG LIRC_DRIVER_NAME
		       "unknown IRQ (shouldn't happen) !!\n");
#endif
		break;
	}
}
Ejemplo n.º 4
0
Archivo: sir_ir.c Proyecto: mdamt/linux
static irqreturn_t sir_interrupt(int irq, void *dev_id)
{
	unsigned char data;
	ktime_t curr_time;
	static unsigned long delt;
	unsigned long deltintr;
	unsigned long flags;
	int counter = 0;
	int iir, lsr;

	while ((iir = inb(io + UART_IIR) & UART_IIR_ID)) {
		if (++counter > 256) {
			dev_err(&sir_ir_dev->dev, "Trapped in interrupt");
			break;
		}

		switch (iir & UART_IIR_ID) { /* FIXME toto treba preriedit */
		case UART_IIR_MSI:
			(void)inb(io + UART_MSR);
			break;
		case UART_IIR_RLSI:
		case UART_IIR_THRI:
			(void)inb(io + UART_LSR);
			break;
		case UART_IIR_RDI:
			/* avoid interference with timer */
			spin_lock_irqsave(&timer_lock, flags);
			do {
				del_timer(&timerlist);
				data = inb(io + UART_RX);
				curr_time = ktime_get();
				delt = min_t(unsigned long,
					     ktime_us_delta(last, curr_time),
					     IR_MAX_DURATION);
				deltintr = min_t(unsigned long,
						 ktime_us_delta(last_intr_time,
								curr_time),
						 IR_MAX_DURATION);
				dev_dbg(&sir_ir_dev->dev, "t %lu, d %d\n",
					deltintr, (int)data);
				/*
				 * if nothing came in last X cycles,
				 * it was gap
				 */
				if (deltintr > TIME_CONST * threshold) {
					if (last_value) {
						dev_dbg(&sir_ir_dev->dev, "GAP\n");
						/* simulate signal change */
						add_read_queue(last_value,
							       delt -
							       deltintr);
						last_value = 0;
						last = last_intr_time;
						delt = deltintr;
					}
				}
				data = 1;
				if (data ^ last_value) {
					/*
					 * deltintr > 2*TIME_CONST, remember?
					 * the other case is timeout
					 */
					add_read_queue(last_value,
						       delt - TIME_CONST);
					last_value = data;
					last = curr_time;
					last = ktime_sub_us(last,
							    TIME_CONST);
				}
				last_intr_time = curr_time;
				if (data) {
					/*
					 * start timer for end of
					 * sequence detection
					 */
					timerlist.expires = jiffies +
								SIR_TIMEOUT;
					add_timer(&timerlist);
				}

				lsr = inb(io + UART_LSR);
			} while (lsr & UART_LSR_DR); /* data ready */
			spin_unlock_irqrestore(&timer_lock, flags);
			break;
		default:
			break;
		}
	}
	ir_raw_event_handle(rcdev);
	return IRQ_RETVAL(IRQ_HANDLED);
}