linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mauro Carvalho Chehab <mchehab@infradead.org>
To: Jon Smirl <jonsmirl@gmail.com>
Cc: "David Härdeman" <david@hardeman.nu>,
	"Andy Walls" <awalls@md.metrocast.net>,
	linux-input@vger.kernel.org, linux-media@vger.kernel.org
Subject: Re: [RFC] Teach drivers/media/IR/ir-raw-event.c to use durations
Date: Wed, 07 Apr 2010 10:29:14 -0300	[thread overview]
Message-ID: <4BBC88AA.4030808@infradead.org> (raw)
In-Reply-To: <j2g9e4733911004070611je836445apb6527b4e2d8137fb@mail.gmail.com>

Jon Smirl wrote:
> I had to rework this portion of code several times in the IR code I posted.
> 
> I had the core provide input_ir_queue() which was legal to call from
> interrupt context. Calling from interrupt context was an important
> aspect I missed in the first versions. I made this a common routine so
> that the code didn't get copied into all of the drivers. This code
> should have used kfifo but I didn't know about kfifo.
> 
>>> The question is though, is the kfifo and work handler really
> necessary?
> 
> Yes, otherwise it will get duplicated into all of the drivers that run
> in interrupt context like this GPIO one. Put this common code into the
> core so that the individual drivers writers don't mess it up.
> 
> void input_ir_queue(struct input_dev *dev, int sample)
> {
> 	unsigned int next;
> 
> 	spin_lock(dev->ir->queue.lock);
> 	dev->ir->queue.samples[dev->ir->queue.head] = sample;
> 	next = dev->ir->queue.head + 1;
> 	dev->ir->queue.head = (next >= MAX_SAMPLES ? 0 : next);
> 	spin_unlock(dev->ir->queue.lock);
> 
> 	schedule_work(&dev->ir->work);
> }

The big advantage of using kfifo is that you don't need to use a spinlock, if
there's just one consumer of the event. On the implementation I did, just
one code writes to the kfifo (the driver) and just one code reads from the 
kfifo, and multiplexing the data to the several decoders (and lirc_dev). 
So, no locks.

> 
> My GPIO implementation simply call input_it_queue() with the timing
> data. I collapsed multiple long space interrupts into one very long
> space. If you are using protocol engines, there is no need to detect
> the long trailing space. The protocol engine will trigger on the last
> pulse of the signal.
> 
> On the other hand, LIRC in user space needs the last long space to
> know when to flush the buffer from kernel space into user space. The
> timeout for this flush should be implemented in the LIRC compatibility
> driver, not ir-core. In this case my GPIO driver doesn't ever generate
> an event for the long space at the end of the message (because it
> doesn't end). Instead the LIRC compatibility layer should start a
> timer and flush when no data has been received for 200ms or whatever.

Agreed.

> static irqreturn_t dpeak_ir_irq(int irq, void *_ir)
> {
> 	struct ir_gpt *ir_gpt = _ir;
> 	int sample, count, delta, bit, wrap;
> 
> 	sample = in_be32(&ir_gpt->regs->status);
> 	out_be32(&ir_gpt->regs->status, 0xF);
> 
> 	count = sample >> 16;
> 	wrap = (sample >> 12) & 7;
> 	bit = (sample >> 8) & 1;
> 
> 	delta = count - ir_gpt->previous;
> 	delta += wrap * 0x10000;
> 
> 	ir_gpt->previous = count;
> 
> 	if (bit)
> 		delta = -delta;
> 
> 	input_ir_queue(ir_gpt->input, delta);
> 
> 	return IRQ_HANDLED;
> }
> 
> For MSMCE I converted their format back into simple delays and fed it
> into input_ir_queue(). This was not done in interrupt context because
> of the way USB works. input_ir_queue() doesn't care - it works
> correctly when called from either context.
> 
> 				if (ir->last.command == 0x80) {
> 					bit = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
> 					delta = (ir->buf_in[i] & MCE_PULSE_MASK) * MCE_TIME_BASE;
> 
> 					if ((ir->buf_in[i] & MCE_PULSE_MASK) == 0x7f) {
> 						if (ir->last.bit == bit)
> 							ir->last.delta += delta;
> 						else {
> 							ir->last.delta = delta;
> 							ir->last.bit = bit;
> 						}
> 						continue;
> 					}
> 					delta += ir->last.delta;
> 					ir->last.delta = 0;
> 					ir->last.bit = bit;
> 
> 					dev_dbg(&ir->usbdev->dev, "bit %d delta %d\n", bit, delta);
> 					if (bit)
> 						delta = -delta;
> 
> 					input_ir_queue(ir->input, delta);
> 				}
> 
> These delay messages are then fed into the protocol engines which
> process the pulses in parallel. Processing in parallel works, because
> that's how IR receivers work. When you shine a remote on an equipment
> rack, all of the equipment sees the command in parallel. The protocols
> are designed so that parallel decode works properly.

On the implementation I did, each event is passed to each decoder serialized (yet, as one keystroke
is a series of events, it behaves as if they are processed in parallel). We might create separate
kthreads for each decoder, and use a spinlock at kfifo, but I suspect that the end result will be
very close and we'll have more threads interfering at the samples collect, especially on those
(broken) hardware that don't have IRQ's to indicate a state transition, so the driver needs
to poll the samples.

-- 

Cheers,
Mauro

  reply	other threads:[~2010-04-07 13:29 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20100406104410.710253548@hardeman.nu>
2010-04-06 10:48 ` [RFC] Teach drivers/media/IR/ir-raw-event.c to use durations David Härdeman
2010-04-06 14:26   ` Mauro Carvalho Chehab
2010-04-07 10:20     ` Andy Walls
2010-04-07 11:42       ` David Härdeman
2010-04-07 13:11         ` Jon Smirl
2010-04-07 13:29           ` Mauro Carvalho Chehab [this message]
2010-04-07 15:03             ` Jon Smirl
2010-04-08  0:28         ` Andy Walls
2010-04-07 11:09     ` David Härdeman
2010-04-07 13:17       ` Mauro Carvalho Chehab

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4BBC88AA.4030808@infradead.org \
    --to=mchehab@infradead.org \
    --cc=awalls@md.metrocast.net \
    --cc=david@hardeman.nu \
    --cc=jonsmirl@gmail.com \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).