All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Remaining patches in my queue for IR
@ 2010-10-16 22:56 ` Maxim Levitsky
  0 siblings, 0 replies; 12+ messages in thread
From: Maxim Levitsky @ 2010-10-16 22:56 UTC (permalink / raw)
  To: lirc-list
  Cc: Jarod Wilson, David Härdeman, mchehab, linux-input, linux-media

Hi,

This series is rebased on top of media_tree/staging/v2.6.37 only.
Really this time, sorry for cheating, last time :-)

The first patch like we agreed extends the raw packets.
It touches all drivers (except imon as it isn't a raw IR driver).
Code is compile tested with all drivers, 
and run tested with ENE and all receiver protocols
(except the streamzap rc5 flavour)
Since it also moves timeouts to lirc bridge, at least streazap driver
should have its timeout gap support removed. I am afraid to break the code
if I do so.

Other 2 patches are ENE specific, and don't touch anything else.

Please test other drivers.

Best regards,
	Maxim Levitsky


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 0/3] Remaining patches in my queue for IR
@ 2010-10-16 22:56 ` Maxim Levitsky
  0 siblings, 0 replies; 12+ messages in thread
From: Maxim Levitsky @ 2010-10-16 22:56 UTC (permalink / raw)
  To: lirc-list-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-media-u79uwXL29TY76Z2rM5mHXA,
	mchehab-wEGCiKHe2LqWVfeAwA7xHQ

Hi,

This series is rebased on top of media_tree/staging/v2.6.37 only.
Really this time, sorry for cheating, last time :-)

