static irqreturn_t ite_cir_isr(int irq, void *data) { struct ite_dev *dev = data; unsigned long flags; irqreturn_t ret = IRQ_RETVAL(IRQ_NONE); u8 rx_buf[ITE_RX_FIFO_LEN]; int rx_bytes; int iflags; ite_dbg_verbose("%s firing", __func__); spin_lock_irqsave(&dev->lock, flags); iflags = dev->params.get_irq_causes(dev); if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) { rx_bytes = dev->params.get_rx_bytes(dev, rx_buf, ITE_RX_FIFO_LEN); if (rx_bytes > 0) { spin_unlock_irqrestore(&dev-> lock, flags); ite_decode_bytes(dev, rx_buf, rx_bytes); spin_lock_irqsave(&dev->lock, flags); ret = IRQ_RETVAL(IRQ_HANDLED); } } else if (iflags & ITE_IRQ_TX_FIFO) { ite_dbg_verbose("got interrupt for TX FIFO"); wake_up_interruptible(&dev->tx_queue); ret = IRQ_RETVAL(IRQ_HANDLED); } spin_unlock_irqrestore(&dev->lock, flags); ite_dbg_verbose("%s done returning %d", __func__, (int)ret); return ret; }
/* decode raw bytes as received by the hardware, and push them to the ir-core * layer */ static void ite_decode_bytes(struct ite_dev *dev, const u8 * data, int length) { u32 sample_period; unsigned long *ldata; unsigned int next_one, next_zero, size; DEFINE_IR_RAW_EVENT(ev); if (length == 0) return; sample_period = dev->params.sample_period; ldata = (unsigned long *)data; size = length << 3; next_one = find_next_bit_le(ldata, size, 0); if (next_one > 0) { ev.pulse = true; ev.duration = ITE_BITS_TO_NS(next_one, sample_period); ir_raw_event_store_with_filter(dev->rdev, &ev); } while (next_one < size) { next_zero = find_next_zero_bit_le(ldata, size, next_one + 1); ev.pulse = false; ev.duration = ITE_BITS_TO_NS(next_zero - next_one, sample_period); ir_raw_event_store_with_filter(dev->rdev, &ev); if (next_zero < size) { next_one = find_next_bit_le(ldata, size, next_zero + 1); ev.pulse = true; ev.duration = ITE_BITS_TO_NS(next_one - next_zero, sample_period); ir_raw_event_store_with_filter (dev->rdev, &ev); } else next_one = size; } ir_raw_event_handle(dev->rdev); ite_dbg_verbose("decoded %d bytes.", length); }
/* interrupt service routine for incoming and outgoing CIR data */ static irqreturn_t ite_cir_isr(int irq, void *data) { struct ite_dev *dev = data; unsigned long flags; irqreturn_t ret = IRQ_RETVAL(IRQ_NONE); u8 rx_buf[ITE_RX_FIFO_LEN]; int rx_bytes; int iflags; ite_dbg_verbose("%s firing", __func__); /* grab the spinlock */ spin_lock_irqsave(&dev->lock, flags); /* read the interrupt flags */ iflags = dev->params.get_irq_causes(dev); /* check for the receive interrupt */ if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) { /* read the FIFO bytes */ rx_bytes = dev->params.get_rx_bytes(dev, rx_buf, ITE_RX_FIFO_LEN); if (rx_bytes > 0) { /* drop the spinlock, since the ir-core layer * may call us back again through * ite_s_idle() */ spin_unlock_irqrestore(&dev-> lock, flags); /* decode the data we've just received */ ite_decode_bytes(dev, rx_buf, rx_bytes); /* reacquire the spinlock */ spin_lock_irqsave(&dev->lock, flags); /* mark the interrupt as serviced */ ret = IRQ_RETVAL(IRQ_HANDLED); } } else if (iflags & ITE_IRQ_TX_FIFO) { /* FIFO space available interrupt */ ite_dbg_verbose("got interrupt for TX FIFO"); /* wake any sleeping transmitter */ wake_up_interruptible(&dev->tx_queue); /* mark the interrupt as serviced */ ret = IRQ_RETVAL(IRQ_HANDLED); } /* drop the spinlock */ spin_unlock_irqrestore(&dev->lock, flags); ite_dbg_verbose("%s done returning %d", __func__, (int)ret); return ret; }