diff options
Diffstat (limited to 'drivers/media/IR/ir-lirc-codec.c')
| -rw-r--r-- | drivers/media/IR/ir-lirc-codec.c | 135 |
1 files changed, 95 insertions, 40 deletions
diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c index 1983cd3f3994..9fc0db9d344d 100644 --- a/drivers/media/IR/ir-lirc-codec.c +++ b/drivers/media/IR/ir-lirc-codec.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) | 32 | static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) |
| 33 | { | 33 | { |
| 34 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | 34 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); |
| 35 | struct lirc_codec *lirc = &ir_dev->raw->lirc; | ||
| 35 | int sample; | 36 | int sample; |
| 36 | 37 | ||
| 37 | if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) | 38 | 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 | if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) | 41 | if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) |
| 41 | return -EINVAL; | 42 | return -EINVAL; |
| 42 | 43 | ||
| 43 | if (IS_RESET(ev)) | 44 | /* Packet start */ |
| 45 | if (ev.reset) | ||
| 44 | return 0; | 46 | return 0; |
| 45 | 47 | ||
| 46 | IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", | 48 | /* Carrier reports */ |
| 47 | TO_US(ev.duration), TO_STR(ev.pulse)); | 49 | if (ev.carrier_report) { |
| 50 | sample = LIRC_FREQUENCY(ev.carrier); | ||
| 51 | |||
| 52 | /* Packet end */ | ||
| 53 | } else if (ev.timeout) { | ||
| 54 | |||
| 55 | if (lirc->gap) | ||
| 56 | return 0; | ||
| 57 | |||
| 58 | lirc->gap_start = ktime_get(); | ||
| 59 | lirc->gap = true; | ||
| 60 | lirc->gap_duration = ev.duration; | ||
| 61 | |||
| 62 | if (!lirc->send_timeout_reports) | ||
| 63 | return 0; | ||
| 64 | |||
| 65 | sample = LIRC_TIMEOUT(ev.duration / 1000); | ||
| 48 | 66 | ||
| 49 | sample = ev.duration / 1000; | 67 | /* Normal sample */ |
| 50 | if (ev.pulse) | 68 | } else { |
| 51 | sample |= PULSE_BIT; | 69 | |
| 70 | if (lirc->gap) { | ||
| 71 | int gap_sample; | ||
| 72 | |||
| 73 | lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(), | ||
| 74 | lirc->gap_start)); | ||
| 75 | |||
| 76 | /* Convert to ms and cap by LIRC_VALUE_MASK */ | ||
| 77 | do_div(lirc->gap_duration, 1000); | ||
| 78 | lirc->gap_duration = min(lirc->gap_duration, | ||
| 79 | (u64)LIRC_VALUE_MASK); | ||
| 80 | |||
| 81 | gap_sample = LIRC_SPACE(lirc->gap_duration); | ||
| 82 | lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, | ||
| 83 | (unsigned char *) &gap_sample); | ||
| 84 | lirc->gap = false; | ||
| 85 | } | ||
| 86 | |||
| 87 | sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) : | ||
| 88 | LIRC_SPACE(ev.duration / 1000); | ||
| 89 | } | ||
| 52 | 90 | ||
| 53 | lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, | 91 | lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, |
| 54 | (unsigned char *) &sample); | 92 | (unsigned char *) &sample); |
| 55 | wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); | 93 | wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); |
| 56 | 94 | ||
| 57 | |||
| 58 | return 0; | 95 | return 0; |
| 59 | } | 96 | } |
| 60 | 97 | ||
| @@ -102,7 +139,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
| 102 | struct ir_input_dev *ir_dev; | 139 | struct ir_input_dev *ir_dev; |
| 103 | int ret = 0; | 140 | int ret = 0; |
| 104 | void *drv_data; | 141 | void *drv_data; |
| 105 | unsigned long val = 0; | 142 | __u32 val = 0, tmp; |
| 106 | 143 | ||
| 107 | lirc = lirc_get_pdata(filep); | 144 | lirc = lirc_get_pdata(filep); |
| 108 | if (!lirc) | 145 | if (!lirc) |
| @@ -115,7 +152,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
| 115 | drv_data = ir_dev->props->priv; | 152 | drv_data = ir_dev->props->priv; |
| 116 | 153 | ||
| 117 | if (_IOC_DIR(cmd) & _IOC_WRITE) { | 154 | if (_IOC_DIR(cmd) & _IOC_WRITE) { |
| 118 | ret = get_user(val, (unsigned long *)arg); | 155 | ret = get_user(val, (__u32 *)arg); |
| 119 | if (ret) | 156 | if (ret) |
| 120 | return ret; | 157 | return ret; |
| 121 | } | 158 | } |
| @@ -130,22 +167,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
| 130 | case LIRC_SET_SEND_MODE: | 167 | case LIRC_SET_SEND_MODE: |
| 131 | if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) | 168 | if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) |
| 132 | return -EINVAL; | 169 | return -EINVAL; |
| 133 | break; | 170 | return 0; |
| 134 | 171 | ||
| 135 | /* TX settings */ | 172 | /* TX settings */ |
| 136 | case LIRC_SET_TRANSMITTER_MASK: | 173 | case LIRC_SET_TRANSMITTER_MASK: |
| 137 | if (ir_dev->props->s_tx_mask) | 174 | if (!ir_dev->props->s_tx_mask) |
| 138 | ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); | ||
| 139 | else | ||
| 140 | return -EINVAL; | 175 | return -EINVAL; |
| 141 | break; | 176 | |
| 177 | return ir_dev->props->s_tx_mask(drv_data, val); | ||
| 142 | 178 | ||
| 143 | case LIRC_SET_SEND_CARRIER: | 179 | case LIRC_SET_SEND_CARRIER: |
| 144 | if (ir_dev->props->s_tx_carrier) | 180 | if (!ir_dev->props->s_tx_carrier) |
| 145 | ir_dev->props->s_tx_carrier(drv_data, (u32)val); | ||
| 146 | else | ||
| 147 | return -EINVAL; | 181 | return -EINVAL; |
| 148 | break; | 182 | |
| 183 | return ir_dev->props->s_tx_carrier(drv_data, val); | ||
| 149 | 184 | ||
| 150 | case LIRC_SET_SEND_DUTY_CYCLE: | 185 | case LIRC_SET_SEND_DUTY_CYCLE: |
| 151 | if (!ir_dev->props->s_tx_duty_cycle) | 186 | if (!ir_dev->props->s_tx_duty_cycle) |
| @@ -154,39 +189,42 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
| 154 | if (val <= 0 || val >= 100) | 189 | if (val <= 0 || val >= 100) |
| 155 | return -EINVAL; | 190 | return -EINVAL; |
| 156 | 191 | ||
| 157 | ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val); | 192 | return ir_dev->props->s_tx_duty_cycle(drv_data, val); |
| 158 | break; | ||
| 159 | 193 | ||
| 160 | /* RX settings */ | 194 | /* RX settings */ |
| 161 | case LIRC_SET_REC_CARRIER: | 195 | case LIRC_SET_REC_CARRIER: |
| 162 | if (ir_dev->props->s_rx_carrier_range) | 196 | if (!ir_dev->props->s_rx_carrier_range) |
| 163 | ret = ir_dev->props->s_rx_carrier_range( | ||
| 164 | ir_dev->props->priv, | ||
| 165 | ir_dev->raw->lirc.carrier_low, val); | ||
| 166 | else | ||
| 167 | return -ENOSYS; | 197 | return -ENOSYS; |
| 168 | 198 | ||
| 169 | if (!ret) | 199 | if (val <= 0) |
| 170 | ir_dev->raw->lirc.carrier_low = 0; | 200 | return -EINVAL; |
| 171 | break; | 201 | |
| 202 | return ir_dev->props->s_rx_carrier_range(drv_data, | ||
| 203 | ir_dev->raw->lirc.carrier_low, val); | ||
| 172 | 204 | ||
| 173 | case LIRC_SET_REC_CARRIER_RANGE: | 205 | case LIRC_SET_REC_CARRIER_RANGE: |
| 174 | if (val >= 0) | 206 | if (val <= 0) |
| 175 | ir_dev->raw->lirc.carrier_low = val; | 207 | return -EINVAL; |
| 176 | break; | ||
| 177 | 208 | ||
| 209 | ir_dev->raw->lirc.carrier_low = val; | ||
| 210 | return 0; | ||
| 178 | 211 | ||
| 179 | case LIRC_GET_REC_RESOLUTION: | 212 | case LIRC_GET_REC_RESOLUTION: |
| 180 | val = ir_dev->props->rx_resolution; | 213 | val = ir_dev->props->rx_resolution; |
| 181 | break; | 214 | break; |
| 182 | 215 | ||
| 183 | case LIRC_SET_WIDEBAND_RECEIVER: | 216 | case LIRC_SET_WIDEBAND_RECEIVER: |
| 184 | if (ir_dev->props->s_learning_mode) | 217 | if (!ir_dev->props->s_learning_mode) |
| 185 | return ir_dev->props->s_learning_mode( | ||
| 186 | ir_dev->props->priv, !!val); | ||
| 187 | else | ||
| 188 | return -ENOSYS; | 218 | return -ENOSYS; |
| 189 | 219 | ||
| 220 | return ir_dev->props->s_learning_mode(drv_data, !!val); | ||
| 221 | |||
| 222 | case LIRC_SET_MEASURE_CARRIER_MODE: | ||
| 223 | if (!ir_dev->props->s_carrier_report) | ||
| 224 | return -ENOSYS; | ||
| 225 | |||
| 226 | return ir_dev->props->s_carrier_report(drv_data, !!val); | ||
| 227 | |||
| 190 | /* Generic timeout support */ | 228 | /* Generic timeout support */ |
| 191 | case LIRC_GET_MIN_TIMEOUT: | 229 | case LIRC_GET_MIN_TIMEOUT: |
| 192 | if (!ir_dev->props->max_timeout) | 230 | if (!ir_dev->props->max_timeout) |
| @@ -201,10 +239,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
| 201 | break; | 239 | break; |
| 202 | 240 | ||
| 203 | case LIRC_SET_REC_TIMEOUT: | 241 | case LIRC_SET_REC_TIMEOUT: |
| 204 | if (val < ir_dev->props->min_timeout || | 242 | if (!ir_dev->props->max_timeout) |
| 205 | val > ir_dev->props->max_timeout) | 243 | return -ENOSYS; |
| 206 | return -EINVAL; | 244 | |
| 207 | ir_dev->props->timeout = val * 1000; | 245 | tmp = val * 1000; |
| 246 | |||
| 247 | if (tmp < ir_dev->props->min_timeout || | ||
| 248 | tmp > ir_dev->props->max_timeout) | ||
| 249 | return -EINVAL; | ||
| 250 | |||
| 251 | ir_dev->props->timeout = tmp; | ||
| 252 | break; | ||
| 253 | |||
| 254 | case LIRC_SET_REC_TIMEOUT_REPORTS: | ||
| 255 | lirc->send_timeout_reports = !!val; | ||
| 208 | break; | 256 | break; |
| 209 | 257 | ||
| 210 | default: | 258 | default: |
| @@ -212,7 +260,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, | |||
| 212 | } | 260 | } |
| 213 | 261 | ||
| 214 | if (_IOC_DIR(cmd) & _IOC_READ) | 262 | if (_IOC_DIR(cmd) & _IOC_READ) |
| 215 | ret = put_user(val, (unsigned long *)arg); | 263 | ret = put_user(val, (__u32 *)arg); |
| 216 | 264 | ||
| 217 | return ret; | 265 | return ret; |
| 218 | } | 266 | } |
| @@ -231,6 +279,9 @@ static struct file_operations lirc_fops = { | |||
| 231 | .owner = THIS_MODULE, | 279 | .owner = THIS_MODULE, |
| 232 | .write = ir_lirc_transmit_ir, | 280 | .write = ir_lirc_transmit_ir, |
| 233 | .unlocked_ioctl = ir_lirc_ioctl, | 281 | .unlocked_ioctl = ir_lirc_ioctl, |
| 282 | #ifdef CONFIG_COMPAT | ||
| 283 | .compat_ioctl = ir_lirc_ioctl, | ||
| 284 | #endif | ||
| 234 | .read = lirc_dev_fop_read, | 285 | .read = lirc_dev_fop_read, |
| 235 | .poll = lirc_dev_fop_poll, | 286 | .poll = lirc_dev_fop_poll, |
| 236 | .open = lirc_dev_fop_open, | 287 | .open = lirc_dev_fop_open, |
| @@ -278,6 +329,10 @@ static int ir_lirc_register(struct input_dev *input_dev) | |||
| 278 | if (ir_dev->props->s_learning_mode) | 329 | if (ir_dev->props->s_learning_mode) |
| 279 | features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; | 330 | features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; |
| 280 | 331 | ||
| 332 | if (ir_dev->props->s_carrier_report) | ||
| 333 | features |= LIRC_CAN_MEASURE_CARRIER; | ||
| 334 | |||
| 335 | |||
| 281 | if (ir_dev->props->max_timeout) | 336 | if (ir_dev->props->max_timeout) |
| 282 | features |= LIRC_CAN_SET_REC_TIMEOUT; | 337 | features |= LIRC_CAN_SET_REC_TIMEOUT; |
| 283 | 338 | ||
