Re: [RFC] Teach drivers/media/IR/ir-raw-event.c to use durations

2010-04-07 Thread Andy Walls
On Tue, 2010-04-06 at 11:26 -0300, Mauro Carvalho Chehab wrote:
 Hi David,
 

 I won't comment every single bits of the change, since we're more interested 
 on the conceptual
 aspects.
 
  -int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type 
  type)
 
 Don't remove the raw_event_store. It is needed by the hardware that gets 
 events from
 IRQ/polling. For sure another interface is needed, for the cases where the 
 hardware pass their
 own time measure, like cx18 
 (http://linuxtv.org/hg/~awalls/cx23885-ir2/rev/2cfef53b95a2).
 
 For those, we need something like:
 
 int ir_raw_event_time_store(struct input_dev *input_dev, enum raw_event_type 
 type, u32 nsecs)
 
 Where, instead of using ktime_get_ts(), it will use the timing provided by 
 the hardware.

Just to clarify what Conexant hardware, and my current driver for it, is
capable of:

1. It provides raw pulse (and space) width measurements.

2. Those measurements can have very high resoltuion (~37 ns IIRC) or
very low resolution (usec or msec IIRC) depending on how the hardware
clock dividers are set up.

3. The hardware provides a timeout when the measurment timer overflows,
meaning that no edge happened for a very long time.  This generates a
special overflow measurment value and a receiver timeout interrupt.

4. The hardware has an 8 measurement deep FIFO, which the driver starts
to drain whenever it is half full (i.e. pulse measurement data is
delayed).  This happens in response to a hardware FIFO service request
interrupt.

5. The hardware FIFO is drained by the driver whenever an interrupt is
received and the available measruement data is placed into a kfifo().
This will then signal a work handler that it has work to do.

6. Measurements are scaled to standard time units (i.e. ns) by the
driver when they are read out of the kfifo() by a work handler.  (No
sense in doing time conversions in an interrupt handler).

7. The work handler then begins passing whatever measurements it has,
one at a time, over to a pulse stream decoder.

8. If the pulse stream decoder actually decodes something, it is passed
over to the input subsystem.

I suspect this device's behavior is much closer to what the MCE-USB
device does, than the raw GPIO handlers, but I don't really know the
MCE-USB.

Regards,
Andy

--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] Teach drivers/media/IR/ir-raw-event.c to use durations

2010-04-07 Thread David Härdeman
On Tue, Apr 06, 2010 at 11:26:35AM -0300, Mauro Carvalho Chehab wrote:
 Hi David,
 
 Em Tue, 6 Apr 2010 12:48:11 +0200
 David Härdeman da...@hardeman.nu escreveu:
 
  Content-Type: text/plain; charset=us-ascii
  Content-Disposition: inline; filename=use-pulse-space-timings-in-ir-raw
 
 Thunderbird 2 really don't like this. It considers the entire body as a file, 
 and
 refuses to quote it.

Never had people complain when I use quilt before but I'll see what I 
can do.

  drivers/media/IR/ir-raw-event.c is currently written with the assumption 
  that
  all raw hardware will generate events only on state change (i.e. when
  a pulse or space starts).
  
  However, some hardware (like mceusb, probably the most popular IR receiver
  out there) only generates duration data (and that data is buffered so using
  any kind of timing on the data is futile).
 
 Am I understanding right and this hardware is not capable of indicating if 
 the 
 event is a pulse or a space? It seems hard to auto-detect what is pulse or 
 space,
 but IMO such code should belong to mceusb driver and not to the decoders.

No, the driver for mceusb sends a usb packet which contains a couple of 
pulse/space durations in the form of signed integers representing pulse 
(positive) and space (negative) durations in microseconds. It's a pretty 
common arrangement. winbond-cir also has a mode (which is the one I'm 
planning on using in the future) where pulse/space durations are 
accumulated in the UART buffer and an IRQ is generated once the buffer 
level reaches a threshold.

 Based on the code changes you did, I suspect that one of the things the 
 hardware
 provides is a machine reset state, right? If you just need to add a code to 
 reset
 the state machines, this could be done as easily as adding an event at kfifo 
 with
 IR_STOP_EVENT. A three line addition at the decoders event handler would be 
 enough
 to use it to reset the state machine:
 
   if (ev-type  IR_STOP_EVENT) {
   data-state = STATE_INACTIVE;
   return;
   }
 
 This event were not added yet, since no hardware currently ported needs it. 
 Eventually,
 we may rename it to IR_RESET_STATE, if you think it is clearer.

Not a particular state per se, I just added a function which the 
hardware can use to reset the state machines when necessary (think 
hardware reset, suspend/resume, switching from RX to TX and back again, 
etc).

I think this:

/* Hardware has been reset, notify ir-core */
ir_raw_event_reset(input_dev);

is a hell lot clearer than this (your current code):

/* Hardware has been reset, notify ir-core */
rc = ir_raw_event_store(input_dev, IR_STOP_EVENT);
if (rc) {
/* Uh oh, what do we do now? */
...
}
rc = ir_raw_event_handle(input_dev);
if (rc) {
/* Not again... */
...
}

  This patch (which is not tested since I haven't yet converted a 
  driver for
  any of my hardware to ir-core yet, will do soon) is a RFC on my proposed
  interface change...once I get the green light on the interface change itself
  I'll make sure that the decoders actually work :)
 
 Yes, better to discuss before changing everything ;)

  The rc5 decoder has also gained rc5x support and the use of kfifo's 
  for
  intermediate storage is gone (since there is no need for it).
 
 The RC-5X addition is welcome, but the better is to add it as a separate 
 patch. 

Using durations (instead of a combination of struct timespec and enum 
raw_event_type) as the argument to the decoder necessitates rewriting 
most of the decoders, so it seemed like a good time to add it. RC5X or 
not will anyway only mean a couple of lines of difference but I can send 
it as a separate patch if that helps you.
 
 I won't comment every single bits of the change, since we're more interested 
 on the conceptual
 aspects.
 
  -int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type 
  type)
 
 Don't remove the raw_event_store. It is needed by the hardware that gets 
 events from
 IRQ/polling.

