|
@@ -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;
|
|
|
|