Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4651918a authored by Maxim Levitsky's avatar Maxim Levitsky Committed by Mauro Carvalho Chehab
Browse files

[media] IR: extend ir_raw_event and do refactoring



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: default avatarMaxim Levitsky <maximlevitsky@gmail.com>
Acked-by: default avatarJarod Wilson <jarod@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent fb249ca6
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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;

+12 −1
Original line number Diff line number Diff line
@@ -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
+3 −2
Original line number Diff line number Diff line
@@ -50,7 +50,8 @@ 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)) {
	if (!is_timing_event(ev)) {
		if (ev.reset)
			data->state = STATE_INACTIVE;
		return 0;
	}
+90 −38
Original line number Diff line number Diff line
@@ -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);

	/* 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.duration / 1000;
	if (ev.pulse)
		sample |= PULSE_BIT;
		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)
		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 = val * 1000;

		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;

+3 −2
Original line number Diff line number Diff line
@@ -54,7 +54,8 @@ 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)) {
	if (!is_timing_event(ev)) {
		if (ev.reset)
			data->state = STATE_INACTIVE;
		return 0;
	}
Loading