See the comments for kfifo below.

 For sure another interface is needed, for the cases where the hardware 
 pass their
 own time measure, like cx18 
 (http://linuxtv.org/hg/~awalls/cx23885-ir2/rev/2cfef53b95a2).
 
 For those, we need something like:
 
 int ir_raw_event_time_store(struct input_dev *input_dev, enum raw_event_type 
 type, u32 nsecs)
 
 Where, instead of using ktime_get_ts(), it will use the timing provided by 
 the hardware.

Um, this sounds exactly like ir_raw_event_duration() which was the main 
point of my patch.
 
   
  -int ir_raw_event_handle(struct input_dev *input_dev)
  +/**
  + * ir_raw_event_edge() - notify raw ir decoders of the start of a 
  pulse/space
  + * @input_dev: the struct input_dev device descriptor
  + * @type:  the type of the event that has occurred
  + *
  + * This routine is used to notify the raw ir 

Re: [RFC] Teach drivers/media/IR/ir-raw-event.c to use durations

2010-04-07 Thread David Härdeman
On Wed, Apr 07, 2010 at 06:20:07AM -0400, Andy Walls wrote:
 On Tue, 2010-04-06 at 11:26 -0300, Mauro Carvalho Chehab wrote:
  I won't comment every single bits of the change, since we're more 
  interested on the conceptual
  aspects.
  
   -int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type 
   type)
  
  Don't remove the raw_event_store. It is needed by the hardware that gets 
  events from
  IRQ/polling. For sure another interface is needed, for the cases where the 
  hardware pass their
  own time measure, like cx18 
  (http://linuxtv.org/hg/~awalls/cx23885-ir2/rev/2cfef53b95a2).
  
  For those, we need something like:
  
  int ir_raw_event_time_store(struct input_dev *input_dev, enum 
  raw_event_type type, u32 nsecs)
  
  Where, instead of using ktime_get_ts(), it will use the timing provided by 
  the hardware.
 
 Just to clarify what Conexant hardware, and my current driver for it, is
 capable of:
 
 1. It provides raw pulse (and space) width measurements.
 
 2. Those measurements can have very high resoltuion (~37 ns IIRC) or
 very low resolution (usec or msec IIRC) depending on how the hardware
 clock dividers are set up.
 
 3. The hardware provides a timeout when the measurment timer overflows,
 meaning that no edge happened for a very long time.  This generates a
 special overflow measurment value and a receiver timeout interrupt.
 
 4. The hardware has an 8 measurement deep FIFO, which the driver starts
 to drain whenever it is half full (i.e. pulse measurement data is
 delayed).  This happens in response to a hardware FIFO service request
 interrupt.
 
 5. The hardware FIFO is drained by the driver whenever an interrupt is
 received and the available measruement data is placed into a kfifo().
 This will then signal a work handler that it has work to do.
 
 6. Measurements are scaled to standard time units (i.e. ns) by the
 driver when they are read out of the kfifo() by a work handler.  (No
 sense in doing time conversions in an interrupt handler).
 
 7. The work handler then begins passing whatever measurements it has,
 one at a time, over to a pulse stream decoder.
 
 8. If the pulse stream decoder actually decodes something, it is passed
 over to the input subsystem.
 
 I suspect this device's behavior is much closer to what the MCE-USB
 device does, than the raw GPIO handlers, but I don't really know the
 MCE-USB.

This sounds very similar to winbond-cir (the hardware parts that is, 
basically until and including item 5, line 1). The mceusb HW does 
something similar...it sends usb packets with a couple of pulse/space 
duration measurements (of 50us resolution IIRC)...and it automatically 
enters an inactive state after 1 us of silence.

The ir_raw_event_duration() function of my patch is intended for exactly 
this kind of hardware (which I mentioned in my reply to Mauro which I 
just sent out).

The question is though, is the kfifo and work handler really 
necessary?

-- 
David Härdeman
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] Teach drivers/media/IR/ir-raw-event.c to use durations

2010-04-07 Thread Jon Smirl
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);
}

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.

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 * 0x1;

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.

-- 
Jon Smirl
jonsm...@gmail.com
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] Teach drivers/media/IR/ir-raw-event.c to use durations

2010-04-07 Thread Mauro Carvalho Chehab
David Härdeman wrote:
 On Tue, Apr 06, 2010 at 11:26:35AM -0300, Mauro Carvalho Chehab wrote:
 Hi David,

 Em Tue, 6 Apr 2010 12:48:11 +0200
 David Härdeman da...@hardeman.nu escreveu:

 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline; filename=use-pulse-space-timings-in-ir-raw
 Thunderbird 2 really don't like this. It considers the entire body as a 
 file, and
 refuses to quote it.
 
 Never had people complain when I use quilt before but I'll see what I 
 can do.

Thanks. I'll also see if I can get some extension to thunderbird to fix it, or 
consider
moving (again) to another emailer.

 drivers/media/IR/ir-raw-event.c is currently written with the assumption 
 that
 all raw hardware will generate events only on state change (i.e. when
 a pulse or space starts).

 However, some hardware (like mceusb, probably the most popular IR receiver
 out there) only generates duration data (and that data is buffered so using
 any kind of timing on the data is futile).
 Am I understanding right and this hardware is not capable of indicating if 
 the 
 event is a pulse or a space? It seems hard to auto-detect what is pulse or 
 space,
 but IMO such code should belong to mceusb driver and not to the decoders.
 
 No, the driver for mceusb sends a usb packet which contains a couple of 
 pulse/space durations in the form of signed integers representing pulse 
 (positive) and space (negative) durations in microseconds. It's a pretty 
 common arrangement. winbond-cir also has a mode (which is the one I'm 
 planning on using in the future) where pulse/space durations are 
 accumulated in the UART buffer and an IRQ is generated once the buffer 
 level reaches a threshold.

Ok.

 Based on the code changes you did, I suspect that one of the things the 
 hardware
 provides is a machine reset state, right? If you just need to add a code 
 to reset
 the state machines, this could be done as easily as adding an event at kfifo 
 with
 IR_STOP_EVENT. A three line addition at the decoders event handler would be 
 enough
 to use it to reset the state machine:

  if (ev-type  IR_STOP_EVENT) {
  data-state = STATE_INACTIVE;
  return;
  }

 This event were not added yet, since no hardware currently ported needs it. 
 Eventually,
 we may rename it to IR_RESET_STATE, if you think it is clearer.
 
 Not a particular state per se, I just added a function which the 
 hardware can use to reset the state machines when necessary (think 
 hardware reset, suspend/resume, switching from RX to TX and back again, 
 etc).
 
 I think this:
 
   /* Hardware has been reset, notify ir-core */
   ir_raw_event_reset(input_dev);
 
 is a hell lot clearer than this (your current code):
 
   /* Hardware has been reset, notify ir-core */
   rc = ir_raw_event_store(input_dev, IR_STOP_EVENT);
   if (rc) {
   /* Uh oh, what do we do now? */
   ...

Ok. What about:

#define ir_raw_event_reset(input_dev) ir_raw_event_store(input_dev, 
IR_STOP_EVENT)

This will save some code and avoid one more symbol to be exported.

   }
   rc = ir_raw_event_handle(input_dev);
   if (rc) {
   /* Not again... */
   ...
   }
 
 This patch (which is not tested since I haven't yet converted a 
 driver for
 any of my hardware to ir-core yet, will do soon) is a RFC on my proposed
 interface change...once I get the green light on the interface change itself
 I'll make sure that the decoders actually work :)
 Yes, better to discuss before changing everything ;)

 The rc5 decoder has also gained rc5x support and the use of kfifo's 
 for
 intermediate storage is gone (since there is no need for it).
 The RC-5X addition is welcome, but the better is to add it as a separate 
 patch. 
 
 Using durations (instead of a combination of struct timespec and enum 
 raw_event_type) as the argument to the decoder necessitates rewriting 
 most of the decoders, so it seemed like a good time to add it. RC5X or 
 not will anyway only mean a couple of lines of difference but I can send 
 it as a separate patch if that helps you.