The first patch like we agreed extends the raw packets.
It touches all drivers (except imon as it isn't a raw IR driver).
Code is compile tested with all drivers, 
and run tested with ENE and all receiver protocols
(except the streamzap rc5 flavour)
Since it also moves timeouts to lirc bridge, at least streazap driver
should have its timeout gap support removed. I am afraid to break the code
if I do so.

Other 2 patches are ENE specific, and don't touch anything else.

Please test other drivers.

Best regards,
	Maxim Levitsky


------------------------------------------------------------------------------
Download new Adobe(R) Flash(R) Builder(TM) 4
The new Adobe(R) Flex(R) 4 and Flash(R) Builder(TM) 4 (formerly 
Flex(R) Builder(TM)) enable the development of rich applications that run
across multiple browsers and platforms. Download your free trials today!
http://p.sf.net/sfu/adobe-dev2dev

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/3] IR: extend ir_raw_event and do refactoring
@ 2010-10-16 22:56   ` Maxim Levitsky
  0 siblings, 0 replies; 12+ messages in thread
From: Maxim Levitsky @ 2010-10-16 22:56 UTC (permalink / raw)
  To: lirc-list
  Cc: Jarod Wilson, David Härdeman, mchehab, linux-input,
	linux-media, Maxim Levitsky

Add new event types for timeout & carrier report
Move timeout handling from ir_raw_event_store_with_filter to
ir-lirc-codec, where it is really needed.
Now lirc bridge ensures proper gap handling.
Extend lirc bridge for carrier & timeout reports

Note: all new ir_raw_event variables now should be initialized
like that: DEFINE_IR_RAW_EVENT(ev);

To clean an existing event, use init_ir_raw_event(&ev);

Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
Acked-by: Jarod Wilson <jarod@redhat.com>
---
 drivers/media/IR/ene_ir.c            |    4 +-
 drivers/media/IR/ir-core-priv.h      |   13 +++-
 drivers/media/IR/ir-jvc-decoder.c    |    5 +-
 drivers/media/IR/ir-lirc-codec.c     |  128 ++++++++++++++++++++++++----------
 drivers/media/IR/ir-nec-decoder.c    |    5 +-
 drivers/media/IR/ir-raw-event.c      |   45 ++++--------
 drivers/media/IR/ir-rc5-decoder.c    |    5 +-
 drivers/media/IR/ir-rc5-sz-decoder.c |    5 +-
 drivers/media/IR/ir-rc6-decoder.c    |    5 +-
 drivers/media/IR/ir-sony-decoder.c   |    5 +-
 drivers/media/IR/mceusb.c            |    3 +-
 drivers/media/IR/nuvoton-cir.c       |    5 +-
 drivers/media/IR/streamzap.c         |    6 +-
 include/media/ir-core.h              |   40 +++++++++--
 14 files changed, 181 insertions(+), 93 deletions(-)

diff --git a/drivers/media/IR/ene_ir.c b/drivers/media/IR/ene_ir.c
index 9f9afe7..8639621 100644
--- a/drivers/media/IR/ene_ir.c
+++ b/drivers/media/IR/ene_ir.c
@@ -697,7 +697,7 @@ static irqreturn_t ene_isr(int irq, void *data)
 	unsigned long flags;
 	irqreturn_t retval = IRQ_NONE;
 	struct ene_device *dev = (struct ene_device *)data;
-	struct ir_raw_event ev;
+	DEFINE_IR_RAW_EVENT(ev);
 
 	spin_lock_irqsave(&dev->hw_lock, flags);
 
@@ -898,7 +898,7 @@ static int ene_set_learning_mode(void *data, int enable)
 }
 
 /* outside interface: enable or disable idle mode */
-static void ene_rx_set_idle(void *data, int idle)
+static void ene_rx_set_idle(void *data, bool idle)
 {
 	struct ene_device *dev = (struct ene_device *)data;
 
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h
index 6830580..81c936b 100644
--- a/drivers/media/IR/ir-core-priv.h
+++ b/drivers/media/IR/ir-core-priv.h
@@ -88,6 +88,12 @@ struct ir_raw_event_ctrl {
 		struct ir_input_dev *ir_dev;
 		struct lirc_driver *drv;
 		int carrier_low;
+
+		ktime_t gap_start;
+		u64 gap_duration;
+		bool gap;
+		bool send_timeout_reports;
+
 	} lirc;
 };
 
@@ -115,9 +121,14 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
 		ev->duration -= duration;
 }
 
+/* Returns true if event is normal pulse/space event */
+static inline bool is_timing_event(struct ir_raw_event ev)
+{
+	return !ev.carrier_report && !ev.reset;
+}
+
 #define TO_US(duration)			DIV_ROUND_CLOSEST((duration), 1000)
 #define TO_STR(is_pulse)		((is_pulse) ? "pulse" : "space")
-#define IS_RESET(ev)			(ev.duration == 0)
 /*
  * Routines from ir-sysfs.c - Meant to be called only internally inside
  * ir-core
diff --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c
index 77a89c4..63dca6e 100644
--- a/drivers/media/IR/ir-jvc-decoder.c
+++ b/drivers/media/IR/ir-jvc-decoder.c
@@ -50,8 +50,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
 		return 0;
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 	}
 
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c
index 20ac9a4..1d9c6b0 100644
--- a/drivers/media/IR/ir-lirc-codec.c
+++ b/drivers/media/IR/ir-lirc-codec.c
@@ -32,6 +32,7 @@
 static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 {
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+	struct lirc_codec *lirc = &ir_dev->raw->lirc;
 	int sample;
 
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
@@ -40,21 +41,57 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
 		return -EINVAL;
 
-	if (IS_RESET(ev))
+	/* Packet start */
+	if (ev.reset)
 		return 0;
 
-	IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
-		   TO_US(ev.duration), TO_STR(ev.pulse));
+	/* Carrier reports */
+	if (ev.carrier_report) {
+		sample = LIRC_FREQUENCY(ev.carrier);
+
+	/* Packet end */
+	} else if (ev.timeout) {
+
+		if (lirc->gap)
+			return 0;
+
+		lirc->gap_start = ktime_get();
+		lirc->gap = true;
+		lirc->gap_duration = ev.duration;
+
+		if (!lirc->send_timeout_reports)
+			return 0;
+
+		sample = LIRC_TIMEOUT(ev.duration / 1000);
 
-	sample = ev.duration / 1000;
-	if (ev.pulse)
-		sample |= PULSE_BIT;
+	/* Normal sample */
+	} else {
+
+		if (lirc->gap) {
+			int gap_sample;
+
+			lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
+				lirc->gap_start));
+
+			/* Convert to ms and cap by LIRC_VALUE_MASK */
+			do_div(lirc->gap_duration, 1000);
+			lirc->gap_duration = min(lirc->gap_duration,
+							(u64)LIRC_VALUE_MASK);
+
+			gap_sample = LIRC_SPACE(lirc->gap_duration);
+			lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
+						(unsigned char *) &gap_sample);
+			lirc->gap = false;
+		}
+
+		sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
+					LIRC_SPACE(ev.duration / 1000);
+	}
 
 	lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
 			  (unsigned char *) &sample);
 	wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
 
-
 	return 0;
 }
 
@@ -102,7 +139,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	struct ir_input_dev *ir_dev;
 	int ret = 0;
 	void *drv_data;
-	__u32 val = 0;
+	__u32 val = 0, tmp;
 
 	lirc = lirc_get_pdata(filep);
 	if (!lirc)
@@ -130,22 +167,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	case LIRC_SET_SEND_MODE:
 		if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
 			return -EINVAL;
-		break;
+		return 0;
 
 	/* TX settings */
 	case LIRC_SET_TRANSMITTER_MASK:
-		if (ir_dev->props->s_tx_mask)
-			ret = ir_dev->props->s_tx_mask(drv_data, val);
-		else
+		if (!ir_dev->props->s_tx_mask)
 			return -EINVAL;
-		break;
+
+		return ir_dev->props->s_tx_mask(drv_data, val);
 
 	case LIRC_SET_SEND_CARRIER:
-		if (ir_dev->props->s_tx_carrier)
-			ir_dev->props->s_tx_carrier(drv_data, val);
-		else
+		if (!ir_dev->props->s_tx_carrier)
 			return -EINVAL;
-		break;
+
+		return ir_dev->props->s_tx_carrier(drv_data, val);
 
 	case LIRC_SET_SEND_DUTY_CYCLE:
 		if (!ir_dev->props->s_tx_duty_cycle)
@@ -154,39 +189,42 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		if (val <= 0 || val >= 100)
 			return -EINVAL;
 
-		ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val);
-		break;
+		return ir_dev->props->s_tx_duty_cycle(drv_data, val);
 
 	/* RX settings */
 	case LIRC_SET_REC_CARRIER:
-		if (ir_dev->props->s_rx_carrier_range)
-			ret = ir_dev->props->s_rx_carrier_range(
-				ir_dev->props->priv,
-				ir_dev->raw->lirc.carrier_low, val);
-		else
+		if (!ir_dev->props->s_rx_carrier_range)
 			return -ENOSYS;
 
-		if (!ret)
-			ir_dev->raw->lirc.carrier_low = 0;
-		break;
+		if (val <= 0)
+			return -EINVAL;
+
+		return ir_dev->props->s_rx_carrier_range(drv_data,
+			ir_dev->raw->lirc.carrier_low, val);
 
 	case LIRC_SET_REC_CARRIER_RANGE:
-		if (val >= 0)
-			ir_dev->raw->lirc.carrier_low = val;
-		break;
+		if (val <= 0)
+			return -EINVAL;
 
+		ir_dev->raw->lirc.carrier_low = val;
+		return 0;
 
 	case LIRC_GET_REC_RESOLUTION:
 		val = ir_dev->props->rx_resolution;
 		break;
 
 	case LIRC_SET_WIDEBAND_RECEIVER:
-		if (ir_dev->props->s_learning_mode)
-			return ir_dev->props->s_learning_mode(
-				ir_dev->props->priv, !!val);
-		else
+		if (!ir_dev->props->s_learning_mode)
 			return -ENOSYS;
 
+		return ir_dev->props->s_learning_mode(drv_data, !!val);
+
+	case LIRC_SET_MEASURE_CARRIER_MODE:
+		if (!ir_dev->props->s_carrier_report)
+			return -ENOSYS;
+
+		return ir_dev->props->s_carrier_report(drv_data, !!val);
+
 	/* Generic timeout support */
 	case LIRC_GET_MIN_TIMEOUT:
 		if (!ir_dev->props->max_timeout)
@@ -201,10 +239,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		break;
 
 	case LIRC_SET_REC_TIMEOUT:
-		if (val < ir_dev->props->min_timeout ||
-		    val > ir_dev->props->max_timeout)
-			return -EINVAL;
-		ir_dev->props->timeout = val * 1000;
+		if (!ir_dev->props->max_timeout)
+			return -ENOSYS;
+
+		tmp = val * 1000;
+
+		if (tmp < ir_dev->props->min_timeout ||
+			tmp > ir_dev->props->max_timeout)
+				return -EINVAL;
+
+		ir_dev->props->timeout = tmp;
+		break;
+
+	case LIRC_SET_REC_TIMEOUT_REPORTS:
+		lirc->send_timeout_reports = !!val;
 		break;
 
 	default:
@@ -280,6 +328,10 @@ static int ir_lirc_register(struct input_dev *input_dev)
 	if (ir_dev->props->s_learning_mode)
 		features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
 
+	if (ir_dev->props->s_carrier_report)
+		features |= LIRC_CAN_MEASURE_CARRIER;
+
+
 	if (ir_dev->props->max_timeout)
 		features |= LIRC_CAN_SET_REC_TIMEOUT;
 
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c
index d597421..70993f7 100644
--- a/drivers/media/IR/ir-nec-decoder.c
+++ b/drivers/media/IR/ir-nec-decoder.c
@@ -54,8 +54,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
 		return 0;
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 	}
 
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
index 119b567..0d59ef7 100644
--- a/drivers/media/IR/ir-raw-event.c
+++ b/drivers/media/IR/ir-raw-event.c
@@ -174,7 +174,7 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev,
 	if (ir->idle && !ev->pulse)
 		return 0;
 	else if (ir->idle)
-		ir_raw_event_set_idle(input_dev, 0);
+		ir_raw_event_set_idle(input_dev, false);
 
 	if (!raw->this_ev.duration) {
 		raw->this_ev = *ev;
@@ -187,48 +187,35 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev,
 
 	/* Enter idle mode if nessesary */
 	if (!ev->pulse && ir->props->timeout &&
-		raw->this_ev.duration >= ir->props->timeout)
-		ir_raw_event_set_idle(input_dev, 1);
+		raw->this_ev.duration >= ir->props->timeout) {
+		ir_raw_event_set_idle(input_dev, true);
+	}
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
 
-void ir_raw_event_set_idle(struct input_dev *input_dev, int idle)
+/**
+ * ir_raw_event_set_idle() - hint the ir core if device is receiving
+ * IR data or not
+ * @input_dev: the struct input_dev device descriptor
+ * @idle: the hint value
+ */
+void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle)
 {
 	struct ir_input_dev *ir = input_get_drvdata(input_dev);
 	struct ir_raw_event_ctrl *raw = ir->raw;
-	ktime_t now;
-	u64 delta;
 
-	if (!ir->props)
+	if (!ir->props || !ir->raw)
 		return;
 
-	if (!ir->raw)
-		goto out;
+	IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");
 
 	if (idle) {
-		IR_dprintk(2, "enter idle mode\n");
-		raw->last_event = ktime_get();
-	} else {
-		IR_dprintk(2, "exit idle mode\n");
-
-		now = ktime_get();
-		delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));
-
-		WARN_ON(raw->this_ev.pulse);
-
-		raw->this_ev.duration =
-			min(raw->this_ev.duration + delta,
-						(u64)IR_MAX_DURATION);
-
+		raw->this_ev.timeout = true;
 		ir_raw_event_store(input_dev, &raw->this_ev);
-
-		if (raw->this_ev.duration == IR_MAX_DURATION)
-			ir_raw_event_reset(input_dev);
-
-		raw->this_ev.duration = 0;
+		init_ir_raw_event(&raw->this_ev);
 	}
-out:
+
 	if (ir->props->s_idle)
 		ir->props->s_idle(ir->props->priv, idle);
 	ir->idle = idle;
diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c
index df4770d..572ed4c 100644
--- a/drivers/media/IR/ir-rc5-decoder.c
+++ b/drivers/media/IR/ir-rc5-decoder.c
@@ -55,8 +55,9 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
         if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
                 return 0;
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 	}
 
diff --git a/drivers/media/IR/ir-rc5-sz-decoder.c b/drivers/media/IR/ir-rc5-sz-decoder.c
index 68f11d6..7c41350 100644
--- a/drivers/media/IR/ir-rc5-sz-decoder.c
+++ b/drivers/media/IR/ir-rc5-sz-decoder.c
@@ -51,8 +51,9 @@ static int ir_rc5_sz_decode(struct input_dev *input_dev, struct ir_raw_event ev)
         if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5_SZ))
                 return 0;
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 	}
 
diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c
index f1624b8..d25da91 100644
--- a/drivers/media/IR/ir-rc6-decoder.c
+++ b/drivers/media/IR/ir-rc6-decoder.c
@@ -85,8 +85,9 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
 		return 0;
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 	}
 
diff --git a/drivers/media/IR/ir-sony-decoder.c b/drivers/media/IR/ir-sony-decoder.c
index b9074f0..2d15730 100644
--- a/drivers/media/IR/ir-sony-decoder.c
+++ b/drivers/media/IR/ir-sony-decoder.c
@@ -48,8 +48,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
 		return 0;
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 	}
 
diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c
index bc620e1..6825da5 100644
--- a/drivers/media/IR/mceusb.c
+++ b/drivers/media/IR/mceusb.c
@@ -660,7 +660,7 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
 
 static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 {
-	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
+	DEFINE_IR_RAW_EVENT(rawir);
 	int i, start_index = 0;
 	u8 hdr = MCE_CONTROL_HEADER;
 
@@ -997,6 +997,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
 	ir->len_in = maxp;
 	ir->flags.microsoft_gen1 = is_microsoft_gen1;
 	ir->flags.tx_mask_inverted = tx_mask_inverted;
+	init_ir_raw_event(&ir->rawir);
 
 	/* Saving usb interface data for use by the transmitter routine */
 	ir->usb_ep_in = ep_in;
diff --git a/drivers/media/IR/nuvoton-cir.c b/drivers/media/IR/nuvoton-cir.c
index 2f0f780..301be53 100644
--- a/drivers/media/IR/nuvoton-cir.c
+++ b/drivers/media/IR/nuvoton-cir.c
@@ -586,7 +586,7 @@ static void nvt_dump_rx_buf(struct nvt_dev *nvt)
  */
 static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
 {
-	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
+	DEFINE_IR_RAW_EVENT(rawir);
 	unsigned int count;
 	u32 carrier;
 	u8 sample;
@@ -622,6 +622,8 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
 		}
 
 		rawir.duration += nvt->rawir.duration;
+
+		init_ir_raw_event(&nvt->rawir);
 		nvt->rawir.duration = 0;
 		nvt->rawir.pulse = rawir.pulse;
 
@@ -1016,6 +1018,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
 
 	spin_lock_init(&nvt->nvt_lock);
 	spin_lock_init(&nvt->tx.lock);
+	init_ir_raw_event(&nvt->rawir);
 
 	ret = -EBUSY;
 	/* now claim resources */
diff --git a/drivers/media/IR/streamzap.c b/drivers/media/IR/streamzap.c
index 86a4f68..548381c 100644
--- a/drivers/media/IR/streamzap.c
+++ b/drivers/media/IR/streamzap.c
@@ -146,7 +146,7 @@ static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
 static void sz_push_full_pulse(struct streamzap_ir *sz,
 			       unsigned char value)
 {
-	struct ir_raw_event rawir;
+	DEFINE_IR_RAW_EVENT(rawir);
 
 	if (sz->idle) {
 		long deltv;
@@ -193,7 +193,7 @@ static void sz_push_half_pulse(struct streamzap_ir *sz,
 static void sz_push_full_space(struct streamzap_ir *sz,
 			       unsigned char value)
 {
-	struct ir_raw_event rawir;
+	DEFINE_IR_RAW_EVENT(rawir);
 
 	rawir.pulse = false;
 	rawir.duration = ((int) value) * SZ_RESOLUTION;
@@ -270,7 +270,7 @@ static void streamzap_callback(struct urb *urb)
 			break;
 		case FullSpace:
 			if (sz->buf_in[i] == SZ_TIMEOUT) {
-				struct ir_raw_event rawir;
+				DEFINE_IR_RAW_EVENT(rawir);
 
 				rawir.pulse = false;
 				rawir.duration = timeout;
diff --git a/include/media/ir-core.h b/include/media/ir-core.h
index 4dd43d4..6dc37fa 100644
--- a/include/media/ir-core.h
+++ b/include/media/ir-core.h
@@ -60,6 +60,7 @@ enum rc_driver_type {
  * @s_idle: optional: enable/disable hardware idle mode, upon which,
 	device doesn't interrupt host until it sees IR pulses
  * @s_learning_mode: enable wide band receiver used for learning
+ * @s_carrier_report: enable carrier reports
  */
 struct ir_dev_props {
 	enum rc_driver_type	driver_type;
@@ -82,8 +83,9 @@ struct ir_dev_props {
 	int			(*s_tx_duty_cycle)(void *priv, u32 duty_cycle);
 	int			(*s_rx_carrier_range)(void *priv, u32 min, u32 max);
 	int			(*tx_ir)(void *priv, int *txbuf, u32 n);
-	void			(*s_idle)(void *priv, int enable);
+	void			(*s_idle)(void *priv, bool enable);
 	int			(*s_learning_mode)(void *priv, int enable);
+	int			(*s_carrier_report) (void *priv, int enable);
 };
 
 struct ir_input_dev {
@@ -163,22 +165,48 @@ u32 ir_g_keycode_from_table(struct input_dev *input_dev, u32 scancode);
 /* From ir-raw-event.c */
 
 struct ir_raw_event {
-	unsigned                        pulse:1;
-	unsigned                        duration:31;
+	union {
+		u32             duration;
+
+		struct {
+			u32     carrier;
+			u8      duty_cycle;
+		};
+	};
+
+	unsigned                pulse:1;
+	unsigned                reset:1;
+	unsigned                timeout:1;
+	unsigned                carrier_report:1;
 };
 
-#define IR_MAX_DURATION                 0x7FFFFFFF      /* a bit more than 2 seconds */
+#define DEFINE_IR_RAW_EVENT(event) \
+	struct ir_raw_event event = { \
+		{ .duration = 0 } , \
+		.pulse = 0, \
+		.reset = 0, \
+		.timeout = 0, \
+		.carrier_report = 0 }
+
+static inline void init_ir_raw_event(struct ir_raw_event *ev)
+{
+	memset(ev, 0, sizeof(*ev));
+}
+
+#define IR_MAX_DURATION         0xFFFFFFFF      /* a bit more than 4 seconds */
 
 void ir_raw_event_handle(struct input_dev *input_dev);
 int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev);
 int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type);
 int ir_raw_event_store_with_filter(struct input_dev *input_dev,
 				struct ir_raw_event *ev);
-void ir_raw_event_set_idle(struct input_dev *input_dev, int idle);
+void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle);
 
 static inline void ir_raw_event_reset(struct input_dev *input_dev)
 {
-	struct ir_raw_event ev = { .pulse = false, .duration = 0 };
+	DEFINE_IR_RAW_EVENT(ev);
+	ev.reset = true;
+
 	ir_raw_event_store(input_dev, &ev);
 	ir_raw_event_handle(input_dev);
 }
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 1/3] IR: extend ir_raw_event and do refactoring
@ 2010-10-16 22:56   ` Maxim Levitsky
  0 siblings, 0 replies; 12+ messages in thread
From: Maxim Levitsky @ 2010-10-16 22:56 UTC (permalink / raw)
  To: lirc-list-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: mchehab-wEGCiKHe2LqWVfeAwA7xHQ,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-media-u79uwXL29TY76Z2rM5mHXA

Add new event types for timeout & carrier report
Move timeout handling from ir_raw_event_store_with_filter to
ir-lirc-codec, where it is really needed.
Now lirc bridge ensures proper gap handling.
Extend lirc bridge for carrier & timeout reports

Note: all new ir_raw_event variables now should be initialized
like that: DEFINE_IR_RAW_EVENT(ev);

To clean an existing event, use init_ir_raw_event(&ev);

Signed-off-by: Maxim Levitsky <maximlevitsky-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Acked-by: Jarod Wilson <jarod-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 drivers/media/IR/ene_ir.c            |    4 +-
 drivers/media/IR/ir-core-priv.h      |   13 +++-
 drivers/media/IR/ir-jvc-decoder.c    |    5 +-
 drivers/media/IR/ir-lirc-codec.c     |  128 ++++++++++++++++++++++++----------
 drivers/media/IR/ir-nec-decoder.c    |    5 +-
 drivers/media/IR/ir-raw-event.c      |   45 ++++--------
 drivers/media/IR/ir-rc5-decoder.c    |    5 +-
 drivers/media/IR/ir-rc5-sz-decoder.c |    5 +-
 drivers/media/IR/ir-rc6-decoder.c    |    5 +-
 drivers/media/IR/ir-sony-decoder.c   |    5 +-
 drivers/media/IR/mceusb.c            |    3 +-
 drivers/media/IR/nuvoton-cir.c       |    5 +-
 drivers/media/IR/streamzap.c         |    6 +-
 include/media/ir-core.h              |   40 +++++++++--
 14 files changed, 181 insertions(+), 93 deletions(-)

diff --git a/drivers/media/IR/ene_ir.c b/drivers/media/IR/ene_ir.c
index 9f9afe7..8639621 100644
--- a/drivers/media/IR/ene_ir.c
+++ b/drivers/media/IR/ene_ir.c
@@ -697,7 +697,7 @@ static irqreturn_t ene_isr(int irq, void *data)
 	unsigned long flags;
 	irqreturn_t retval = IRQ_NONE;
 	struct ene_device *dev = (struct ene_device *)data;
-	struct ir_raw_event ev;
+	DEFINE_IR_RAW_EVENT(ev);
 
 	spin_lock_irqsave(&dev->hw_lock, flags);
 
@@ -898,7 +898,7 @@ static int ene_set_learning_mode(void *data, int enable)
 }
 
 /* outside interface: enable or disable idle mode */
-static void ene_rx_set_idle(void *data, int idle)
+static void ene_rx_set_idle(void *data, bool idle)
 {
 	struct ene_device *dev = (struct ene_device *)data;
 
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h
index 6830580..81c936b 100644
--- a/drivers/media/IR/ir-core-priv.h
+++ b/drivers/media/IR/ir-core-priv.h
@@ -88,6 +88,12 @@ struct ir_raw_event_ctrl {
 		struct ir_input_dev *ir_dev;
 		struct lirc_driver *drv;
 		int carrier_low;
+
+		ktime_t gap_start;
+		u64 gap_duration;
+		bool gap;
+		bool send_timeout_reports;
+
 	} lirc;
 };
 
@@ -115,9 +121,14 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
 		ev->duration -= duration;
 }
 
+/* Returns true if event is normal pulse/space event */
+static inline bool is_timing_event(struct ir_raw_event ev)
+{
+	return !ev.carrier_report && !ev.reset;
+}
+
 #define TO_US(duration)			DIV_ROUND_CLOSEST((duration), 1000)
 #define TO_STR(is_pulse)		((is_pulse) ? "pulse" : "space")
-#define IS_RESET(ev)			(ev.duration == 0)
 /*
  * Routines from ir-sysfs.c - Meant to be called only internally inside
  * ir-core
diff --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c
index 77a89c4..63dca6e 100644
--- a/drivers/media/IR/ir-jvc-decoder.c
+++ b/drivers/media/IR/ir-jvc-decoder.c
@@ -50,8 +50,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
 		return 0;
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 	}
 
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c
index 20ac9a4..1d9c6b0 100644
--- a/drivers/media/IR/ir-lirc-codec.c
+++ b/drivers/media/IR/ir-lirc-codec.c
@@ -32,6 +32,7 @@
 static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 {
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+	struct lirc_codec *lirc = &ir_dev->raw->lirc;
 	int sample;
 
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
@@ -40,21 +41,57 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
 		return -EINVAL;
 
-	if (IS_RESET(ev))
+	/* Packet start */
+	if (ev.reset)
 		return 0;
 
-	IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
-		   TO_US(ev.duration), TO_STR(ev.pulse));
+	/* Carrier reports */
+	if (ev.carrier_report) {
+		sample = LIRC_FREQUENCY(ev.carrier);
+
+	/* Packet end */
+	} else if (ev.timeout) {
+
+		if (lirc->gap)
+			return 0;
+
+		lirc->gap_start = ktime_get();
+		lirc->gap = true;
+		lirc->gap_duration = ev.duration;
+
+		if (!lirc->send_timeout_reports)
+			return 0;
+
+		sample = LIRC_TIMEOUT(ev.duration / 1000);
 
-	sample = ev.duration / 1000;
-	if (ev.pulse)
-		sample |= PULSE_BIT;
+	/* Normal sample */
+	} else {
+
+		if (lirc->gap) {
+			int gap_sample;
+
+			lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
+				lirc->gap_start));
+
+			/* Convert to ms and cap by LIRC_VALUE_MASK */
+			do_div(lirc->gap_duration, 1000);
+			lirc->gap_duration = min(lirc->gap_duration,
+							(u64)LIRC_VALUE_MASK);
+
+			gap_sample = LIRC_SPACE(lirc->gap_duration);
+			lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
+						(unsigned char *) &gap_sample);
+			lirc->gap = false;
+		}
+
+		sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
+					LIRC_SPACE(ev.duration / 1000);
+	}
 
 	lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
 			  (unsigned char *) &sample);
 	wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
 
-
 	return 0;
 }
 
@@ -102,7 +139,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	struct ir_input_dev *ir_dev;
 	int ret = 0;
 	void *drv_data;
-	__u32 val = 0;
+	__u32 val = 0, tmp;
 
 	lirc = lirc_get_pdata(filep);
 	if (!lirc)
@@ -130,22 +167,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	case LIRC_SET_SEND_MODE:
 		if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
 			return -EINVAL;
-		break;
+		return 0;
 
 	/* TX settings */
 	case LIRC_SET_TRANSMITTER_MASK:
-		if (ir_dev->props->s_tx_mask)
-			ret = ir_dev->props->s_tx_mask(drv_data, val);
-		else
+		if (!ir_dev->props->s_tx_mask)
 			return -EINVAL;
-		break;
+
+		return ir_dev->props->s_tx_mask(drv_data, val);
 
 	case LIRC_SET_SEND_CARRIER:
-		if (ir_dev->props->s_tx_carrier)
-			ir_dev->props->s_tx_carrier(drv_data, val);
-		else
+		if (!ir_dev->props->s_tx_carrier)
 			return -EINVAL;
-		break;
+
+		return ir_dev->props->s_tx_carrier(drv_data, val);
 
 	case LIRC_SET_SEND_DUTY_CYCLE:
 		if (!ir_dev->props->s_tx_duty_cycle)
@@ -154,39 +189,42 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		if (val <= 0 || val >= 100)
 			return -EINVAL;
 
-		ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val);
-		break;
+		return ir_dev->props->s_tx_duty_cycle(drv_data, val);
 
 	/* RX settings */
 	case LIRC_SET_REC_CARRIER:
-		if (ir_dev->props->s_rx_carrier_range)
-			ret = ir_dev->props->s_rx_carrier_range(
-				ir_dev->props->priv,
-				ir_dev->raw->lirc.carrier_low, val);
-		else
+		if (!ir_dev->props->s_rx_carrier_range)
 			return -ENOSYS;
 
-		if (!ret)
-			ir_dev->raw->lirc.carrier_low = 0;
-		break;
+		if (val <= 0)
+			return -EINVAL;
+
+		return ir_dev->props->s_rx_carrier_range(drv_data,
+			ir_dev->raw->lirc.carrier_low, val);
 
 	case LIRC_SET_REC_CARRIER_RANGE:
-		if (val >= 0)
-			ir_dev->raw->lirc.carrier_low = val;
-		break;
+		if (val <= 0)
+			return -EINVAL;
 
+		ir_dev->raw->lirc.carrier_low = val;
+		return 0;
 
 	case LIRC_GET_REC_RESOLUTION:
 		val = ir_dev->props->rx_resolution;
 		break;
 
 	case LIRC_SET_WIDEBAND_RECEIVER:
-		if (ir_dev->props->s_learning_mode)
-			return ir_dev->props->s_learning_mode(
-				ir_dev->props->priv, !!val);
-		else
+		if (!ir_dev->props->s_learning_mode)
 			return -ENOSYS;
 
+		return ir_dev->props->s_learning_mode(drv_data, !!val);
+
+	case LIRC_SET_MEASURE_CARRIER_MODE:
+		if (!ir_dev->props->s_carrier_report)
+			return -ENOSYS;
+
+		return ir_dev->props->s_carrier_report(drv_data, !!val);
+
 	/* Generic timeout support */
 	case LIRC_GET_MIN_TIMEOUT:
 		if (!ir_dev->props->max_timeout)
@@ -201,10 +239,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		break;
 
 	case LIRC_SET_REC_TIMEOUT:
-		if (val < ir_dev->props->min_timeout ||
-		    val > ir_dev->props->max_timeout)
-			return -EINVAL;
-		ir_dev->props->timeout = val * 1000;
+		if (!ir_dev->props->max_timeout)
+			return -ENOSYS;
+
+		tmp = val * 1000;
+
+		if (tmp < ir_dev->props->min_timeout ||
+			tmp > ir_dev->props->max_timeout)
+				return -EINVAL;
+
+		ir_dev->props->timeout = tmp;
+		break;
+
+	case LIRC_SET_REC_TIMEOUT_REPORTS:
+		lirc->send_timeout_reports = !!val;
 		break;
 
 	default:
