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

[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
...@@ -697,7 +697,7 @@ static irqreturn_t ene_isr(int irq, void *data) ...@@ -697,7 +697,7 @@ static irqreturn_t ene_isr(int irq, void *data)
unsigned long flags; unsigned long flags;
irqreturn_t retval = IRQ_NONE; irqreturn_t retval = IRQ_NONE;
struct ene_device *dev = (struct ene_device *)data; 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); spin_lock_irqsave(&dev->hw_lock, flags);
...@@ -898,7 +898,7 @@ static int ene_set_learning_mode(void *data, int enable) ...@@ -898,7 +898,7 @@ static int ene_set_learning_mode(void *data, int enable)
} }
/* outside interface: enable or disable idle mode */ /* 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; struct ene_device *dev = (struct ene_device *)data;
......
...@@ -88,6 +88,12 @@ struct ir_raw_event_ctrl { ...@@ -88,6 +88,12 @@ struct ir_raw_event_ctrl {
struct ir_input_dev *ir_dev; struct ir_input_dev *ir_dev;
struct lirc_driver *drv; struct lirc_driver *drv;
int carrier_low; int carrier_low;
ktime_t gap_start;
u64 gap_duration;
bool gap;
bool send_timeout_reports;
} lirc; } lirc;
}; };
...@@ -115,9 +121,14 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) ...@@ -115,9 +121,14 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
ev->duration -= 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_US(duration) DIV_ROUND_CLOSEST((duration), 1000)
#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") #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 * Routines from ir-sysfs.c - Meant to be called only internally inside
* ir-core * ir-core
......
...@@ -50,7 +50,8 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) ...@@ -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)) if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
return 0; return 0;
if (IS_RESET(ev)) { if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE; data->state = STATE_INACTIVE;
return 0; return 0;
} }
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) 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 ir_input_dev *ir_dev = input_get_drvdata(input_dev);
struct lirc_codec *lirc = &ir_dev->raw->lirc;
int sample; int sample;
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) 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) ...@@ -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) if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
return -EINVAL; return -EINVAL;
if (IS_RESET(ev)) /* Packet start */
if (ev.reset)
return 0; return 0;
IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", /* Carrier reports */
TO_US(ev.duration), TO_STR(ev.pulse)); 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; sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
if (ev.pulse) LIRC_SPACE(ev.duration / 1000);
sample |= PULSE_BIT; }
lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
(unsigned char *) &sample); (unsigned char *) &sample);
wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
return 0; return 0;
} }
...@@ -102,7 +139,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, ...@@ -102,7 +139,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
struct ir_input_dev *ir_dev; struct ir_input_dev *ir_dev;
int ret = 0; int ret = 0;
void *drv_data; void *drv_data;
__u32 val = 0; __u32 val = 0, tmp;
lirc = lirc_get_pdata(filep); lirc = lirc_get_pdata(filep);
if (!lirc) if (!lirc)
...@@ -130,22 +167,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, ...@@ -130,22 +167,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
case LIRC_SET_SEND_MODE: case LIRC_SET_SEND_MODE:
if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
return -EINVAL; return -EINVAL;
break; return 0;
/* TX settings */ /* TX settings */
case LIRC_SET_TRANSMITTER_MASK: case LIRC_SET_TRANSMITTER_MASK:
if (ir_dev->props->s_tx_mask) if (!ir_dev->props->s_tx_mask)
ret = ir_dev->props->s_tx_mask(drv_data, val);
else
return -EINVAL; return -EINVAL;
break;
return ir_dev->props->s_tx_mask(drv_data, val);
case LIRC_SET_SEND_CARRIER: case LIRC_SET_SEND_CARRIER:
if (ir_dev->props->s_tx_carrier) if (!ir_dev->props->s_tx_carrier)
ir_dev->props->s_tx_carrier(drv_data, val);
else
return -EINVAL; return -EINVAL;
break;
return ir_dev->props->s_tx_carrier(drv_data, val);
case LIRC_SET_SEND_DUTY_CYCLE: case LIRC_SET_SEND_DUTY_CYCLE:
if (!ir_dev->props->s_tx_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, ...@@ -154,39 +189,42 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
if (val <= 0 || val >= 100) if (val <= 0 || val >= 100)
return -EINVAL; return -EINVAL;
ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val); return ir_dev->props->s_tx_duty_cycle(drv_data, val);
break;
/* RX settings */ /* RX settings */
case LIRC_SET_REC_CARRIER: case LIRC_SET_REC_CARRIER:
if (ir_dev->props->s_rx_carrier_range) 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
return -ENOSYS; return -ENOSYS;
if (!ret) if (val <= 0)
ir_dev->raw->lirc.carrier_low = 0; return -EINVAL;
break;
return ir_dev->props->s_rx_carrier_range(drv_data,
ir_dev->raw->lirc.carrier_low, val);
case LIRC_SET_REC_CARRIER_RANGE: case LIRC_SET_REC_CARRIER_RANGE:
if (val >= 0) if (val <= 0)
ir_dev->raw->lirc.carrier_low = val; return -EINVAL;
break;
ir_dev->raw->lirc.carrier_low = val;
return 0;
case LIRC_GET_REC_RESOLUTION: case LIRC_GET_REC_RESOLUTION:
val = ir_dev->props->rx_resolution; val = ir_dev->props->rx_resolution;
break; break;
case LIRC_SET_WIDEBAND_RECEIVER: case LIRC_SET_WIDEBAND_RECEIVER:
if (ir_dev->props->s_learning_mode) if (!ir_dev->props->s_learning_mode)
return ir_dev->props->s_learning_mode(
ir_dev->props->priv, !!val);
else
return -ENOSYS; 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 */ /* Generic timeout support */
case LIRC_GET_MIN_TIMEOUT: case LIRC_GET_MIN_TIMEOUT:
if (!ir_dev->props->max_timeout) if (!ir_dev->props->max_timeout)
...@@ -201,10 +239,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, ...@@ -201,10 +239,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
break; break;
case LIRC_SET_REC_TIMEOUT: case LIRC_SET_REC_TIMEOUT:
if (val < ir_dev->props->min_timeout || if (!ir_dev->props->max_timeout)
val > 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; 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; break;
default: default:
...@@ -280,6 +328,10 @@ static int ir_lirc_register(struct input_dev *input_dev) ...@@ -280,6 +328,10 @@ static int ir_lirc_register(struct input_dev *input_dev)
if (ir_dev->props->s_learning_mode) if (ir_dev->props->s_learning_mode)
features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
if (ir_dev->props->s_carrier_report)
features |= LIRC_CAN_MEASURE_CARRIER;
if (ir_dev->props->max_timeout) if (ir_dev->props->max_timeout)
features |= LIRC_CAN_SET_REC_TIMEOUT; features |= LIRC_CAN_SET_REC_TIMEOUT;
......
...@@ -54,7 +54,8 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) ...@@ -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)) if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
return 0; return 0;
if (IS_RESET(ev)) { if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE; data->state = STATE_INACTIVE;
return 0; return 0;
} }
......
...@@ -174,7 +174,7 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev, ...@@ -174,7 +174,7 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev,
if (ir->idle && !ev->pulse) if (ir->idle && !ev->pulse)
return 0; return 0;
else if (ir->idle) 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) { if (!raw->this_ev.duration) {
raw->this_ev = *ev; raw->this_ev = *ev;
...@@ -187,48 +187,35 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev, ...@@ -187,48 +187,35 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev,
/* Enter idle mode if nessesary */ /* Enter idle mode if nessesary */
if (!ev->pulse && ir->props->timeout && if (!ev->pulse && ir->props->timeout &&
raw->this_ev.duration >= ir->props->timeout) raw->this_ev.duration >= ir->props->timeout) {
ir_raw_event_set_idle(input_dev, 1); ir_raw_event_set_idle(input_dev, true);
}
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); 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_input_dev *ir = input_get_drvdata(input_dev);
struct ir_raw_event_ctrl *raw = ir->raw; struct ir_raw_event_ctrl *raw = ir->raw;
ktime_t now;
u64 delta;
if (!ir->props) if (!ir->props || !ir->raw)
return; return;
if (!ir->raw) IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");
goto out;
if (idle) { if (idle) {
IR_dprintk(2, "enter idle mode\n"); raw->this_ev.timeout = true;
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);
ir_raw_event_store(input_dev, &raw->this_ev); ir_raw_event_store(input_dev, &raw->this_ev);
init_ir_raw_event(&raw->this_ev);
if (raw->this_ev.duration == IR_MAX_DURATION)
ir_raw_event_reset(input_dev);
raw->this_ev.duration = 0;
} }
out:
if (ir->props->s_idle) if (ir->props->s_idle)
ir->props->s_idle(ir->props->priv, idle); ir->props->s_idle(ir->props->priv, idle);
ir->idle = idle; ir->idle = idle;
......
...@@ -55,7 +55,8 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev) ...@@ -55,7 +55,8 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5)) if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
return 0; return 0;
if (IS_RESET(ev)) { if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE; data->state = STATE_INACTIVE;
return 0; return 0;
} }
......
...@@ -51,7 +51,8 @@ static int ir_rc5_sz_decode(struct input_dev *input_dev, struct ir_raw_event ev) ...@@ -51,7 +51,8 @@ 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)) if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5_SZ))
return 0; return 0;
if (IS_RESET(ev)) { if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE; data->state = STATE_INACTIVE;
return 0; return 0;
} }
......
...@@ -85,7 +85,8 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev) ...@@ -85,7 +85,8 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6)) if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
return 0; return 0;
if (IS_RESET(ev)) { if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE; data->state = STATE_INACTIVE;
return 0; return 0;
} }
......
...@@ -48,7 +48,8 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev) ...@@ -48,7 +48,8 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY)) if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
return 0; return 0;
if (IS_RESET(ev)) { if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE; data->state = STATE_INACTIVE;
return 0; return 0;
} }
......
...@@ -660,7 +660,7 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier) ...@@ -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) 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; int i, start_index = 0;
u8 hdr = MCE_CONTROL_HEADER; u8 hdr = MCE_CONTROL_HEADER;
...@@ -997,6 +997,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, ...@@ -997,6 +997,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
ir->len_in = maxp; ir->len_in = maxp;
ir->flags.microsoft_gen1 = is_microsoft_gen1; ir->flags.microsoft_gen1 = is_microsoft_gen1;
ir->flags.tx_mask_inverted = tx_mask_inverted; ir->flags.tx_mask_inverted = tx_mask_inverted;
init_ir_raw_event(&ir->rawir);
/* Saving usb interface data for use by the transmitter routine */ /* Saving usb interface data for use by the transmitter routine */
ir->usb_ep_in = ep_in; ir->usb_ep_in = ep_in;
......
...@@ -586,7 +586,7 @@ static void nvt_dump_rx_buf(struct nvt_dev *nvt) ...@@ -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) 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; unsigned int count;
u32 carrier; u32 carrier;
u8 sample; u8 sample;
...@@ -622,6 +622,8 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt) ...@@ -622,6 +622,8 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
} }
rawir.duration += nvt->rawir.duration; rawir.duration += nvt->rawir.duration;
init_ir_raw_event(&nvt->rawir);
nvt->rawir.duration = 0; nvt->rawir.duration = 0;
nvt->rawir.pulse = rawir.pulse; nvt->rawir.pulse = rawir.pulse;
...@@ -1016,6 +1018,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) ...@@ -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->nvt_lock);
spin_lock_init(&nvt->tx.lock); spin_lock_init(&nvt->tx.lock);
init_ir_raw_event(&nvt->rawir);
ret = -EBUSY; ret = -EBUSY;
/* now claim resources */ /* now claim resources */
......
...@@ -146,7 +146,7 @@ static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir) ...@@ -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, static void sz_push_full_pulse(struct streamzap_ir *sz,
unsigned char value) unsigned char value)
{ {
struct ir_raw_event rawir; DEFINE_IR_RAW_EVENT(rawir);
if (sz->idle) { if (sz->idle) {
long deltv; long deltv;
...@@ -193,7 +193,7 @@ static void sz_push_half_pulse(struct streamzap_ir *sz, ...@@ -193,7 +193,7 @@ static void sz_push_half_pulse(struct streamzap_ir *sz,
static void sz_push_full_space(struct streamzap_ir *sz, static void sz_push_full_space(struct streamzap_ir *sz,
unsigned char value) unsigned char value)
{ {
struct ir_raw_event rawir; DEFINE_IR_RAW_EVENT(rawir);
rawir.pulse = false; rawir.pulse = false;
rawir.duration = ((int) value) * SZ_RESOLUTION; rawir.duration = ((int) value) * SZ_RESOLUTION;
...@@ -270,7 +270,7 @@ static void streamzap_callback(struct urb *urb) ...@@ -270,7 +270,7 @@ static void streamzap_callback(struct urb *urb)
break; break;
case FullSpace: case FullSpace:
if (sz->buf_in[i] == SZ_TIMEOUT) { if (sz->buf_in[i] == SZ_TIMEOUT) {
struct ir_raw_event rawir; DEFINE_IR_RAW_EVENT(rawir);
rawir.pulse = false; rawir.pulse = false;
rawir.duration = timeout; rawir.duration = timeout;
......
...@@ -60,6 +60,7 @@ enum rc_driver_type { ...@@ -60,6 +60,7 @@ enum rc_driver_type {
* @s_idle: optional: enable/disable hardware idle mode, upon which, * @s_idle: optional: enable/disable hardware idle mode, upon which,
device doesn't interrupt host until it sees IR pulses device doesn't interrupt host until it sees IR pulses
* @s_learning_mode: enable wide band receiver used for learning * @s_learning_mode: enable wide band receiver used for learning
* @s_carrier_report: enable carrier reports
*/ */
struct ir_dev_props { struct ir_dev_props {
enum rc_driver_type driver_type; enum rc_driver_type driver_type;
...@@ -82,8 +83,9 @@ struct ir_dev_props { ...@@ -82,8 +83,9 @@ struct ir_dev_props {
int (*s_tx_duty_cycle)(void *priv, u32 duty_cycle); int (*s_tx_duty_cycle)(void *priv, u32 duty_cycle);
int (*s_rx_carrier_range)(void *priv, u32 min, u32 max); int (*s_rx_carrier_range)(void *priv, u32 min, u32 max);
int (*tx_ir)(void *priv, int *txbuf, u32 n); 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_learning_mode)(void *priv, int enable);
int (*s_carrier_report) (void *priv, int enable);
}; };
struct ir_input_dev { struct ir_input_dev {
...@@ -163,22 +165,48 @@ u32 ir_g_keycode_from_table(struct input_dev *input_dev, u32 scancode); ...@@ -163,22 +165,48 @@ u32 ir_g_keycode_from_table(struct input_dev *input_dev, u32 scancode);
/* From ir-raw-event.c */ /* From ir-raw-event.c */
struct ir_raw_event { struct ir_raw_event {
union {
u32 duration;
struct {
u32 carrier;
u8 duty_cycle;
};
};
unsigned pulse:1; unsigned pulse:1;
unsigned duration:31; 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); 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(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_edge(struct input_dev *input_dev, enum raw_event_type type);
int ir_raw_event_store_with_filter(struct input_dev *input_dev, int ir_raw_event_store_with_filter(struct input_dev *input_dev,
struct ir_raw_event *ev); 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) 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_store(input_dev, &ev);
ir_raw_event_handle(input_dev); ir_raw_event_handle(input_dev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment