at v4.8 453 lines 10 kB view raw
1/* ir-lirc-codec.c - rc-core to classic lirc interface bridge 2 * 3 * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation version 2 of the License. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15#include <linux/sched.h> 16#include <linux/wait.h> 17#include <linux/module.h> 18#include <media/lirc.h> 19#include <media/lirc_dev.h> 20#include <media/rc-core.h> 21#include "rc-core-priv.h" 22 23#define LIRCBUF_SIZE 256 24 25/** 26 * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the 27 * lircd userspace daemon for decoding. 28 * @input_dev: the struct rc_dev descriptor of the device 29 * @duration: the struct ir_raw_event descriptor of the pulse/space 30 * 31 * This function returns -EINVAL if the lirc interfaces aren't wired up. 32 */ 33static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev) 34{ 35 struct lirc_codec *lirc = &dev->raw->lirc; 36 int sample; 37 38 if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf) 39 return -EINVAL; 40 41 /* Packet start */ 42 if (ev.reset) { 43 /* Userspace expects a long space event before the start of 44 * the signal to use as a sync. This may be done with repeat 45 * packets and normal samples. But if a reset has been sent 46 * then we assume that a long time has passed, so we send a 47 * space with the maximum time value. */ 48 sample = LIRC_SPACE(LIRC_VALUE_MASK); 49 IR_dprintk(2, "delivering reset sync space to lirc_dev\n"); 50 51 /* Carrier reports */ 52 } else if (ev.carrier_report) { 53 sample = LIRC_FREQUENCY(ev.carrier); 54 IR_dprintk(2, "carrier report (freq: %d)\n", sample); 55 56 /* Packet end */ 57 } else if (ev.timeout) { 58 59 if (lirc->gap) 60 return 0; 61 62 lirc->gap_start = ktime_get(); 63 lirc->gap = true; 64 lirc->gap_duration = ev.duration; 65 66 if (!lirc->send_timeout_reports) 67 return 0; 68 69 sample = LIRC_TIMEOUT(ev.duration / 1000); 70 IR_dprintk(2, "timeout report (duration: %d)\n", sample); 71 72 /* Normal sample */ 73 } else { 74 75 if (lirc->gap) { 76 int gap_sample; 77 78 lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(), 79 lirc->gap_start)); 80 81 /* Convert to ms and cap by LIRC_VALUE_MASK */ 82 do_div(lirc->gap_duration, 1000); 83 lirc->gap_duration = min(lirc->gap_duration, 84 (u64)LIRC_VALUE_MASK); 85 86 gap_sample = LIRC_SPACE(lirc->gap_duration); 87 lirc_buffer_write(dev->raw->lirc.drv->rbuf, 88 (unsigned char *) &gap_sample); 89 lirc->gap = false; 90 } 91 92 sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) : 93 LIRC_SPACE(ev.duration / 1000); 94 IR_dprintk(2, "delivering %uus %s to lirc_dev\n", 95 TO_US(ev.duration), TO_STR(ev.pulse)); 96 } 97 98 lirc_buffer_write(dev->raw->lirc.drv->rbuf, 99 (unsigned char *) &sample); 100 wake_up(&dev->raw->lirc.drv->rbuf->wait_poll); 101 102 return 0; 103} 104 105static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, 106 size_t n, loff_t *ppos) 107{ 108 struct lirc_codec *lirc; 109 struct rc_dev *dev; 110 unsigned int *txbuf; /* buffer with values to transmit */ 111 ssize_t ret = -EINVAL; 112 size_t count; 113 ktime_t start; 114 s64 towait; 115 unsigned int duration = 0; /* signal duration in us */ 116 int i; 117 118 start = ktime_get(); 119 120 lirc = lirc_get_pdata(file); 121 if (!lirc) 122 return -EFAULT; 123 124 if (n < sizeof(unsigned) || n % sizeof(unsigned)) 125 return -EINVAL; 126 127 count = n / sizeof(unsigned); 128 if (count > LIRCBUF_SIZE || count % 2 == 0) 129 return -EINVAL; 130 131 txbuf = memdup_user(buf, n); 132 if (IS_ERR(txbuf)) 133 return PTR_ERR(txbuf); 134 135 dev = lirc->dev; 136 if (!dev) { 137 ret = -EFAULT; 138 goto out; 139 } 140 141 if (!dev->tx_ir) { 142 ret = -ENOSYS; 143 goto out; 144 } 145 146 for (i = 0; i < count; i++) { 147 if (txbuf[i] > IR_MAX_DURATION / 1000 - duration || !txbuf[i]) { 148 ret = -EINVAL; 149 goto out; 150 } 151 152 duration += txbuf[i]; 153 } 154 155 ret = dev->tx_ir(dev, txbuf, count); 156 if (ret < 0) 157 goto out; 158 159 for (duration = i = 0; i < ret; i++) 160 duration += txbuf[i]; 161 162 ret *= sizeof(unsigned int); 163 164 /* 165 * The lircd gap calculation expects the write function to 166 * wait for the actual IR signal to be transmitted before 167 * returning. 168 */ 169 towait = ktime_us_delta(ktime_add_us(start, duration), ktime_get()); 170 if (towait > 0) { 171 set_current_state(TASK_INTERRUPTIBLE); 172 schedule_timeout(usecs_to_jiffies(towait)); 173 } 174 175out: 176 kfree(txbuf); 177 return ret; 178} 179 180static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, 181 unsigned long arg) 182{ 183 struct lirc_codec *lirc; 184 struct rc_dev *dev; 185 u32 __user *argp = (u32 __user *)(arg); 186 int ret = 0; 187 __u32 val = 0, tmp; 188 189 lirc = lirc_get_pdata(filep); 190 if (!lirc) 191 return -EFAULT; 192 193 dev = lirc->dev; 194 if (!dev) 195 return -EFAULT; 196 197 if (_IOC_DIR(cmd) & _IOC_WRITE) { 198 ret = get_user(val, argp); 199 if (ret) 200 return ret; 201 } 202 203 switch (cmd) { 204 205 /* legacy support */ 206 case LIRC_GET_SEND_MODE: 207 val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK; 208 break; 209 210 case LIRC_SET_SEND_MODE: 211 if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) 212 return -EINVAL; 213 return 0; 214 215 /* TX settings */ 216 case LIRC_SET_TRANSMITTER_MASK: 217 if (!dev->s_tx_mask) 218 return -ENOSYS; 219 220 return dev->s_tx_mask(dev, val); 221 222 case LIRC_SET_SEND_CARRIER: 223 if (!dev->s_tx_carrier) 224 return -ENOSYS; 225 226 return dev->s_tx_carrier(dev, val); 227 228 case LIRC_SET_SEND_DUTY_CYCLE: 229 if (!dev->s_tx_duty_cycle) 230 return -ENOSYS; 231 232 if (val <= 0 || val >= 100) 233 return -EINVAL; 234 235 return dev->s_tx_duty_cycle(dev, val); 236 237 /* RX settings */ 238 case LIRC_SET_REC_CARRIER: 239 if (!dev->s_rx_carrier_range) 240 return -ENOSYS; 241 242 if (val <= 0) 243 return -EINVAL; 244 245 return dev->s_rx_carrier_range(dev, 246 dev->raw->lirc.carrier_low, 247 val); 248 249 case LIRC_SET_REC_CARRIER_RANGE: 250 if (val <= 0) 251 return -EINVAL; 252 253 dev->raw->lirc.carrier_low = val; 254 return 0; 255 256 case LIRC_GET_REC_RESOLUTION: 257 val = dev->rx_resolution; 258 break; 259 260 case LIRC_SET_WIDEBAND_RECEIVER: 261 if (!dev->s_learning_mode) 262 return -ENOSYS; 263 264 return dev->s_learning_mode(dev, !!val); 265 266 case LIRC_SET_MEASURE_CARRIER_MODE: 267 if (!dev->s_carrier_report) 268 return -ENOSYS; 269 270 return dev->s_carrier_report(dev, !!val); 271 272 /* Generic timeout support */ 273 case LIRC_GET_MIN_TIMEOUT: 274 if (!dev->max_timeout) 275 return -ENOSYS; 276 val = dev->min_timeout / 1000; 277 break; 278 279 case LIRC_GET_MAX_TIMEOUT: 280 if (!dev->max_timeout) 281 return -ENOSYS; 282 val = dev->max_timeout / 1000; 283 break; 284 285 case LIRC_SET_REC_TIMEOUT: 286 if (!dev->max_timeout) 287 return -ENOSYS; 288 289 tmp = val * 1000; 290 291 if (tmp < dev->min_timeout || 292 tmp > dev->max_timeout) 293 return -EINVAL; 294 295 if (dev->s_timeout) 296 ret = dev->s_timeout(dev, tmp); 297 if (!ret) 298 dev->timeout = tmp; 299 break; 300 301 case LIRC_SET_REC_TIMEOUT_REPORTS: 302 lirc->send_timeout_reports = !!val; 303 break; 304 305 default: 306 return lirc_dev_fop_ioctl(filep, cmd, arg); 307 } 308 309 if (_IOC_DIR(cmd) & _IOC_READ) 310 ret = put_user(val, argp); 311 312 return ret; 313} 314 315static int ir_lirc_open(void *data) 316{ 317 return 0; 318} 319 320static void ir_lirc_close(void *data) 321{ 322 return; 323} 324 325static const struct file_operations lirc_fops = { 326 .owner = THIS_MODULE, 327 .write = ir_lirc_transmit_ir, 328 .unlocked_ioctl = ir_lirc_ioctl, 329#ifdef CONFIG_COMPAT 330 .compat_ioctl = ir_lirc_ioctl, 331#endif 332 .read = lirc_dev_fop_read, 333 .poll = lirc_dev_fop_poll, 334 .open = lirc_dev_fop_open, 335 .release = lirc_dev_fop_close, 336 .llseek = no_llseek, 337}; 338 339static int ir_lirc_register(struct rc_dev *dev) 340{ 341 struct lirc_driver *drv; 342 struct lirc_buffer *rbuf; 343 int rc = -ENOMEM; 344 unsigned long features; 345 346 drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); 347 if (!drv) 348 return rc; 349 350 rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL); 351 if (!rbuf) 352 goto rbuf_alloc_failed; 353 354 rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE); 355 if (rc) 356 goto rbuf_init_failed; 357 358 features = LIRC_CAN_REC_MODE2; 359 if (dev->tx_ir) { 360 features |= LIRC_CAN_SEND_PULSE; 361 if (dev->s_tx_mask) 362 features |= LIRC_CAN_SET_TRANSMITTER_MASK; 363 if (dev->s_tx_carrier) 364 features |= LIRC_CAN_SET_SEND_CARRIER; 365 if (dev->s_tx_duty_cycle) 366 features |= LIRC_CAN_SET_SEND_DUTY_CYCLE; 367 } 368 369 if (dev->s_rx_carrier_range) 370 features |= LIRC_CAN_SET_REC_CARRIER | 371 LIRC_CAN_SET_REC_CARRIER_RANGE; 372 373 if (dev->s_learning_mode) 374 features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; 375 376 if (dev->s_carrier_report) 377 features |= LIRC_CAN_MEASURE_CARRIER; 378 379 if (dev->max_timeout) 380 features |= LIRC_CAN_SET_REC_TIMEOUT; 381 382 snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", 383 dev->driver_name); 384 drv->minor = -1; 385 drv->features = features; 386 drv->data = &dev->raw->lirc; 387 drv->rbuf = rbuf; 388 drv->set_use_inc = &ir_lirc_open; 389 drv->set_use_dec = &ir_lirc_close; 390 drv->code_length = sizeof(struct ir_raw_event) * 8; 391 drv->fops = &lirc_fops; 392 drv->dev = &dev->dev; 393 drv->rdev = dev; 394 drv->owner = THIS_MODULE; 395 396 drv->minor = lirc_register_driver(drv); 397 if (drv->minor < 0) { 398 rc = -ENODEV; 399 goto lirc_register_failed; 400 } 401 402 dev->raw->lirc.drv = drv; 403 dev->raw->lirc.dev = dev; 404 return 0; 405 406lirc_register_failed: 407rbuf_init_failed: 408 kfree(rbuf); 409rbuf_alloc_failed: 410 kfree(drv); 411 412 return rc; 413} 414 415static int ir_lirc_unregister(struct rc_dev *dev) 416{ 417 struct lirc_codec *lirc = &dev->raw->lirc; 418 419 lirc_unregister_driver(lirc->drv->minor); 420 lirc_buffer_free(lirc->drv->rbuf); 421 kfree(lirc->drv->rbuf); 422 kfree(lirc->drv); 423 424 return 0; 425} 426 427static struct ir_raw_handler lirc_handler = { 428 .protocols = 0, 429 .decode = ir_lirc_decode, 430 .raw_register = ir_lirc_register, 431 .raw_unregister = ir_lirc_unregister, 432}; 433 434static int __init ir_lirc_codec_init(void) 435{ 436 ir_raw_handler_register(&lirc_handler); 437 438 printk(KERN_INFO "IR LIRC bridge handler initialized\n"); 439 return 0; 440} 441 442static void __exit ir_lirc_codec_exit(void) 443{ 444 ir_raw_handler_unregister(&lirc_handler); 445} 446 447module_init(ir_lirc_codec_init); 448module_exit(ir_lirc_codec_exit); 449 450MODULE_LICENSE("GPL"); 451MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); 452MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); 453MODULE_DESCRIPTION("LIRC IR handler bridge");