@@ -280,6 +328,10 @@ static int ir_lirc_register(struct input_dev *input_dev)
 	if (ir_dev->props->s_learning_mode)
 		features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
 
+	if (ir_dev->props->s_carrier_report)
+		features |= LIRC_CAN_MEASURE_CARRIER;
+
+
 	if (ir_dev->props->max_timeout)
 		features |= LIRC_CAN_SET_REC_TIMEOUT;
 
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c
index d597421..70993f7 100644
--- a/drivers/media/IR/ir-nec-decoder.c
+++ b/drivers/media/IR/ir-nec-decoder.c
@@ -54,8 +54,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
 		return 0;
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 	}
 
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
index 119b567..0d59ef7 100644
--- a/drivers/media/IR/ir-raw-event.c
+++ b/drivers/media/IR/ir-raw-event.c
@@ -174,7 +174,7 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev,
 	if (ir->idle && !ev->pulse)
 		return 0;
 	else if (ir->idle)
-		ir_raw_event_set_idle(input_dev, 0);
+		ir_raw_event_set_idle(input_dev, false);
 
 	if (!raw->this_ev.duration) {
 		raw->this_ev = *ev;
@@ -187,48 +187,35 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev,
 
 	/* Enter idle mode if nessesary */
 	if (!ev->pulse && ir->props->timeout &&
-		raw->this_ev.duration >= ir->props->timeout)
-		ir_raw_event_set_idle(input_dev, 1);
+		raw->this_ev.duration >= ir->props->timeout) {
+		ir_raw_event_set_idle(input_dev, true);
+	}
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
 
-void ir_raw_event_set_idle(struct input_dev *input_dev, int idle)
+/**
+ * ir_raw_event_set_idle() - hint the ir core if device is receiving
+ * IR data or not
+ * @input_dev: the struct input_dev device descriptor
+ * @idle: the hint value
+ */
+void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle)
 {
 	struct ir_input_dev *ir = input_get_drvdata(input_dev);
 	struct ir_raw_event_ctrl *raw = ir->raw;
-	ktime_t now;
-	u64 delta;
 
-	if (!ir->props)
+	if (!ir->props || !ir->raw)
 		return;
 
-	if (!ir->raw)
-		goto out;
+	IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");
 
 	if (idle) {
-		IR_dprintk(2, "enter idle mode\n");
-		raw->last_event = ktime_get();
-	} else {
-		IR_dprintk(2, "exit idle mode\n");
-
-		now = ktime_get();
-		delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));
-
-		WARN_ON(raw->this_ev.pulse);
-
-		raw->this_ev.duration =
-			min(raw->this_ev.duration + delta,
-						(u64)IR_MAX_DURATION);
-
+		raw->this_ev.timeout = true;
 		ir_raw_event_store(input_dev, &raw->this_ev);
-
-		if (raw->this_ev.duration == IR_MAX_DURATION)
-			ir_raw_event_reset(input_dev);
-
-		raw->this_ev.duration = 0;
+		init_ir_raw_event(&raw->this_ev);
 	}
-out:
+
 	if (ir->props->s_idle)
 		ir->props->s_idle(ir->props->priv, idle);
 	ir->idle = idle;
diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c
index df4770d..572ed4c 100644
--- a/drivers/media/IR/ir-rc5-decoder.c
+++ b/drivers/media/IR/ir-rc5-decoder.c
@@ -55,8 +55,9 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
         if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
                 return 0;
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 	}
 
diff --git a/drivers/media/IR/ir-rc5-sz-decoder.c b/drivers/media/IR/ir-rc5-sz-decoder.c
index 68f11d6..7c41350 100644
--- a/drivers/media/IR/ir-rc5-sz-decoder.c
+++ b/drivers/media/IR/ir-rc5-sz-decoder.c
@@ -51,8 +51,9 @@ static int ir_rc5_sz_decode(struct input_dev *input_dev, struct ir_raw_event ev)
         if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5_SZ))
                 return 0;
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 	}
 
diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c
index f1624b8..d25da91 100644
--- a/drivers/media/IR/ir-rc6-decoder.c
+++ b/drivers/media/IR/ir-rc6-decoder.c
@@ -85,8 +85,9 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
 		return 0;
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 	}
 
diff --git a/drivers/media/IR/ir-sony-decoder.c b/drivers/media/IR/ir-sony-decoder.c
index b9074f0..2d15730 100644
--- a/drivers/media/IR/ir-sony-decoder.c
+++ b/drivers/media/IR/ir-sony-decoder.c
@@ -48,8 +48,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
 		return 0;
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 	}
 
diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c
index bc620e1..6825da5 100644
--- a/drivers/media/IR/mceusb.c
+++ b/drivers/media/IR/mceusb.c
@@ -660,7 +660,7 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
 
 static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 {
-	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
+	DEFINE_IR_RAW_EVENT(rawir);
 	int i, start_index = 0;
 	u8 hdr = MCE_CONTROL_HEADER;
 
@@ -997,6 +997,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
 	ir->len_in = maxp;
 	ir->flags.microsoft_gen1 = is_microsoft_gen1;
 	ir->flags.tx_mask_inverted = tx_mask_inverted;
+	init_ir_raw_event(&ir->rawir);
 
 	/* Saving usb interface data for use by the transmitter routine */
 	ir->usb_ep_in = ep_in;
diff --git a/drivers/media/IR/nuvoton-cir.c b/drivers/media/IR/nuvoton-cir.c
index 2f0f780..301be53 100644
--- a/drivers/media/IR/nuvoton-cir.c
+++ b/drivers/media/IR/nuvoton-cir.c
@@ -586,7 +586,7 @@ static void nvt_dump_rx_buf(struct nvt_dev *nvt)
  */
 static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
 {
-	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
+	DEFINE_IR_RAW_EVENT(rawir);
 	unsigned int count;
 	u32 carrier;
 	u8 sample;
@@ -622,6 +622,8 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
 		}
 
 		rawir.duration += nvt->rawir.duration;
+
+		init_ir_raw_event(&nvt->rawir);
 		nvt->rawir.duration = 0;
 		nvt->rawir.pulse = rawir.pulse;
 
@@ -1016,6 +1018,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
 
 	spin_lock_init(&nvt->nvt_lock);
 	spin_lock_init(&nvt->tx.lock);
+	init_ir_raw_event(&nvt->rawir);
 
 	ret = -EBUSY;
 	/* now claim resources */
diff --git a/drivers/media/IR/streamzap.c b/drivers/media/IR/streamzap.c
index 86a4f68..548381c 100644
--- a/drivers/media/IR/streamzap.c
+++ b/drivers/media/IR/streamzap.c
@@ -146,7 +146,7 @@ static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
 static void sz_push_full_pulse(struct streamzap_ir *sz,
 			       unsigned char value)
 {
-	struct ir_raw_event rawir;
+	DEFINE_IR_RAW_EVENT(rawir);
 
 	if (sz->idle) {
 		long deltv;
@@ -193,7 +193,7 @@ static void sz_push_half_pulse(struct streamzap_ir *sz,
 static void sz_push_full_space(struct streamzap_ir *sz,
 			       unsigned char value)
 {
-	struct ir_raw_event rawir;
+	DEFINE_IR_RAW_EVENT(rawir);
 
 	rawir.pulse = false;
 	rawir.duration = ((int) value) * SZ_RESOLUTION;
@@ -270,7 +270,7 @@ static void streamzap_callback(struct urb *urb)
 			break;
 		case FullSpace:
 			if (sz->buf_in[i] == SZ_TIMEOUT) {
-				struct ir_raw_event rawir;
+				DEFINE_IR_RAW_EVENT(rawir);
 
 				rawir.pulse = false;
 				rawir.duration = timeout;
diff --git a/include/media/ir-core.h b/include/media/ir-core.h
index 4dd43d4..6dc37fa 100644
--- a/include/media/ir-core.h
+++ b/include/media/ir-core.h
@@ -60,6 +60,7 @@ enum rc_driver_type {
  * @s_idle: optional: enable/disable hardware idle mode, upon which,
 	device doesn't interrupt host until it sees IR pulses
  * @s_learning_mode: enable wide band receiver used for learning
+ * @s_carrier_report: enable carrier reports
  */
 struct ir_dev_props {
 	enum rc_driver_type	driver_type;
@@ -82,8 +83,9 @@ struct ir_dev_props {
 	int			(*s_tx_duty_cycle)(void *priv, u32 duty_cycle);
 	int			(*s_rx_carrier_range)(void *priv, u32 min, u32 max);
 	int			(*tx_ir)(void *priv, int *txbuf, u32 n);
-	void			(*s_idle)(void *priv, int enable);
+	void			(*s_idle)(void *priv, bool enable);
 	int			(*s_learning_mode)(void *priv, int enable);
+	int			(*s_carrier_report) (void *priv, int enable);
 };
 
 struct ir_input_dev {
@@ -163,22 +165,48 @@ u32 ir_g_keycode_from_table(struct input_dev *input_dev, u32 scancode);
 /* From ir-raw-event.c */
 
 struct ir_raw_event {
-	unsigned                        pulse:1;
-	unsigned                        duration:31;
+	union {
+		u32             duration;
+
+		struct {
+			u32     carrier;
+			u8      duty_cycle;
+		};
+	};
+
+	unsigned                pulse:1;
+	unsigned                reset:1;
+	unsigned                timeout:1;
+	unsigned                carrier_report:1;
 };
 
-#define IR_MAX_DURATION                 0x7FFFFFFF      /* a bit more than 2 seconds */
+#define DEFINE_IR_RAW_EVENT(event) \
+	struct ir_raw_event event = { \
+		{ .duration = 0 } , \
+		.pulse = 0, \
+		.reset = 0, \
+		.timeout = 0, \
+		.carrier_report = 0 }
+
+static inline void init_ir_raw_event(struct ir_raw_event *ev)
+{
+	memset(ev, 0, sizeof(*ev));
+}
+
+#define IR_MAX_DURATION         0xFFFFFFFF      /* a bit more than 4 seconds */
 
 void ir_raw_event_handle(struct input_dev *input_dev);
 int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev);
 int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type);
 int ir_raw_event_store_with_filter(struct input_dev *input_dev,
 				struct ir_raw_event *ev);
-void ir_raw_event_set_idle(struct input_dev *input_dev, int idle);
+void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle);
 
 static inline void ir_raw_event_reset(struct input_dev *input_dev)
 {
-	struct ir_raw_event ev = { .pulse = false, .duration = 0 };
+	DEFINE_IR_RAW_EVENT(ev);
+	ev.reset = true;
+
 	ir_raw_event_store(input_dev, &ev);
 	ir_raw_event_handle(input_dev);
 }
-- 
1.7.1


------------------------------------------------------------------------------
Download new Adobe(R) Flash(R) Builder(TM) 4
The new Adobe(R) Flex(R) 4 and Flash(R) Builder(TM) 4 (formerly 
Flex(R) Builder(TM)) enable the development of rich applications that run
across multiple browsers and platforms. Download your free trials today!
http://p.sf.net/sfu/adobe-dev2dev

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/3] IR: ene_ir: add support for carrier reports
  2010-10-16 22:56 ` Maxim Levitsky
  (?)
  (?)
@ 2010-10-16 22:56 ` Maxim Levitsky
  -1 siblings, 0 replies; 12+ messages in thread
From: Maxim Levitsky @ 2010-10-16 22:56 UTC (permalink / raw)
  To: lirc-list
  Cc: Jarod Wilson, David Härdeman, mchehab, linux-input,
	linux-media, Maxim Levitsky

Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
---
 drivers/media/IR/ene_ir.c |   37 +++++++++++++++++++++++++++++--------
 1 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/drivers/media/IR/ene_ir.c b/drivers/media/IR/ene_ir.c
index 8639621..1962652 100644
--- a/drivers/media/IR/ene_ir.c
+++ b/drivers/media/IR/ene_ir.c
@@ -193,10 +193,11 @@ static int ene_hw_detect(struct ene_device *dev)
 /* Sense current received carrier */
 void ene_rx_sense_carrier(struct ene_device *dev)
 {
+	DEFINE_IR_RAW_EVENT(ev);
+
+	int carrier, duty_cycle;
 	int period = ene_read_reg(dev, ENE_CIRCAR_PRD);
 	int hperiod = ene_read_reg(dev, ENE_CIRCAR_HPRD);
-	int carrier, duty_cycle;
-
 
 	if (!(period & ENE_CIRCAR_PRD_VALID))
 		return;
@@ -209,13 +210,16 @@ void ene_rx_sense_carrier(struct ene_device *dev)
 	dbg("RX: hardware carrier period = %02x", period);
 	dbg("RX: hardware carrier pulse period = %02x", hperiod);
 
-
 	carrier = 2000000 / period;
 	duty_cycle = (hperiod * 100) / period;
 	dbg("RX: sensed carrier = %d Hz, duty cycle %d%%",
-							carrier, duty_cycle);
-
-	/* TODO: Send carrier & duty cycle to IR layer */
+						carrier, duty_cycle);
+	if (dev->carrier_detect_enabled) {
+		ev.carrier_report = true;
+		ev.carrier = carrier;
+		ev.duty_cycle = duty_cycle;
+		ir_raw_event_store(dev->idev, &ev);
+	}
 }
 
 /* this enables/disables the CIR RX engine */
@@ -724,7 +728,7 @@ static irqreturn_t ene_isr(int irq, void *data)
 
 	dbg_verbose("RX interrupt");
 
-	if (dev->carrier_detect_enabled || debug)
+	if (dev->hw_learning_and_tx_capable)
 		ene_rx_sense_carrier(dev);
 
 	/* On hardware that don't support extra buffer we need to trust
@@ -897,6 +901,23 @@ static int ene_set_learning_mode(void *data, int enable)
 	return 0;
 }
 
+static int ene_set_carrier_report(void *data, int enable)
+{
+	struct ene_device *dev = (struct ene_device *)data;
+	unsigned long flags;
+
+	if (enable == dev->carrier_detect_enabled)
+		return 0;
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+	dev->carrier_detect_enabled = enable;
+	ene_rx_disable(dev);
+	ene_rx_setup(dev);
+	ene_rx_enable(dev);
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+	return 0;
+}
+
 /* outside interface: enable or disable idle mode */
 static void ene_rx_set_idle(void *data, bool idle)
 {
@@ -1029,7 +1050,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 		ir_props->s_tx_mask = ene_set_tx_mask;
 		ir_props->s_tx_carrier = ene_set_tx_carrier;
 		ir_props->s_tx_duty_cycle = ene_set_tx_duty_cycle;
-		/* ir_props->s_carrier_report = ene_set_carrier_report; */
+		ir_props->s_carrier_report = ene_set_carrier_report;
 	}
 
 	ene_setup_hw_buffer(dev);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/3] IR: ene_ir: don't upload all settings on each TX packet.
  2010-10-16 22:56 ` Maxim Levitsky
                   ` (2 preceding siblings ...)
  (?)
@ 2010-10-16 22:56 ` Maxim Levitsky
  -1 siblings, 0 replies; 12+ messages in thread
From: Maxim Levitsky @ 2010-10-16 22:56 UTC (permalink / raw)
  To: lirc-list
  Cc: Jarod Wilson, David Härdeman, mchehab, linux-input,
	linux-media, Maxim Levitsky

This is just unnessesary, and now more logical

Also a lot of refactoring

Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
---
 drivers/media/IR/ene_ir.c |  474 +++++++++++++++++++++++---------------------
 drivers/media/IR/ene_ir.h |    6 +-
 2 files changed, 251 insertions(+), 229 deletions(-)

diff --git a/drivers/media/IR/ene_ir.c b/drivers/media/IR/ene_ir.c
index 1962652..685db83 100644
--- a/drivers/media/IR/ene_ir.c
+++ b/drivers/media/IR/ene_ir.c
@@ -43,7 +43,7 @@
 #include "ene_ir.h"
 
 static int sample_period;
-static bool learning_mode;
+static bool learning_mode_force;
 static int debug;
 static bool txsim;
 
@@ -190,6 +190,145 @@ static int ene_hw_detect(struct ene_device *dev)
 	return 0;
 }
 
+/* Read properities of hw sample buffer */
+static void ene_rx_setup_hw_buffer(struct ene_device *dev)
+{
+	u16 tmp;
+
+	ene_rx_read_hw_pointer(dev);
+	dev->r_pointer = dev->w_pointer;
+
+	if (!dev->hw_extra_buffer) {
+		dev->buffer_len = ENE_FW_PACKET_SIZE * 2;
+		return;
+	}
+
+	tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER);
+	tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER+1) << 8;
+	dev->extra_buf1_address = tmp;
+
+	dev->extra_buf1_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 2);
+
+	tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 3);
+	tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 4) << 8;
+	dev->extra_buf2_address = tmp;
+
+	dev->extra_buf2_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 5);
+
+	dev->buffer_len = dev->extra_buf1_len + dev->extra_buf2_len + 8;
+
+	ene_notice("Hardware uses 2 extended buffers:");
+	ene_notice("  0x%04x - len : %d", dev->extra_buf1_address,
+						dev->extra_buf1_len);
+	ene_notice("  0x%04x - len : %d", dev->extra_buf2_address,
+						dev->extra_buf2_len);
+
+	ene_notice("Total buffer len = %d", dev->buffer_len);
+
+	if (dev->buffer_len > 64 || dev->buffer_len < 16)
+		goto error;
+
+	if (dev->extra_buf1_address > 0xFBFC ||
+					dev->extra_buf1_address < 0xEC00)
+		goto error;
+
+	if (dev->extra_buf2_address > 0xFBFC ||
+					dev->extra_buf2_address < 0xEC00)
+		goto error;
+
+	if (dev->r_pointer > dev->buffer_len)
+		goto error;
+
+	ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
+	return;
+error:
+	ene_warn("Error validating extra buffers, device probably won't work");
+	dev->hw_extra_buffer = false;
+	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
+}
+
+
+/* Restore the pointers to extra buffers - to make module reload work*/
+static void ene_rx_restore_hw_buffer(struct ene_device *dev)
+{
+	if (!dev->hw_extra_buffer)
+		return;
+
+	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 0,
+				dev->extra_buf1_address & 0xFF);
+	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 1,
+				dev->extra_buf1_address >> 8);
+	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 2, dev->extra_buf1_len);
+
+	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 3,
+				dev->extra_buf2_address & 0xFF);
+	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 4,
+				dev->extra_buf2_address >> 8);
+	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 5,
+				dev->extra_buf2_len);
+	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
+}
+
+/* Read hardware write pointer */
+static void ene_rx_read_hw_pointer(struct ene_device *dev)
+{
+	if (dev->hw_extra_buffer)
+		dev->w_pointer = ene_read_reg(dev, ENE_FW_RX_POINTER);
+	else
+		dev->w_pointer = ene_read_reg(dev, ENE_FW2)
+			& ENE_FW2_BUF_WPTR ? 0 : ENE_FW_PACKET_SIZE;
+
+	dbg_verbose("RB: HW write pointer: %02x, driver read pointer: %02x",
+		dev->w_pointer, dev->r_pointer);
+}
+
+/* Gets address of next sample from HW ring buffer */
+static int ene_rx_get_sample_reg(struct ene_device *dev)
+{
+	int r_pointer;
+
+	if (dev->r_pointer == dev->w_pointer) {
+		dbg_verbose("RB: hit end, try update w_pointer");
+		ene_rx_read_hw_pointer(dev);
+	}
+
+	if (dev->r_pointer == dev->w_pointer) {
+		dbg_verbose("RB: end of data at %d", dev->r_pointer);
+		return 0;
+	}
+
+	dbg_verbose("RB: reading at offset %d", dev->r_pointer);
+	r_pointer = dev->r_pointer;
+
+	dev->r_pointer++;
+	if (dev->r_pointer == dev->buffer_len)
+		dev->r_pointer = 0;
+
+	dbg_verbose("RB: next read will be from offset %d", dev->r_pointer);
+
+	if (r_pointer < 8) {
+		dbg_verbose("RB: read at main buffer at %d", r_pointer);
+		return ENE_FW_SAMPLE_BUFFER + r_pointer;
+	}
+
+	r_pointer -= 8;
+
+	if (r_pointer < dev->extra_buf1_len) {
+		dbg_verbose("RB: read at 1st extra buffer at %d", r_pointer);
+		return dev->extra_buf1_address + r_pointer;
+	}
+
+	r_pointer -= dev->extra_buf1_len;
+
+	if (r_pointer < dev->extra_buf2_len) {
+		dbg_verbose("RB: read at 2nd extra buffer at %d", r_pointer);
+		return dev->extra_buf2_address + r_pointer;
+	}
+
+	dbg("attempt to read beyong ring bufer end");
+	return 0;
+}
+
 /* Sense current received carrier */
 void ene_rx_sense_carrier(struct ene_device *dev)
 {
@@ -223,14 +362,14 @@ void ene_rx_sense_carrier(struct ene_device *dev)
 }
 
 /* this enables/disables the CIR RX engine */
-static void ene_enable_cir_engine(struct ene_device *dev, bool enable)
+static void ene_rx_enable_cir_engine(struct ene_device *dev, bool enable)
 {
 	ene_set_clear_reg_mask(dev, ENE_CIRCFG,
 			ENE_CIRCFG_RX_EN | ENE_CIRCFG_RX_IRQ, enable);
 }
 
 /* this selects input for CIR engine. Ether GPIO 0A or GPIO40*/
-static void ene_select_rx_input(struct ene_device *dev, bool gpio_0a)
+static void ene_rx_select_input(struct ene_device *dev, bool gpio_0a)
 {
 	ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_GPIO0A, gpio_0a);
 }
@@ -239,7 +378,7 @@ static void ene_select_rx_input(struct ene_device *dev, bool gpio_0a)
  * this enables alternative input via fan tachometer sensor and bypasses
  * the hw CIR engine
  */
-static void ene_enable_fan_input(struct ene_device *dev, bool enable)
+static void ene_rx_enable_fan_input(struct ene_device *dev, bool enable)
 {
 	if (!dev->hw_fan_input)
 		return;
@@ -250,16 +389,18 @@ static void ene_enable_fan_input(struct ene_device *dev, bool enable)
 		ene_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN);
 		ene_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN);
 	}
-	dev->rx_fan_input_inuse = enable;
 }
 
 /* setup the receiver for RX*/
 static void ene_rx_setup(struct ene_device *dev)
 {
-	bool learning_mode = dev->learning_enabled ||
+	bool learning_mode = dev->learning_mode_enabled ||
 					dev->carrier_detect_enabled;
 	int sample_period_adjust = 0;
 
+	dbg("RX: setup receiver, learning mode = %d", learning_mode);
+
+
 	/* This selects RLC input and clears CFG2 settings */
 	ene_write_reg(dev, ENE_CIRCFG2, 0x00);
 
@@ -284,7 +425,7 @@ static void ene_rx_setup(struct ene_device *dev)
 		and vice versa.
 		This input will carry non demodulated
 		signal, and we will tell the hw to demodulate it itself */
-		ene_select_rx_input(dev, !dev->hw_use_gpio_0a);
+		ene_rx_select_input(dev, !dev->hw_use_gpio_0a);
 		dev->rx_fan_input_inuse = false;
 
 		/* Enable carrier demodulation */
@@ -298,7 +439,7 @@ static void ene_rx_setup(struct ene_device *dev)
 		if (dev->hw_fan_input)
 			dev->rx_fan_input_inuse = true;
 		else
-			ene_select_rx_input(dev, dev->hw_use_gpio_0a);
+			ene_rx_select_input(dev, dev->hw_use_gpio_0a);
 
 		/* Disable carrier detection & demodulation */
 		ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
@@ -339,7 +480,6 @@ select_timeout:
 static void ene_rx_enable(struct ene_device *dev)
 {
 	u8 reg_value;
-	dbg("RX: setup receiver, learning mode = %d", learning_mode);
 
 	/* Enable system interrupt */
 	if (dev->hw_revision < ENE_HW_C) {
@@ -354,8 +494,8 @@ static void ene_rx_enable(struct ene_device *dev)
 	}
 
 	/* Enable inputs */
-	ene_enable_fan_input(dev, dev->rx_fan_input_inuse);
-	ene_enable_cir_engine(dev, !dev->rx_fan_input_inuse);
+	ene_rx_enable_fan_input(dev, dev->rx_fan_input_inuse);
+	ene_rx_enable_cir_engine(dev, !dev->rx_fan_input_inuse);
 
 	/* ack any pending irqs - just in case */
 	ene_irq_status(dev);
@@ -372,8 +512,8 @@ static void ene_rx_enable(struct ene_device *dev)
 static void ene_rx_disable(struct ene_device *dev)
 {
 	/* disable inputs */
-	ene_enable_cir_engine(dev, false);
-	ene_enable_fan_input(dev, false);
+	ene_rx_enable_cir_engine(dev, false);
+	ene_rx_enable_fan_input(dev, false);
 
 	/* disable hardware IRQ and firmware flag */
 	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
@@ -382,8 +522,60 @@ static void ene_rx_disable(struct ene_device *dev)
 	dev->rx_enabled = false;
 }
 
+/* This resets the receiver. Usefull to stop stream of spaces at end of
+ * transmission
+ */
+static void ene_rx_reset(struct ene_device *dev)
+{
+	ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
+	ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
+}
+
+/* Set up the TX carrier frequency and duty cycle */
+static void ene_tx_set_carrier(struct ene_device *dev)
+{
+	u8 tx_puls_width;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+
+	ene_set_clear_reg_mask(dev, ENE_CIRCFG,
+		ENE_CIRCFG_TX_CARR, dev->tx_period > 0);
+
+	if (!dev->tx_period)
+		goto unlock;
+
+	BUG_ON(dev->tx_duty_cycle >= 100 || dev->tx_duty_cycle <= 0);
+
+	tx_puls_width = dev->tx_period / (100 / dev->tx_duty_cycle);
+
+	if (!tx_puls_width)
+		tx_puls_width = 1;
+
+	dbg("TX: pulse distance = %d * 500 ns", dev->tx_period);
+	dbg("TX: pulse width = %d * 500 ns", tx_puls_width);
+
+	ene_write_reg(dev, ENE_CIRMOD_PRD, dev->tx_period | ENE_CIRMOD_PRD_POL);
+	ene_write_reg(dev, ENE_CIRMOD_HPRD, tx_puls_width);
+unlock:
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+}
+
+/* Enable/disable transmitters */
+static void ene_tx_set_transmitters(struct ene_device *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+	ene_set_clear_reg_mask(dev, ENE_GPIOFS8, ENE_GPIOFS8_GPIO41,
+					!!(dev->transmitter_mask & 0x01));
+	ene_set_clear_reg_mask(dev, ENE_GPIOFS1, ENE_GPIOFS1_GPIO0D,
+					!!(dev->transmitter_mask & 0x02));
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+}
+
 /* prepare transmission */
-static void ene_tx_prepare(struct ene_device *dev)
+static void ene_tx_enable(struct ene_device *dev)
 {
 	u8 conf1 = ene_read_reg(dev, ENE_CIRCFG);
 	u8 fwreg2 = ene_read_reg(dev, ENE_FW2);
@@ -400,32 +592,6 @@ static void ene_tx_prepare(struct ene_device *dev)
 	if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN)))
 		ene_warn("TX: transmitter cable isn't connected!");
 
-	/* Set transmitter mask */
-	ene_set_clear_reg_mask(dev, ENE_GPIOFS8, ENE_GPIOFS8_GPIO41,
-					!!(dev->transmitter_mask & 0x01));
-	ene_set_clear_reg_mask(dev, ENE_GPIOFS1, ENE_GPIOFS1_GPIO0D,
-					!!(dev->transmitter_mask & 0x02));
-
-	/* Set the carrier period && duty cycle */
-	if (dev->tx_period) {
-
-		int tx_puls_width = dev->tx_period / (100 / dev->tx_duty_cycle);
-
-		if (!tx_puls_width)
-			tx_puls_width = 1;
-
-		dbg("TX: pulse distance = %d * 500 ns", dev->tx_period);
-		dbg("TX: pulse width = %d * 500 ns", tx_puls_width);
-
-		ene_write_reg(dev, ENE_CIRMOD_PRD, ENE_CIRMOD_PRD_POL |
-					dev->tx_period);
-
-		ene_write_reg(dev, ENE_CIRMOD_HPRD, tx_puls_width);
-
-		conf1 |= ENE_CIRCFG_TX_CARR;
-	} else
-		conf1 &= ~ENE_CIRCFG_TX_CARR;
-
 	/* disable receive on revc */
 	if (dev->hw_revision == ENE_HW_C)
 		conf1 &= ~ENE_CIRCFG_RX_EN;
@@ -436,7 +602,7 @@ static void ene_tx_prepare(struct ene_device *dev)
 }
 
 /* end transmission */
-static void ene_tx_complete(struct ene_device *dev)
+static void ene_tx_disable(struct ene_device *dev)
 {
 	ene_write_reg(dev, ENE_CIRCFG, dev->saved_conf1);
 	dev->tx_buffer = NULL;
@@ -465,7 +631,7 @@ static void ene_tx_sample(struct ene_device *dev)
 				goto exit;
 			} else {
 				dbg("TX: last sample sent by hardware");
-				ene_tx_complete(dev);
+				ene_tx_disable(dev);
 				complete(&dev->tx_complete);
 				return;
 			}
@@ -509,85 +675,6 @@ static void ene_tx_irqsim(unsigned long data)
 	spin_unlock_irqrestore(&dev->hw_lock, flags);
 }
 
-/* Read properities of hw sample buffer */
-static void ene_setup_hw_buffer(struct ene_device *dev)
-{
-	u16 tmp;
-
-	ene_read_hw_pointer(dev);
-	dev->r_pointer = dev->w_pointer;
-
-	if (!dev->hw_extra_buffer) {
-		dev->buffer_len = ENE_FW_PACKET_SIZE * 2;
-		return;
-	}
-
-	tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER);
-	tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER+1) << 8;
-	dev->extra_buf1_address = tmp;
-
-	dev->extra_buf1_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 2);
-
-	tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 3);
-	tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 4) << 8;
-	dev->extra_buf2_address = tmp;
-
-	dev->extra_buf2_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 5);
-
-	dev->buffer_len = dev->extra_buf1_len + dev->extra_buf2_len + 8;
-
-	ene_notice("Hardware uses 2 extended buffers:");
-	ene_notice("  0x%04x - len : %d", dev->extra_buf1_address,
-						dev->extra_buf1_len);
-	ene_notice("  0x%04x - len : %d", dev->extra_buf2_address,
-						dev->extra_buf2_len);
-
-	ene_notice("Total buffer len = %d", dev->buffer_len);
-
-	if (dev->buffer_len > 64 || dev->buffer_len < 16)
-		goto error;
-
-	if (dev->extra_buf1_address > 0xFBFC ||
-					dev->extra_buf1_address < 0xEC00)
-		goto error;
-
-	if (dev->extra_buf2_address > 0xFBFC ||
-					dev->extra_buf2_address < 0xEC00)
-		goto error;
-
-	if (dev->r_pointer > dev->buffer_len)
-		goto error;
-
-	ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
-	return;
-error:
-	ene_warn("Error validating extra buffers, device probably won't work");
-	dev->hw_extra_buffer = false;
-	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
-}
-
-
-/* Restore the pointers to extra buffers - to make module reload work*/
-static void ene_restore_extra_buffer(struct ene_device *dev)
-{
-	if (!dev->hw_extra_buffer)
-		return;
-
-	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 0,
-				dev->extra_buf1_address & 0xFF);
-	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 1,
-				dev->extra_buf1_address >> 8);
-	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 2, dev->extra_buf1_len);
-
-	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 3,
-				dev->extra_buf2_address & 0xFF);
-	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 4,
-				dev->extra_buf2_address >> 8);
-	ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 5,
-				dev->extra_buf2_len);
-	ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
-}
-
 
 /* read irq status and ack it */
 static int ene_irq_status(struct ene_device *dev)
@@ -632,66 +719,6 @@ static int ene_irq_status(struct ene_device *dev)
 	return retval;
 }
 
-/* Read hardware write pointer */
-static void ene_read_hw_pointer(struct ene_device *dev)
-{
-	if (dev->hw_extra_buffer)
-		dev->w_pointer = ene_read_reg(dev, ENE_FW_RX_POINTER);
-	else
-		dev->w_pointer = ene_read_reg(dev, ENE_FW2)
-			& ENE_FW2_BUF_WPTR ? 0 : ENE_FW_PACKET_SIZE;
-
-	dbg_verbose("RB: HW write pointer: %02x, driver read pointer: %02x",
-		dev->w_pointer, dev->r_pointer);
-}
-
-/* Gets address of next sample from HW ring buffer */
-static int ene_get_sample_reg(struct ene_device *dev)
-{
-	int r_pointer;
-
-	if (dev->r_pointer == dev->w_pointer) {
-		dbg_verbose("RB: hit end, try update w_pointer");
-		ene_read_hw_pointer(dev);
-	}
-
-	if (dev->r_pointer == dev->w_pointer) {
-		dbg_verbose("RB: end of data at %d", dev->r_pointer);
-		return 0;
-	}
-
-	dbg_verbose("RB: reading at offset %d", dev->r_pointer);
-	r_pointer = dev->r_pointer;
-
-	dev->r_pointer++;
-	if (dev->r_pointer == dev->buffer_len)
-		dev->r_pointer = 0;
-
-	dbg_verbose("RB: next read will be from offset %d", dev->r_pointer);
-
-	if (r_pointer < 8) {
-		dbg_verbose("RB: read at main buffer at %d", r_pointer);
-		return ENE_FW_SAMPLE_BUFFER + r_pointer;
-	}
-
-	r_pointer -= 8;
-
-	if (r_pointer < dev->extra_buf1_len) {
-		dbg_verbose("RB: read at 1st extra buffer at %d", r_pointer);
-		return dev->extra_buf1_address + r_pointer;
-	}
-
-	r_pointer -= dev->extra_buf1_len;
-
-	if (r_pointer < dev->extra_buf2_len) {
-		dbg_verbose("RB: read at 2nd extra buffer at %d", r_pointer);
-		return dev->extra_buf2_address + r_pointer;
-	}
-
-	dbg("attempt to read beyong ring bufer end");
-	return 0;
-}
-
 /* interrupt handler */
 static irqreturn_t ene_isr(int irq, void *data)
 {
@@ -706,7 +733,7 @@ static irqreturn_t ene_isr(int irq, void *data)
 	spin_lock_irqsave(&dev->hw_lock, flags);
 
 	dbg_verbose("ISR called");
-	ene_read_hw_pointer(dev);
+	ene_rx_read_hw_pointer(dev);
 	irq_status = ene_irq_status(dev);
 
 	if (!irq_status)
@@ -738,7 +765,7 @@ static irqreturn_t ene_isr(int irq, void *data)
 
 	while (1) {
 
-		reg = ene_get_sample_reg(dev);
+		reg = ene_rx_get_sample_reg(dev);
 
 		dbg_verbose("next sample to read at: %04x", reg);
 		if (!reg)
@@ -788,17 +815,28 @@ unlock:
 }
 
 /* Initialize default settings */
-static void ene_setup_settings(struct ene_device *dev)
+static void ene_setup_default_settings(struct ene_device *dev)
 {
 	dev->tx_period = 32;
 	dev->tx_duty_cycle = 50; /*%*/
 	dev->transmitter_mask = 0x03;
-	dev->learning_enabled = learning_mode;
+	dev->learning_mode_enabled = learning_mode_force;
 
 	/* Set reasonable default timeout */
 	dev->props->timeout = MS_TO_NS(150000);
 }
 
+/* Upload all hardware settings at once. Used at load and resume time */
+static void ene_setup_hw_settings(struct ene_device *dev)
+{
+	if (dev->hw_learning_and_tx_capable) {
+		ene_tx_set_carrier(dev);
+		ene_tx_set_transmitters(dev);
+	}
+
+	ene_rx_setup(dev);
+}
+
 /* outside interface: called on first open*/
 static int ene_open(void *data)
 {
@@ -826,7 +864,6 @@ static void ene_close(void *data)
 static int ene_set_tx_mask(void *data, u32 tx_mask)
 {
 	struct ene_device *dev = (struct ene_device *)data;
-	unsigned long flags;
 	dbg("TX: attempt to set transmitter mask %02x", tx_mask);
 
 	/* invalid txmask */
@@ -836,9 +873,8 @@ static int ene_set_tx_mask(void *data, u32 tx_mask)
 		return 2;
 	}
 
-	spin_lock_irqsave(&dev->hw_lock, flags);
 	dev->transmitter_mask = tx_mask;
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
+	ene_tx_set_transmitters(dev);
 	return 0;
 }
 
@@ -846,7 +882,6 @@ static int ene_set_tx_mask(void *data, u32 tx_mask)
 static int ene_set_tx_carrier(void *data, u32 carrier)
 {
 	struct ene_device *dev = (struct ene_device *)data;
-	unsigned long flags;
 	u32 period = 2000000 / carrier;
 
 	dbg("TX: attempt to set tx carrier to %d kHz", carrier);
@@ -855,16 +890,12 @@ static int ene_set_tx_carrier(void *data, u32 carrier)
 			period < ENE_CIRMOD_PRD_MIN)) {
 
 		dbg("TX: out of range %d-%d kHz carrier",
-			2000 / ENE_CIRMOD_PRD_MIN,
-			2000 / ENE_CIRMOD_PRD_MAX);
-
+			2000 / ENE_CIRMOD_PRD_MIN, 2000 / ENE_CIRMOD_PRD_MAX);
 		return -1;
 	}
 
-	dbg("TX: set carrier to %d kHz", carrier);
-	spin_lock_irqsave(&dev->hw_lock, flags);
 	dev->tx_period = period;
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
+	ene_tx_set_carrier(dev);
 	return 0;
 }
 
@@ -872,15 +903,9 @@ static int ene_set_tx_carrier(void *data, u32 carrier)
 static int ene_set_tx_duty_cycle(void *data, u32 duty_cycle)
 {
 	struct ene_device *dev = (struct ene_device *)data;
-	unsigned long flags;
-
 	dbg("TX: setting duty cycle to %d%%", duty_cycle);
-
-	BUG_ON(!duty_cycle || duty_cycle >= 100);
-
-	spin_lock_irqsave(&dev->hw_lock, flags);
 	dev->tx_duty_cycle = duty_cycle;
-	spin_unlock_irqrestore(&dev->hw_lock, flags);
+	ene_tx_set_carrier(dev);
 	return 0;
 }
 
@@ -889,11 +914,11 @@ static int ene_set_learning_mode(void *data, int enable)
 {
 	struct ene_device *dev = (struct ene_device *)data;
 	unsigned long flags;
-	if (enable == dev->learning_enabled)
+	if (enable == dev->learning_mode_enabled)
 		return 0;
 
 	spin_lock_irqsave(&dev->hw_lock, flags);
-	dev->learning_enabled = enable;
+	dev->learning_mode_enabled = enable;
 	ene_rx_disable(dev);
 	ene_rx_setup(dev);
 	ene_rx_enable(dev);
@@ -919,16 +944,12 @@ static int ene_set_carrier_report(void *data, int enable)
 }
 
 /* outside interface: enable or disable idle mode */
-static void ene_rx_set_idle(void *data, bool idle)
+static void ene_set_idle(void *data, bool idle)
 {
-	struct ene_device *dev = (struct ene_device *)data;
-
-	if (!idle)
-		return;
-
-	dbg("RX: stopping the receiver");
-	ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
-	ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
+	if (idle) {
+		ene_rx_reset((struct ene_device *)data);
+		dbg("RX: end of data");
+	}
 }
 
 /* outside interface: transmit */
@@ -949,7 +970,7 @@ static int ene_transmit(void *data, int *buf, u32 n)
 
 	spin_lock_irqsave(&dev->hw_lock, flags);
 
-	ene_tx_prepare(dev);
+	ene_tx_enable(dev);
 
 	/* Transmit first two samples */
 	ene_tx_sample(dev);
@@ -960,7 +981,7 @@ static int ene_transmit(void *data, int *buf, u32 n)
 	if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) {
 		dbg("TX: timeout");
 		spin_lock_irqsave(&dev->hw_lock, flags);
-		ene_tx_complete(dev);
+		ene_tx_disable(dev);
 		spin_unlock_irqrestore(&dev->hw_lock, flags);
 	} else
 		dbg("TX: done");
@@ -1031,14 +1052,14 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 	}
 
 	if (!dev->hw_learning_and_tx_capable)
-		learning_mode = false;
+		learning_mode_force = false;
 
 	ir_props->driver_type = RC_DRIVER_IR_RAW;
 	ir_props->allowed_protos = IR_TYPE_ALL;
 	ir_props->priv = dev;
 	ir_props->open = ene_open;
 	ir_props->close = ene_close;
-	ir_props->s_idle = ene_rx_set_idle;
+	ir_props->s_idle = ene_set_idle;
 
 	dev->props = ir_props;
 	dev->idev = input_dev;
@@ -1053,9 +1074,9 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 		ir_props->s_carrier_report = ene_set_carrier_report;
 	}
 
-	ene_setup_hw_buffer(dev);
-	ene_setup_settings(dev);
-	ene_rx_setup(dev);
+	ene_rx_setup_hw_buffer(dev);
+	ene_setup_default_settings(dev);
+	ene_setup_hw_settings(dev);
 
 	device_set_wakeup_capable(&pnp_dev->dev, true);
 	device_set_wakeup_enable(&pnp_dev->dev, true);
@@ -1092,7 +1113,7 @@ static void ene_remove(struct pnp_dev *pnp_dev)
 
 	spin_lock_irqsave(&dev->hw_lock, flags);
 	ene_rx_disable(dev);
-	ene_restore_extra_buffer(dev);
+	ene_rx_restore_hw_buffer(dev);
 	spin_unlock_irqrestore(&dev->hw_lock, flags);
 
 	free_irq(dev->irq, dev);
@@ -1123,10 +1144,11 @@ static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
 static int ene_resume(struct pnp_dev *pnp_dev)
 {
 	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
-	if (dev->rx_enabled) {
-		ene_rx_setup(dev);
+	ene_setup_hw_settings(dev);
+
+	if (dev->rx_enabled)
 		ene_rx_enable(dev);
-	}
+
 	ene_enable_wake(dev, false);
 	return 0;
 }
@@ -1173,8 +1195,8 @@ static void ene_exit(void)
 module_param(sample_period, int, S_IRUGO);
 MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)");
 
-module_param(learning_mode, bool, S_IRUGO);
-MODULE_PARM_DESC(learning_mode, "Enable learning mode by default");
+module_param(learning_mode_force, bool, S_IRUGO);
+MODULE_PARM_DESC(learning_mode_force, "Enable learning mode by default");
 
 module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level");
diff --git a/drivers/media/IR/ene_ir.h b/drivers/media/IR/ene_ir.h
index 39c707b..f587066 100644
--- a/drivers/media/IR/ene_ir.h
+++ b/drivers/media/IR/ene_ir.h
@@ -215,7 +215,7 @@ struct ene_device {
 
 	/* HW features */
 	int hw_revision;			/* hardware revision */
-	bool hw_use_gpio_0a;			/* gpio40 is demodulated input*/
+	bool hw_use_gpio_0a;			/* gpio0a is demodulated input*/
 	bool hw_extra_buffer;			/* hardware has 'extra buffer' */
 	bool hw_fan_input;			/* fan input is IR data source */
 	bool hw_learning_and_tx_capable;	/* learning & tx capable */
@@ -252,11 +252,11 @@ struct ene_device {
 	int transmitter_mask;
 
 	/* RX settings */
-	bool learning_enabled;			/* learning input enabled */
+	bool learning_mode_enabled;		/* learning input enabled */
 	bool carrier_detect_enabled;		/* carrier detect enabled */
 	int rx_period_adjust;
 	bool rx_enabled;
 };
 
 static int ene_irq_status(struct ene_device *dev);
-static void ene_read_hw_pointer(struct ene_device *dev);
+static void ene_rx_read_hw_pointer(struct ene_device *dev);
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] Remaining patches in my queue for IR
  2010-10-16 22:56 ` Maxim Levitsky
                   ` (3 preceding siblings ...)
  (?)
@ 2010-10-17  0:36 ` Andy Walls
  2010-10-17  1:07   ` Maxim Levitsky
  -1 siblings, 1 reply; 12+ messages in thread
From: Andy Walls @ 2010-10-17  0:36 UTC (permalink / raw)
  To: Maxim Levitsky
  Cc: lirc-list, Jarod Wilson, David Härdeman, mchehab,
	linux-input, linux-media

On Sun, 2010-10-17 at 00:56 +0200, Maxim Levitsky wrote:
> Hi,
> 
> This series is rebased on top of media_tree/staging/v2.6.37 only.
> Really this time, sorry for cheating, last time :-)
> 
> The first patch like we agreed extends the raw packets.
> It touches all drivers (except imon as it isn't a raw IR driver).

Will IR for the CX23885 and CX23888 still work given the changes?

Here's the relevant files that use struct ir_raw_event:

http://git.linuxtv.org/media_tree.git?a=blob;f=drivers/media/video/cx23885/cx23885-input.c;h=bb61870b8d6ed39d25c11aa676b55bd0a94dc235;hb=staging/v2.6.37
http://git.linuxtv.org/media_tree.git?a=blob;f=drivers/media/video/cx25840/cx25840-ir.c;h=c2b4c14dc9ab533ff524b3e301235d6bdc92e2b9;hb=staging/v2.6.37
http://git.linuxtv.org/media_tree.git?a=blob;f=drivers/media/video/cx23885/cx23888-ir.c;h=2502a0a6709783b8c01d5de639d759d097f0f1cd;hb=staging/v2.6.37

If needed, cx23885-input.c is where a fix can be made to ensure
structure fields are properly zeroed until I have time to fix he lower
level stuff.

Regards,
Andy

> Code is compile tested with all drivers, 
> and run tested with ENE and all receiver protocols
> (except the streamzap rc5 flavour)
> Since it also moves timeouts to lirc bridge, at least streazap driver
> should have its timeout gap support removed. I am afraid to break the code
> if I do so.
> 
> Other 2 patches are ENE specific, and don't touch anything else.
> 
> Please test other drivers.
> 
> Best regards,
> 	Maxim Levitsky
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] Remaining patches in my queue for IR
  2010-10-17  0:36 ` [PATCH 0/3] Remaining patches in my queue for IR Andy Walls
@ 2010-10-17  1:07   ` Maxim Levitsky
  0 siblings, 0 replies; 12+ messages in thread
From: Maxim Levitsky @ 2010-10-17  1:07 UTC (permalink / raw)
  To: Andy Walls
  Cc: lirc-list, Jarod Wilson, David Härdeman, mchehab,
	linux-input, linux-media

On Sat, 2010-10-16 at 20:36 -0400, Andy Walls wrote:
> On Sun, 2010-10-17 at 00:56 +0200, Maxim Levitsky wrote:
> > Hi,
> > 
> > This series is rebased on top of media_tree/staging/v2.6.37 only.
> > Really this time, sorry for cheating, last time :-)
> > 
> > The first patch like we agreed extends the raw packets.
> > It touches all drivers (except imon as it isn't a raw IR driver).
> 
> Will IR for the CX23885 and CX23888 still work given the changes?
> 
> Here's the relevant files that use struct ir_raw_event:
> 
> http://git.linuxtv.org/media_tree.git?a=blob;f=drivers/media/video/cx23885/cx23885-input.c;h=bb61870b8d6ed39d25c11aa676b55bd0a94dc235;hb=staging/v2.6.37
> http://git.linuxtv.org/media_tree.git?a=blob;f=drivers/media/video/cx25840/cx25840-ir.c;h=c2b4c14dc9ab533ff524b3e301235d6bdc92e2b9;hb=staging/v2.6.37
> http://git.linuxtv.org/media_tree.git?a=blob;f=drivers/media/video/cx23885/cx23888-ir.c;h=2502a0a6709783b8c01d5de639d759d097f0f1cd;hb=staging/v2.6.37
> 
> If needed, cx23885-input.c is where a fix can be made to ensure
> structure fields are properly zeroed until I have time to fix he lower
> level stuff.
> 
> Regards,
> Andy
Wasn't aware of this as I only looked at IR directory. Will grep the
sources for more drivers. 
Anyway the changes I propose are
straightforward, I shouldn't break the driver with it.
But of course if driver isn't updated it probably won't work.

Best regards,
	Maxim Levitsky



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] Remaining patches in my queue for IR
  2010-10-16 22:56 ` Maxim Levitsky
                   ` (4 preceding siblings ...)
  (?)
@ 2010-10-20 18:40 ` Jarod Wilson
  2010-10-22  0:17   ` Maxim Levitsky
  -1 siblings, 1 reply; 12+ messages in thread
From: Jarod Wilson @ 2010-10-20 18:40 UTC (permalink / raw)
  To: Maxim Levitsky
  Cc: lirc-list, Jarod Wilson, David Härdeman, mchehab,
	linux-input, linux-media

On Sun, Oct 17, 2010 at 12:56:27AM +0200, Maxim Levitsky wrote:
> Hi,
> 
> This series is rebased on top of media_tree/staging/v2.6.37 only.
> Really this time, sorry for cheating, last time :-)
> 
> The first patch like we agreed extends the raw packets.
> It touches all drivers (except imon as it isn't a raw IR driver).
> Code is compile tested with all drivers, 
> and run tested with ENE and all receiver protocols
> (except the streamzap rc5 flavour)
> Since it also moves timeouts to lirc bridge, at least streazap driver
> should have its timeout gap support removed. I am afraid to break the code
> if I do so.

I've tested both mceusb and streamzap with this patchset included, don't
see any ill side-effects. Only issue I really saw was that the raw event
init call was added somewhat superfluously to a number of drivers -- the
rawir struct its initializing was already kzalloc'd, so we're just
needlessly re-zero'ing it out again. Its not bad for clarity's sake, but
does add some unnecessary inefficiency.

-- 
Jarod Wilson
jarod@redhat.com


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] Remaining patches in my queue for IR
  2010-10-16 22:56 ` Maxim Levitsky
                   ` (5 preceding siblings ...)
  (?)
@ 2010-10-20 19:43 ` David Härdeman
  -1 siblings, 0 replies; 12+ messages in thread
From: David Härdeman @ 2010-10-20 19:43 UTC (permalink / raw)
  To: Maxim Levitsky; +Cc: Jarod Wilson, mchehab, linux-input, linux-media

On Sun, Oct 17, 2010 at 12:56:27AM +0200, Maxim Levitsky wrote:
> This series is rebased on top of media_tree/staging/v2.6.37 only.
> Really this time, sorry for cheating, last time :-)

On a related note, Mauro - is the plan still that I should wait for the 
large scancodes support for the input subsystem to land (somewhere 
around 2.6.37-rc1 supposedly) and then resend my patchset based on the 
media_tree/staging/v2.6.37 tree at that point?

-- 
David Härdeman

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/3] Remaining patches in my queue for IR
  2010-10-20 18:40 ` Jarod Wilson
@ 2010-10-22  0:17   ` Maxim Levitsky
  0 siblings, 0 replies; 12+ messages in thread
From: Maxim Levitsky @ 2010-10-22  0:17 UTC (permalink / raw)
  To: Jarod Wilson
  Cc: lirc-list, Jarod Wilson, David Härdeman, mchehab,
	linux-input, linux-media

On Wed, 2010-10-20 at 14:40 -0400, Jarod Wilson wrote:
> On Sun, Oct 17, 2010 at 12:56:27AM +0200, Maxim Levitsky wrote:
> > Hi,
> > 
> > This series is rebased on top of media_tree/staging/v2.6.37 only.
> > Really this time, sorry for cheating, last time :-)
> > 
> > The first patch like we agreed extends the raw packets.
> > It touches all drivers (except imon as it isn't a raw IR driver).
> > Code is compile tested with all drivers, 
> > and run tested with ENE and all receiver protocols
> > (except the streamzap rc5 flavour)
> > Since it also moves timeouts to lirc bridge, at least streazap driver
> > should have its timeout gap support removed. I am afraid to break the code
> > if I do so.
> 
> I've tested both mceusb and streamzap with this patchset included, don't
> see any ill side-effects. Only issue I really saw was that the raw event
> init call was added somewhat superfluously to a number of drivers -- the
> rawir struct its initializing was already kzalloc'd, so we're just
> needlessly re-zero'ing it out again. Its not bad for clarity's sake, but
> does add some unnecessary inefficiency.
Yes, I somewhat agree.

On the other hand, I had an idea to add a magic field to ir_raw_event to
guard against uninitialized uses.
(something like the struct scatterlist).

Don't know it that is worth it.
Or that I sound like a typical supporter of OOP style of abstracting
everything because sometime at the future there will be need to change
it..

Anyway, as Andy pointed, note that few drivers became broken due to that
patch because these don't initialize the ir_raw_event.

I will send a patch tomorrow (I was very busy this week).

Best regards,
	Maxim Levitsky


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/3] IR: extend ir_raw_event and do refactoring
  2010-10-16 22:56   ` Maxim Levitsky
  (?)
@ 2010-10-23 12:13   ` David Härdeman
  -1 siblings, 0 replies; 12+ messages in thread