Ok, thanks.

 I won't comment every single bits of the change, since we're more interested 
 on the conceptual
 aspects.

 -int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type 
 type)
 Don't remove the raw_event_store. It is needed by the hardware that gets 
 events from
 IRQ/polling.
 
 See the comments for kfifo below.
 
 For sure another interface is needed, for the cases where the hardware 
 pass their
 own time measure, like cx18 
 (http://linuxtv.org/hg/~awalls/cx23885-ir2/rev/2cfef53b95a2).

 For those, we need something like:

 int ir_raw_event_time_store(struct input_dev *input_dev, enum raw_event_type 
 type, u32 nsecs)

 Where, instead of using ktime_get_ts(), it will use the timing provided by 
 the hardware.
 
 Um, this sounds exactly like ir_raw_event_duration() which was the main 
 point of my patch.

The better 

Re: [RFC] Teach drivers/media/IR/ir-raw-event.c to use durations

2010-04-07 Thread Mauro Carvalho Chehab
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 * 0x1;
 
   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 

Re: [RFC] Teach drivers/media/IR/ir-raw-event.c to use durations

2010-04-07 Thread Jon Smirl
On Wed, Apr 7, 2010 at 9:29 AM, Mauro Carvalho Chehab
mche...@infradead.org wrote:
 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.

Polling should be the driver's problem. They can set up a timer
interrupt and do it that way. Do all of the protocols have a long
enough lead one for a timer tick to catch them? If so, look for it in
the timer event, then go into a polling loop. You'd be way better off
buying new hardware since your video is going to stop while this
pooling loop runs. Do modern serial ports interrupt on DTR or whatever
those Iguana devices use? What is an example of a polled input device?
I can't think of one, even IR diode on mic input is interrupt driven
(that require a special ALSA driver to pass the data into RC core).

No need to use different kthreads for each protocol decoder, but don't
lock up the default kernel thread waiting for a user space response.
What I meant by parallel was that pulses are fed one at a time into
each of the decoders, don't wait for a long space and then feed the
entire message into the decoders.


 --

 Cheers,
 Mauro




-- 
Jon Smirl
jonsm...@gmail.com
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] Teach drivers/media/IR/ir-raw-event.c to use durations

2010-04-06 Thread Mauro Carvalho Chehab
Hi David,

Em Tue, 6 Apr 2010 12:48:11 +0200
David Härdeman da...@hardeman.nu escreveu:

 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline; filename=use-pulse-space-timings-in-ir-raw

