at v4.6 450 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 dev->timeout = tmp; 296 break; 297 298 case LIRC_SET_REC_TIMEOUT_REPORTS: 299 lirc->send_timeout_reports = !!val; 300 break; 301 302 default: 303 return lirc_dev_fop_ioctl(filep, cmd, arg); 304 } 305 306 if (_IOC_DIR(cmd) & _IOC_READ) 307 ret = put_user(val, argp); 308 309 return ret; 310} 311 312static int ir_lirc_open(void *data) 313{ 314 return 0; 315} 316 317static void ir_lirc_close(void *data) 318{ 319 return; 320} 321 322static const struct file_operations lirc_fops = { 323 .owner = THIS_MODULE, 324 .write = ir_lirc_transmit_ir, 325 .unlocked_ioctl = ir_lirc_ioctl, 326#ifdef CONFIG_COMPAT 327 .compat_ioctl = ir_lirc_ioctl, 328#endif 329 .read = lirc_dev_fop_read, 330 .poll = lirc_dev_fop_poll, 331 .open = lirc_dev_fop_open, 332 .release = lirc_dev_fop_close, 333 .llseek = no_llseek, 334}; 335 336static int ir_lirc_register(struct rc_dev *dev) 337{ 338 struct lirc_driver *drv; 339 struct lirc_buffer *rbuf; 340 int rc = -ENOMEM; 341 unsigned long features; 342 343 drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); 344 if (!drv) 345 return rc; 346 347 rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL); 348 if (!rbuf) 349 goto rbuf_alloc_failed; 350 351 rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE); 352 if (rc) 353 goto rbuf_init_failed; 354 355 features = LIRC_CAN_REC_MODE2; 356 if (dev->tx_ir) { 357 features |= LIRC_CAN_SEND_PULSE; 358 if (dev->s_tx_mask) 359 features |= LIRC_CAN_SET_TRANSMITTER_MASK; 360 if (dev->s_tx_carrier) 361 features |= LIRC_CAN_SET_SEND_CARRIER; 362 if (dev->s_tx_duty_cycle) 363 features |= LIRC_CAN_SET_SEND_DUTY_CYCLE; 364 } 365 366 if (dev->s_rx_carrier_range) 367 features |= LIRC_CAN_SET_REC_CARRIER | 368 LIRC_CAN_SET_REC_CARRIER_RANGE; 369 370 if (dev->s_learning_mode) 371 features |= LIRC_CAN_USE_WIDEBAND_RECEIVER; 372 373 if (dev->s_carrier_report) 374 features |= LIRC_CAN_MEASURE_CARRIER; 375 376 if (dev->max_timeout) 377 features |= LIRC_CAN_SET_REC_TIMEOUT; 378 379 snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", 380 dev->driver_name); 381 drv->minor = -1; 382 drv->features = features; 383 drv->data = &dev->raw->lirc; 384 drv->rbuf = rbuf; 385 drv->set_use_inc = &ir_lirc_open; 386 drv->set_use_dec = &ir_lirc_close; 387 drv->code_length = sizeof(struct ir_raw_event) * 8; 388 drv->fops = &lirc_fops; 389 drv->dev = &dev->dev; 390 drv->rdev = dev; 391 drv->owner = THIS_MODULE; 392 393 drv->minor = lirc_register_driver(drv); 394 if (drv->minor < 0) { 395 rc = -ENODEV; 396 goto lirc_register_failed; 397 } 398 399 dev->raw->lirc.drv = drv; 400 dev->raw->lirc.dev = dev; 401 return 0; 402 403lirc_register_failed: 404rbuf_init_failed: 405 kfree(rbuf); 406rbuf_alloc_failed: 407 kfree(drv); 408 409 return rc; 410} 411 412static int ir_lirc_unregister(struct rc_dev *dev) 413{ 414 struct lirc_codec *lirc = &dev->raw->lirc; 415 416 lirc_unregister_driver(lirc->drv->minor); 417 lirc_buffer_free(lirc->drv->rbuf); 418 kfree(lirc->drv->rbuf); 419 kfree(lirc->drv); 420 421 return 0; 422} 423 424static struct ir_raw_handler lirc_handler = { 425 .protocols = 0, 426 .decode = ir_lirc_decode, 427 .raw_register = ir_lirc_register, 428 .raw_unregister = ir_lirc_unregister, 429}; 430 431static int __init ir_lirc_codec_init(void) 432{ 433 ir_raw_handler_register(&lirc_handler); 434 435 printk(KERN_INFO "IR LIRC bridge handler initialized\n"); 436 return 0; 437} 438 439static void __exit ir_lirc_codec_exit(void) 440{ 441 ir_raw_handler_unregister(&lirc_handler); 442} 443 444module_init(ir_lirc_codec_init); 445module_exit(ir_lirc_codec_exit); 446 447MODULE_LICENSE("GPL"); 448MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); 449MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); 450MODULE_DESCRIPTION("LIRC IR handler bridge");