From: David Härdeman @ 2010-10-23 12:13 UTC (permalink / raw)
  To: Maxim Levitsky; +Cc: lirc-list, Jarod Wilson, mchehab, linux-input, linux-media

On Sun, Oct 17, 2010 at 12:56:28AM +0200, Maxim Levitsky wrote:
> Add new event types for timeout & carrier report
> Move timeout handling from ir_raw_event_store_with_filter to
> ir-lirc-codec, where it is really needed.
> Now lirc bridge ensures proper gap handling.
> Extend lirc bridge for carrier & timeout reports
> 
> Note: all new ir_raw_event variables now should be initialized
> like that: DEFINE_IR_RAW_EVENT(ev);
> 
> To clean an existing event, use init_ir_raw_event(&ev);
> 
> Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
> Acked-by: Jarod Wilson <jarod@redhat.com>

I finally had a read-through of this patch. I like it. Note that we're 
going to have to change the decoders to also use the timeout event 
(since it basically behaves like a long space and e.g. the NEC decoder 
waits for the trailing space before sending a keydown). The same problem 
already exists for users of ir_raw_event_store_with_filter() though so 
the patch should still go in.

Acked-by: David Härdeman <david@hardeman.nu>


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2010-10-23 12:13 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-16 22:56 [PATCH 0/3] Remaining patches in my queue for IR Maxim Levitsky
2010-10-16 22:56 ` Maxim Levitsky
2010-10-16 22:56 ` [PATCH 1/3] IR: extend ir_raw_event and do refactoring Maxim Levitsky
2010-10-16 22:56   ` Maxim Levitsky
2010-10-23 12:13   ` David Härdeman
2010-10-16 22:56 ` [PATCH 2/3] IR: ene_ir: add support for carrier reports Maxim Levitsky
2010-10-16 22:56 ` [PATCH 3/3] IR: ene_ir: don't upload all settings on each TX packet Maxim Levitsky
2010-10-17  0:36 ` [PATCH 0/3] Remaining patches in my queue for IR Andy Walls
2010-10-17  1:07   ` Maxim Levitsky
2010-10-20 18:40 ` Jarod Wilson
2010-10-22  0:17   ` Maxim Levitsky
2010-10-20 19:43 ` David Härdeman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.