Thunderbird 2 really don't like this. It considers the entire body as a file, 
and
refuses to quote it.

 drivers/media/IR/ir-raw-event.c is currently written with the assumption that
 all raw hardware will generate events only on state change (i.e. when
 a pulse or space starts).
 
 However, some hardware (like mceusb, probably the most popular IR receiver
 out there) only generates duration data (and that data is buffered so using
 any kind of timing on the data is futile).

Am I understanding right and this hardware is not capable of indicating if the 
event is a pulse or a space? It seems hard to auto-detect what is pulse or 
space,
but IMO such code should belong to mceusb driver and not to the decoders.

Based on the code changes you did, I suspect that one of the things the hardware
provides is a machine reset state, right? If you just need to add a code to 
reset
the state machines, this could be done as easily as adding an event at kfifo 
with
IR_STOP_EVENT. A three line addition at the decoders event handler would be 
enough
to use it to reset the state machine:

if (ev-type  IR_STOP_EVENT) {
data-state = STATE_INACTIVE;
return;
}

This event were not added yet, since no hardware currently ported needs it. 
Eventually,
we may rename it to IR_RESET_STATE, if you think it is clearer.

 This patch (which is not tested since I haven't yet converted a driver for
 any of my hardware to ir-core yet, will do soon) is a RFC on my proposed
 interface change...once I get the green light on the interface change itself
 I'll make sure that the decoders actually work :)

Yes, better to discuss before changing everything ;)

 The rc5 decoder has also gained rc5x support and the use of kfifo's for
 intermediate storage is gone (since there is no need for it).

The RC-5X addition is welcome, but the better is to add it as a separate patch. 

I won't comment every single bits of the change, since we're more interested on 
the conceptual
aspects.

 -int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type)

Don't remove the raw_event_store. It is needed by the hardware that gets events 
from
IRQ/polling. For sure another interface is needed, for the cases where the 
hardware pass their
own time measure, like cx18 
(http://linuxtv.org/hg/~awalls/cx23885-ir2/rev/2cfef53b95a2).

For those, we need something like:

int ir_raw_event_time_store(struct input_dev *input_dev, enum raw_event_type 
type, u32 nsecs)

Where, instead of using ktime_get_ts(), it will use the timing provided by the 
hardware.

  
 -int ir_raw_event_handle(struct input_dev *input_dev)
 +/**
 + * ir_raw_event_edge() - notify raw ir decoders of the start of a pulse/space
 + * @input_dev:   the struct input_dev device descriptor
 + * @type:the type of the event that has occurred
 + *
 + * This routine is used to notify the raw ir decoders on the beginning of an
 + * ir pulse or space (or the start/end of ir reception). This is used by
 + * hardware which does not provide durations directly but only interrupts
 + * (or similar events) on state change.
 + */
 +void ir_raw_event_edge(struct input_dev *input_dev, enum raw_event_type type)
  {
 - struct ir_input_dev *ir = input_get_drvdata(input_dev);
 - int rc;
 - struct ir_raw_event ev;
 - int len, i;
 -
 - /*
 -  * Store the events into a temporary buffer. This allows calling more 
 than
 -  * one decoder to deal with the received data
 -  */
 - len = kfifo_len(ir-raw-kfifo) / sizeof(ev);
 - if (!len)
 - return 0;

The removal of kfifo is not a good idea. On several drivers, the event is 
generated during
IRQ time, or on a very expensive polling loop. So, buffering is needed to 
release the
IRQ as soon as possible and not adding too much processing during polling.

 -
 - for (i = 0; i  len; i++) {
 - rc = kfifo_out(ir-raw-kfifo, ev, sizeof(ev));
 - if (rc != sizeof(ev)) {
 - IR_dprintk(1, overflow error: received %d instead of 
 %zd\n,
 -rc, sizeof(ev));
 - return -EINVAL;
 - }
 - IR_dprintk(2, event type %d, time before event: %07luus\n,
 - ev.type, (ev.delta.tv_nsec + 500) / 1000);
 - rc = RUN_DECODER(decode, input_dev, ev);
 - }
 + struct ir_input_dev *ir = input_get_drvdata(input_dev);
 + ktime_t now;
 + s64 delta; /* us */
 +
 + if (!ir-raw)
 + return;
  
 - /*
 -  * Call all ir decoders. This allows decoding the same event with
 -  * more than one