diff options
Diffstat (limited to 'drivers/media/IR/lirc_dev.c')
-rw-r--r-- | drivers/media/IR/lirc_dev.c | 133 |
1 files changed, 89 insertions, 44 deletions
diff --git a/drivers/media/IR/lirc_dev.c b/drivers/media/IR/lirc_dev.c index 202581808bdc..8418b14ee4d2 100644 --- a/drivers/media/IR/lirc_dev.c +++ b/drivers/media/IR/lirc_dev.c | |||
@@ -57,13 +57,12 @@ struct irctl { | |||
57 | 57 | ||
58 | struct task_struct *task; | 58 | struct task_struct *task; |
59 | long jiffies_to_wait; | 59 | long jiffies_to_wait; |
60 | |||
61 | struct cdev cdev; | ||
62 | }; | 60 | }; |
63 | 61 | ||
64 | static DEFINE_MUTEX(lirc_dev_lock); | 62 | static DEFINE_MUTEX(lirc_dev_lock); |
65 | 63 | ||
66 | static struct irctl *irctls[MAX_IRCTL_DEVICES]; | 64 | static struct irctl *irctls[MAX_IRCTL_DEVICES]; |
65 | static struct cdev cdevs[MAX_IRCTL_DEVICES]; | ||
67 | 66 | ||
68 | /* Only used for sysfs but defined to void otherwise */ | 67 | /* Only used for sysfs but defined to void otherwise */ |
69 | static struct class *lirc_class; | 68 | static struct class *lirc_class; |
@@ -71,15 +70,13 @@ static struct class *lirc_class; | |||
71 | /* helper function | 70 | /* helper function |
72 | * initializes the irctl structure | 71 | * initializes the irctl structure |
73 | */ | 72 | */ |
74 | static void init_irctl(struct irctl *ir) | 73 | static void lirc_irctl_init(struct irctl *ir) |
75 | { | 74 | { |
76 | dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n", | ||
77 | ir->d.name, ir->d.minor); | ||
78 | mutex_init(&ir->irctl_lock); | 75 | mutex_init(&ir->irctl_lock); |
79 | ir->d.minor = NOPLUG; | 76 | ir->d.minor = NOPLUG; |
80 | } | 77 | } |
81 | 78 | ||
82 | static void cleanup(struct irctl *ir) | 79 | static void lirc_irctl_cleanup(struct irctl *ir) |
83 | { | 80 | { |
84 | dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor); | 81 | dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor); |
85 | 82 | ||
@@ -96,7 +93,7 @@ static void cleanup(struct irctl *ir) | |||
96 | * reads key codes from driver and puts them into buffer | 93 | * reads key codes from driver and puts them into buffer |
97 | * returns 0 on success | 94 | * returns 0 on success |
98 | */ | 95 | */ |
99 | static int add_to_buf(struct irctl *ir) | 96 | static int lirc_add_to_buf(struct irctl *ir) |
100 | { | 97 | { |
101 | if (ir->d.add_to_buf) { | 98 | if (ir->d.add_to_buf) { |
102 | int res = -ENODATA; | 99 | int res = -ENODATA; |
@@ -139,7 +136,7 @@ static int lirc_thread(void *irctl) | |||
139 | } | 136 | } |
140 | if (kthread_should_stop()) | 137 | if (kthread_should_stop()) |
141 | break; | 138 | break; |
142 | if (!add_to_buf(ir)) | 139 | if (!lirc_add_to_buf(ir)) |
143 | wake_up_interruptible(&ir->buf->wait_poll); | 140 | wake_up_interruptible(&ir->buf->wait_poll); |
144 | } else { | 141 | } else { |
145 | set_current_state(TASK_INTERRUPTIBLE); | 142 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -154,12 +151,15 @@ static int lirc_thread(void *irctl) | |||
154 | } | 151 | } |
155 | 152 | ||
156 | 153 | ||
157 | static struct file_operations fops = { | 154 | static struct file_operations lirc_dev_fops = { |
158 | .owner = THIS_MODULE, | 155 | .owner = THIS_MODULE, |
159 | .read = lirc_dev_fop_read, | 156 | .read = lirc_dev_fop_read, |
160 | .write = lirc_dev_fop_write, | 157 | .write = lirc_dev_fop_write, |
161 | .poll = lirc_dev_fop_poll, | 158 | .poll = lirc_dev_fop_poll, |
162 | .unlocked_ioctl = lirc_dev_fop_ioctl, | 159 | .unlocked_ioctl = lirc_dev_fop_ioctl, |
160 | #ifdef CONFIG_COMPAT | ||
161 | .compat_ioctl = lirc_dev_fop_ioctl, | ||
162 | #endif | ||
163 | .open = lirc_dev_fop_open, | 163 | .open = lirc_dev_fop_open, |
164 | .release = lirc_dev_fop_close, | 164 | .release = lirc_dev_fop_close, |
165 | .llseek = noop_llseek, | 165 | .llseek = noop_llseek, |
@@ -169,19 +169,20 @@ static int lirc_cdev_add(struct irctl *ir) | |||
169 | { | 169 | { |
170 | int retval; | 170 | int retval; |
171 | struct lirc_driver *d = &ir->d; | 171 | struct lirc_driver *d = &ir->d; |
172 | struct cdev *cdev = &cdevs[d->minor]; | ||
172 | 173 | ||
173 | if (d->fops) { | 174 | if (d->fops) { |
174 | cdev_init(&ir->cdev, d->fops); | 175 | cdev_init(cdev, d->fops); |
175 | ir->cdev.owner = d->owner; | 176 | cdev->owner = d->owner; |
176 | } else { | 177 | } else { |
177 | cdev_init(&ir->cdev, &fops); | 178 | cdev_init(cdev, &lirc_dev_fops); |
178 | ir->cdev.owner = THIS_MODULE; | 179 | cdev->owner = THIS_MODULE; |
179 | } | 180 | } |
180 | kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor); | 181 | kobject_set_name(&cdev->kobj, "lirc%d", d->minor); |
181 | 182 | ||
182 | retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); | 183 | retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); |
183 | if (retval) | 184 | if (retval) |
184 | kobject_put(&ir->cdev.kobj); | 185 | kobject_put(&cdev->kobj); |
185 | 186 | ||
186 | return retval; | 187 | return retval; |
187 | } | 188 | } |
@@ -202,6 +203,12 @@ int lirc_register_driver(struct lirc_driver *d) | |||
202 | goto out; | 203 | goto out; |
203 | } | 204 | } |
204 | 205 | ||
206 | if (!d->dev) { | ||
207 | printk(KERN_ERR "%s: dev pointer not filled in!\n", __func__); | ||
208 | err = -EINVAL; | ||
209 | goto out; | ||
210 | } | ||
211 | |||
205 | if (MAX_IRCTL_DEVICES <= d->minor) { | 212 | if (MAX_IRCTL_DEVICES <= d->minor) { |
206 | dev_err(d->dev, "lirc_dev: lirc_register_driver: " | 213 | dev_err(d->dev, "lirc_dev: lirc_register_driver: " |
207 | "\"minor\" must be between 0 and %d (%d)!\n", | 214 | "\"minor\" must be between 0 and %d (%d)!\n", |
@@ -277,7 +284,7 @@ int lirc_register_driver(struct lirc_driver *d) | |||
277 | err = -ENOMEM; | 284 | err = -ENOMEM; |
278 | goto out_lock; | 285 | goto out_lock; |
279 | } | 286 | } |
280 | init_irctl(ir); | 287 | lirc_irctl_init(ir); |
281 | irctls[minor] = ir; | 288 | irctls[minor] = ir; |
282 | d->minor = minor; | 289 | d->minor = minor; |
283 | 290 | ||
@@ -316,7 +323,6 @@ int lirc_register_driver(struct lirc_driver *d) | |||
316 | d->features = LIRC_CAN_REC_LIRCCODE; | 323 | d->features = LIRC_CAN_REC_LIRCCODE; |
317 | 324 | ||
318 | ir->d = *d; | 325 | ir->d = *d; |
319 | ir->d.minor = minor; | ||
320 | 326 | ||
321 | device_create(lirc_class, ir->d.dev, | 327 | device_create(lirc_class, ir->d.dev, |
322 | MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL, | 328 | MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL, |
@@ -357,21 +363,28 @@ EXPORT_SYMBOL(lirc_register_driver); | |||
357 | int lirc_unregister_driver(int minor) | 363 | int lirc_unregister_driver(int minor) |
358 | { | 364 | { |
359 | struct irctl *ir; | 365 | struct irctl *ir; |
366 | struct cdev *cdev; | ||
360 | 367 | ||
361 | if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { | 368 | if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { |
362 | printk(KERN_ERR "lirc_dev: lirc_unregister_driver: " | 369 | printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between " |
363 | "\"minor (%d)\" must be between 0 and %d!\n", | 370 | "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1); |
364 | minor, MAX_IRCTL_DEVICES-1); | ||
365 | return -EBADRQC; | 371 | return -EBADRQC; |
366 | } | 372 | } |
367 | 373 | ||
368 | ir = irctls[minor]; | 374 | ir = irctls[minor]; |
375 | if (!ir) { | ||
376 | printk(KERN_ERR "lirc_dev: %s: failed to get irctl struct " | ||
377 | "for minor %d!\n", __func__, minor); | ||
378 | return -ENOENT; | ||
379 | } | ||
380 | |||
381 | cdev = &cdevs[minor]; | ||
369 | 382 | ||
370 | mutex_lock(&lirc_dev_lock); | 383 | mutex_lock(&lirc_dev_lock); |
371 | 384 | ||
372 | if (ir->d.minor != minor) { | 385 | if (ir->d.minor != minor) { |
373 | printk(KERN_ERR "lirc_dev: lirc_unregister_driver: " | 386 | printk(KERN_ERR "lirc_dev: %s: minor (%d) device not " |
374 | "minor (%d) device not registered!", minor); | 387 | "registered!\n", __func__, minor); |
375 | mutex_unlock(&lirc_dev_lock); | 388 | mutex_unlock(&lirc_dev_lock); |
376 | return -ENOENT; | 389 | return -ENOENT; |
377 | } | 390 | } |
@@ -390,12 +403,11 @@ int lirc_unregister_driver(int minor) | |||
390 | wake_up_interruptible(&ir->buf->wait_poll); | 403 | wake_up_interruptible(&ir->buf->wait_poll); |
391 | mutex_lock(&ir->irctl_lock); | 404 | mutex_lock(&ir->irctl_lock); |
392 | ir->d.set_use_dec(ir->d.data); | 405 | ir->d.set_use_dec(ir->d.data); |
393 | module_put(ir->d.owner); | 406 | module_put(cdev->owner); |
394 | mutex_unlock(&ir->irctl_lock); | 407 | mutex_unlock(&ir->irctl_lock); |
395 | cdev_del(&ir->cdev); | ||
396 | } else { | 408 | } else { |
397 | cleanup(ir); | 409 | lirc_irctl_cleanup(ir); |
398 | cdev_del(&ir->cdev); | 410 | cdev_del(cdev); |
399 | kfree(ir); | 411 | kfree(ir); |
400 | irctls[minor] = NULL; | 412 | irctls[minor] = NULL; |
401 | } | 413 | } |
@@ -409,6 +421,7 @@ EXPORT_SYMBOL(lirc_unregister_driver); | |||
409 | int lirc_dev_fop_open(struct inode *inode, struct file *file) | 421 | int lirc_dev_fop_open(struct inode *inode, struct file *file) |
410 | { | 422 | { |
411 | struct irctl *ir; | 423 | struct irctl *ir; |
424 | struct cdev *cdev; | ||
412 | int retval = 0; | 425 | int retval = 0; |
413 | 426 | ||
414 | if (iminor(inode) >= MAX_IRCTL_DEVICES) { | 427 | if (iminor(inode) >= MAX_IRCTL_DEVICES) { |
@@ -425,7 +438,6 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) | |||
425 | retval = -ENODEV; | 438 | retval = -ENODEV; |
426 | goto error; | 439 | goto error; |
427 | } | 440 | } |
428 | file->private_data = ir; | ||
429 | 441 | ||
430 | dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); | 442 | dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); |
431 | 443 | ||
@@ -439,13 +451,14 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file) | |||
439 | goto error; | 451 | goto error; |
440 | } | 452 | } |
441 | 453 | ||
442 | if (try_module_get(ir->d.owner)) { | 454 | cdev = &cdevs[iminor(inode)]; |
443 | ++ir->open; | 455 | if (try_module_get(cdev->owner)) { |
456 | ir->open++; | ||
444 | retval = ir->d.set_use_inc(ir->d.data); | 457 | retval = ir->d.set_use_inc(ir->d.data); |
445 | 458 | ||
446 | if (retval) { | 459 | if (retval) { |
447 | module_put(ir->d.owner); | 460 | module_put(cdev->owner); |
448 | --ir->open; | 461 | ir->open--; |
449 | } else { | 462 | } else { |
450 | lirc_buffer_clear(ir->buf); | 463 | lirc_buffer_clear(ir->buf); |
451 | } | 464 | } |
@@ -469,17 +482,24 @@ EXPORT_SYMBOL(lirc_dev_fop_open); | |||
469 | int lirc_dev_fop_close(struct inode *inode, struct file *file) | 482 | int lirc_dev_fop_close(struct inode *inode, struct file *file) |
470 | { | 483 | { |
471 | struct irctl *ir = irctls[iminor(inode)]; | 484 | struct irctl *ir = irctls[iminor(inode)]; |
485 | struct cdev *cdev = &cdevs[iminor(inode)]; | ||
486 | |||
487 | if (!ir) { | ||
488 | printk(KERN_ERR "%s: called with invalid irctl\n", __func__); | ||
489 | return -EINVAL; | ||
490 | } | ||
472 | 491 | ||
473 | dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor); | 492 | dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor); |
474 | 493 | ||
475 | WARN_ON(mutex_lock_killable(&lirc_dev_lock)); | 494 | WARN_ON(mutex_lock_killable(&lirc_dev_lock)); |
476 | 495 | ||
477 | --ir->open; | 496 | ir->open--; |
478 | if (ir->attached) { | 497 | if (ir->attached) { |
479 | ir->d.set_use_dec(ir->d.data); | 498 | ir->d.set_use_dec(ir->d.data); |
480 | module_put(ir->d.owner); | 499 | module_put(cdev->owner); |
481 | } else { | 500 | } else { |
482 | cleanup(ir); | 501 | lirc_irctl_cleanup(ir); |
502 | cdev_del(cdev); | ||
483 | irctls[ir->d.minor] = NULL; | 503 | irctls[ir->d.minor] = NULL; |
484 | kfree(ir); | 504 | kfree(ir); |
485 | } | 505 | } |
@@ -495,6 +515,11 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) | |||
495 | struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; | 515 | struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; |
496 | unsigned int ret; | 516 | unsigned int ret; |
497 | 517 | ||
518 | if (!ir) { | ||
519 | printk(KERN_ERR "%s: called with invalid irctl\n", __func__); | ||
520 | return POLLERR; | ||
521 | } | ||
522 | |||
498 | dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor); | 523 | dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor); |
499 | 524 | ||
500 | if (!ir->attached) { | 525 | if (!ir->attached) { |
@@ -521,9 +546,14 @@ EXPORT_SYMBOL(lirc_dev_fop_poll); | |||
521 | 546 | ||
522 | long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 547 | long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
523 | { | 548 | { |
524 | unsigned long mode; | 549 | __u32 mode; |
525 | int result = 0; | 550 | int result = 0; |
526 | struct irctl *ir = file->private_data; | 551 | struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; |
552 | |||
553 | if (!ir) { | ||
554 | printk(KERN_ERR "lirc_dev: %s: no irctl found!\n", __func__); | ||
555 | return -ENODEV; | ||
556 | } | ||
527 | 557 | ||
528 | dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", | 558 | dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", |
529 | ir->d.name, ir->d.minor, cmd); | 559 | ir->d.name, ir->d.minor, cmd); |
@@ -538,7 +568,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
538 | 568 | ||
539 | switch (cmd) { | 569 | switch (cmd) { |
540 | case LIRC_GET_FEATURES: | 570 | case LIRC_GET_FEATURES: |
541 | result = put_user(ir->d.features, (unsigned long *)arg); | 571 | result = put_user(ir->d.features, (__u32 *)arg); |
542 | break; | 572 | break; |
543 | case LIRC_GET_REC_MODE: | 573 | case LIRC_GET_REC_MODE: |
544 | if (!(ir->d.features & LIRC_CAN_REC_MASK)) { | 574 | if (!(ir->d.features & LIRC_CAN_REC_MASK)) { |
@@ -548,7 +578,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
548 | 578 | ||
549 | result = put_user(LIRC_REC2MODE | 579 | result = put_user(LIRC_REC2MODE |
550 | (ir->d.features & LIRC_CAN_REC_MASK), | 580 | (ir->d.features & LIRC_CAN_REC_MASK), |
551 | (unsigned long *)arg); | 581 | (__u32 *)arg); |
552 | break; | 582 | break; |
553 | case LIRC_SET_REC_MODE: | 583 | case LIRC_SET_REC_MODE: |
554 | if (!(ir->d.features & LIRC_CAN_REC_MASK)) { | 584 | if (!(ir->d.features & LIRC_CAN_REC_MASK)) { |
@@ -556,7 +586,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
556 | break; | 586 | break; |
557 | } | 587 | } |
558 | 588 | ||
559 | result = get_user(mode, (unsigned long *)arg); | 589 | result = get_user(mode, (__u32 *)arg); |
560 | if (!result && !(LIRC_MODE2REC(mode) & ir->d.features)) | 590 | if (!result && !(LIRC_MODE2REC(mode) & ir->d.features)) |
561 | result = -EINVAL; | 591 | result = -EINVAL; |
562 | /* | 592 | /* |
@@ -565,7 +595,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
565 | */ | 595 | */ |
566 | break; | 596 | break; |
567 | case LIRC_GET_LENGTH: | 597 | case LIRC_GET_LENGTH: |
568 | result = put_user(ir->d.code_length, (unsigned long *)arg); | 598 | result = put_user(ir->d.code_length, (__u32 *)arg); |
569 | break; | 599 | break; |
570 | case LIRC_GET_MIN_TIMEOUT: | 600 | case LIRC_GET_MIN_TIMEOUT: |
571 | if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || | 601 | if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || |
@@ -574,7 +604,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
574 | break; | 604 | break; |
575 | } | 605 | } |
576 | 606 | ||
577 | result = put_user(ir->d.min_timeout, (unsigned long *)arg); | 607 | result = put_user(ir->d.min_timeout, (__u32 *)arg); |
578 | break; | 608 | break; |
579 | case LIRC_GET_MAX_TIMEOUT: | 609 | case LIRC_GET_MAX_TIMEOUT: |
580 | if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || | 610 | if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || |
@@ -583,7 +613,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
583 | break; | 613 | break; |
584 | } | 614 | } |
585 | 615 | ||
586 | result = put_user(ir->d.max_timeout, (unsigned long *)arg); | 616 | result = put_user(ir->d.max_timeout, (__u32 *)arg); |
587 | break; | 617 | break; |
588 | default: | 618 | default: |
589 | result = -EINVAL; | 619 | result = -EINVAL; |
@@ -604,12 +634,21 @@ ssize_t lirc_dev_fop_read(struct file *file, | |||
604 | loff_t *ppos) | 634 | loff_t *ppos) |
605 | { | 635 | { |
606 | struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; | 636 | struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; |
607 | unsigned char buf[ir->chunk_size]; | 637 | unsigned char *buf; |
608 | int ret = 0, written = 0; | 638 | int ret = 0, written = 0; |
609 | DECLARE_WAITQUEUE(wait, current); | 639 | DECLARE_WAITQUEUE(wait, current); |
610 | 640 | ||
641 | if (!ir) { | ||
642 | printk(KERN_ERR "%s: called with invalid irctl\n", __func__); | ||
643 | return -ENODEV; | ||
644 | } | ||
645 | |||
611 | dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); | 646 | dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); |
612 | 647 | ||
648 | buf = kzalloc(ir->chunk_size, GFP_KERNEL); | ||
649 | if (!buf) | ||
650 | return -ENOMEM; | ||
651 | |||
613 | if (mutex_lock_interruptible(&ir->irctl_lock)) | 652 | if (mutex_lock_interruptible(&ir->irctl_lock)) |
614 | return -ERESTARTSYS; | 653 | return -ERESTARTSYS; |
615 | if (!ir->attached) { | 654 | if (!ir->attached) { |
@@ -681,6 +720,7 @@ ssize_t lirc_dev_fop_read(struct file *file, | |||
681 | mutex_unlock(&ir->irctl_lock); | 720 | mutex_unlock(&ir->irctl_lock); |
682 | 721 | ||
683 | out_unlocked: | 722 | out_unlocked: |
723 | kfree(buf); | ||
684 | dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n", | 724 | dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n", |
685 | ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret); | 725 | ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret); |
686 | 726 | ||
@@ -709,6 +749,11 @@ ssize_t lirc_dev_fop_write(struct file *file, const char *buffer, | |||
709 | { | 749 | { |
710 | struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; | 750 | struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; |
711 | 751 | ||
752 | if (!ir) { | ||
753 | printk(KERN_ERR "%s: called with invalid irctl\n", __func__); | ||
754 | return -ENODEV; | ||
755 | } | ||
756 | |||
712 | dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor); | 757 | dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor); |
713 | 758 | ||
714 | if (!ir->attached) | 759 | if (!ir->attached) |