1/* 2 * LIRC base driver 3 * 4 * by Artur Lipowski <alipowski@interia.pl> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22#include <linux/module.h> 23#include <linux/kernel.h> 24#include <linux/sched.h> 25#include <linux/errno.h> 26#include <linux/ioctl.h> 27#include <linux/fs.h> 28#include <linux/poll.h> 29#include <linux/completion.h> 30#include <linux/errno.h> 31#include <linux/mutex.h> 32#include <linux/wait.h> 33#include <linux/unistd.h> 34#include <linux/kthread.h> 35#include <linux/bitops.h> 36#include <linux/device.h> 37#include <linux/cdev.h> 38 39#include <media/lirc.h> 40#include <media/lirc_dev.h> 41 42static int debug; 43 44#define IRCTL_DEV_NAME "BaseRemoteCtl" 45#define NOPLUG -1 46#define LOGHEAD "lirc_dev (%s[%d]): " 47 48static dev_t lirc_base_dev; 49 50struct irctl { 51 struct lirc_driver d; 52 int attached; 53 int open; 54 55 struct mutex irctl_lock; 56 struct lirc_buffer *buf; 57 unsigned int chunk_size; 58 59 struct task_struct *task; 60 long jiffies_to_wait; 61 62 struct cdev cdev; 63}; 64 65static DEFINE_MUTEX(lirc_dev_lock); 66 67static struct irctl *irctls[MAX_IRCTL_DEVICES]; 68 69/* Only used for sysfs but defined to void otherwise */ 70static struct class *lirc_class; 71 72/* helper function 73 * initializes the irctl structure 74 */ 75static void init_irctl(struct irctl *ir) 76{ 77 dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n", 78 ir->d.name, ir->d.minor); 79 mutex_init(&ir->irctl_lock); 80 ir->d.minor = NOPLUG; 81} 82 83static void cleanup(struct irctl *ir) 84{ 85 dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor); 86 87 device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor)); 88 89 if (ir->buf != ir->d.rbuf) { 90 lirc_buffer_free(ir->buf); 91 kfree(ir->buf); 92 } 93 ir->buf = NULL; 94} 95 96/* helper function 97 * reads key codes from driver and puts them into buffer 98 * returns 0 on success 99 */ 100static int add_to_buf(struct irctl *ir) 101{ 102 if (ir->d.add_to_buf) { 103 int res = -ENODATA; 104 int got_data = 0; 105 106 /* 107 * service the device as long as it is returning 108 * data and we have space 109 */ 110get_data: 111 res = ir->d.add_to_buf(ir->d.data, ir->buf); 112 if (res == 0) { 113 got_data++; 114 goto get_data; 115 } 116 117 if (res == -ENODEV) 118 kthread_stop(ir->task); 119 120 return got_data ? 0 : res; 121 } 122 123 return 0; 124} 125 126/* main function of the polling thread 127 */ 128static int lirc_thread(void *irctl) 129{ 130 struct irctl *ir = irctl; 131 132 dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n", 133 ir->d.name, ir->d.minor); 134 135 do { 136 if (ir->open) { 137 if (ir->jiffies_to_wait) { 138 set_current_state(TASK_INTERRUPTIBLE); 139 schedule_timeout(ir->jiffies_to_wait); 140 } 141 if (kthread_should_stop()) 142 break; 143 if (!add_to_buf(ir)) 144 wake_up_interruptible(&ir->buf->wait_poll); 145 } else { 146 set_current_state(TASK_INTERRUPTIBLE); 147 schedule(); 148 } 149 } while (!kthread_should_stop()); 150 151 dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n", 152 ir->d.name, ir->d.minor); 153 154 return 0; 155} 156 157 158static struct file_operations fops = { 159 .owner = THIS_MODULE, 160 .read = lirc_dev_fop_read, 161 .write = lirc_dev_fop_write, 162 .poll = lirc_dev_fop_poll, 163 .unlocked_ioctl = lirc_dev_fop_ioctl, 164 .open = lirc_dev_fop_open, 165 .release = lirc_dev_fop_close, 166}; 167 168static int lirc_cdev_add(struct irctl *ir) 169{ 170 int retval; 171 struct lirc_driver *d = &ir->d; 172 173 if (d->fops) { 174 cdev_init(&ir->cdev, d->fops); 175 ir->cdev.owner = d->owner; 176 } else { 177 cdev_init(&ir->cdev, &fops); 178 ir->cdev.owner = THIS_MODULE; 179 } 180 kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor); 181 182 retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); 183 if (retval) 184 kobject_put(&ir->cdev.kobj); 185 186 return retval; 187} 188 189int lirc_register_driver(struct lirc_driver *d) 190{ 191 struct irctl *ir; 192 int minor; 193 int bytes_in_key; 194 unsigned int chunk_size; 195 unsigned int buffer_size; 196 int err; 197 198 if (!d) { 199 printk(KERN_ERR "lirc_dev: lirc_register_driver: " 200 "driver pointer must be not NULL!\n"); 201 err = -EBADRQC; 202 goto out; 203 } 204 205 if (MAX_IRCTL_DEVICES <= d->minor) { 206 dev_err(d->dev, "lirc_dev: lirc_register_driver: " 207 "\"minor\" must be between 0 and %d (%d)!\n", 208 MAX_IRCTL_DEVICES-1, d->minor); 209 err = -EBADRQC; 210 goto out; 211 } 212 213 if (1 > d->code_length || (BUFLEN * 8) < d->code_length) { 214 dev_err(d->dev, "lirc_dev: lirc_register_driver: " 215 "code length in bits for minor (%d) " 216 "must be less than %d!\n", 217 d->minor, BUFLEN * 8); 218 err = -EBADRQC; 219 goto out; 220 } 221 222 dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n", 223 d->sample_rate); 224 if (d->sample_rate) { 225 if (2 > d->sample_rate || HZ < d->sample_rate) { 226 dev_err(d->dev, "lirc_dev: lirc_register_driver: " 227 "sample_rate must be between 2 and %d!\n", HZ); 228 err = -EBADRQC; 229 goto out; 230 } 231 if (!d->add_to_buf) { 232 dev_err(d->dev, "lirc_dev: lirc_register_driver: " 233 "add_to_buf cannot be NULL when " 234 "sample_rate is set\n"); 235 err = -EBADRQC; 236 goto out; 237 } 238 } else if (!(d->fops && d->fops->read) && !d->rbuf) { 239 dev_err(d->dev, "lirc_dev: lirc_register_driver: " 240 "fops->read and rbuf cannot all be NULL!\n"); 241 err = -EBADRQC; 242 goto out; 243 } else if (!d->rbuf) { 244 if (!(d->fops && d->fops->read && d->fops->poll && 245 d->fops->unlocked_ioctl)) { 246 dev_err(d->dev, "lirc_dev: lirc_register_driver: " 247 "neither read, poll nor unlocked_ioctl can be NULL!\n"); 248 err = -EBADRQC; 249 goto out; 250 } 251 } 252 253 mutex_lock(&lirc_dev_lock); 254 255 minor = d->minor; 256 257 if (minor < 0) { 258 /* find first free slot for driver */ 259 for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++) 260 if (!irctls[minor]) 261 break; 262 if (MAX_IRCTL_DEVICES == minor) { 263 dev_err(d->dev, "lirc_dev: lirc_register_driver: " 264 "no free slots for drivers!\n"); 265 err = -ENOMEM; 266 goto out_lock; 267 } 268 } else if (irctls[minor]) { 269 dev_err(d->dev, "lirc_dev: lirc_register_driver: " 270 "minor (%d) just registered!\n", minor); 271 err = -EBUSY; 272 goto out_lock; 273 } 274 275 ir = kzalloc(sizeof(struct irctl), GFP_KERNEL); 276 if (!ir) { 277 err = -ENOMEM; 278 goto out_lock; 279 } 280 init_irctl(ir); 281 irctls[minor] = ir; 282 d->minor = minor; 283 284 if (d->sample_rate) { 285 ir->jiffies_to_wait = HZ / d->sample_rate; 286 } else { 287 /* it means - wait for external event in task queue */ 288 ir->jiffies_to_wait = 0; 289 } 290 291 /* some safety check 8-) */ 292 d->name[sizeof(d->name)-1] = '\0'; 293 294 bytes_in_key = BITS_TO_LONGS(d->code_length) + 295 (d->code_length % 8 ? 1 : 0); 296 buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key; 297 chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key; 298 299 if (d->rbuf) { 300 ir->buf = d->rbuf; 301 } else { 302 ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); 303 if (!ir->buf) { 304 err = -ENOMEM; 305 goto out_lock; 306 } 307 err = lirc_buffer_init(ir->buf, chunk_size, buffer_size); 308 if (err) { 309 kfree(ir->buf); 310 goto out_lock; 311 } 312 } 313 ir->chunk_size = ir->buf->chunk_size; 314 315 if (d->features == 0) 316 d->features = LIRC_CAN_REC_LIRCCODE; 317 318 ir->d = *d; 319 ir->d.minor = minor; 320 321 device_create(lirc_class, ir->d.dev, 322 MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL, 323 "lirc%u", ir->d.minor); 324 325 if (d->sample_rate) { 326 /* try to fire up polling thread */ 327 ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev"); 328 if (IS_ERR(ir->task)) { 329 dev_err(d->dev, "lirc_dev: lirc_register_driver: " 330 "cannot run poll thread for minor = %d\n", 331 d->minor); 332 err = -ECHILD; 333 goto out_sysfs; 334 } 335 } 336 337 err = lirc_cdev_add(ir); 338 if (err) 339 goto out_sysfs; 340 341 ir->attached = 1; 342 mutex_unlock(&lirc_dev_lock); 343 344 dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n", 345 ir->d.name, ir->d.minor); 346 return minor; 347 348out_sysfs: 349 device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor)); 350out_lock: 351 mutex_unlock(&lirc_dev_lock); 352out: 353 return err; 354} 355EXPORT_SYMBOL(lirc_register_driver); 356 357int lirc_unregister_driver(int minor) 358{ 359 struct irctl *ir; 360 361 if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { 362 printk(KERN_ERR "lirc_dev: lirc_unregister_driver: " 363 "\"minor (%d)\" must be between 0 and %d!\n", 364 minor, MAX_IRCTL_DEVICES-1); 365 return -EBADRQC; 366 } 367 368 ir = irctls[minor]; 369 370 mutex_lock(&lirc_dev_lock); 371 372 if (ir->d.minor != minor) { 373 printk(KERN_ERR "lirc_dev: lirc_unregister_driver: " 374 "minor (%d) device not registered!", minor); 375 mutex_unlock(&lirc_dev_lock); 376 return -ENOENT; 377 } 378 379 /* end up polling thread */ 380 if (ir->task) 381 kthread_stop(ir->task); 382 383 dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n", 384 ir->d.name, ir->d.minor); 385 386 ir->attached = 0; 387 if (ir->open) { 388 dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n", 389 ir->d.name, ir->d.minor); 390 wake_up_interruptible(&ir->buf->wait_poll); 391 mutex_lock(&ir->irctl_lock); 392 ir->d.set_use_dec(ir->d.data); 393 module_put(ir->d.owner); 394 mutex_unlock(&ir->irctl_lock); 395 cdev_del(&ir->cdev); 396 } else { 397 cleanup(ir); 398 cdev_del(&ir->cdev); 399 kfree(ir); 400 irctls[minor] = NULL; 401 } 402 403 mutex_unlock(&lirc_dev_lock); 404 405 return 0; 406} 407EXPORT_SYMBOL(lirc_unregister_driver); 408 409int lirc_dev_fop_open(struct inode *inode, struct file *file) 410{ 411 struct irctl *ir; 412 int retval = 0; 413 414 if (iminor(inode) >= MAX_IRCTL_DEVICES) { 415 printk(KERN_WARNING "lirc_dev [%d]: open result = -ENODEV\n", 416 iminor(inode)); 417 return -ENODEV; 418 } 419 420 if (mutex_lock_interruptible(&lirc_dev_lock)) 421 return -ERESTARTSYS; 422 423 ir = irctls[iminor(inode)]; 424 if (!ir) { 425 retval = -ENODEV; 426 goto error; 427 } 428 file->private_data = ir; 429 430 dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor); 431 432 if (ir->d.minor == NOPLUG) { 433 retval = -ENODEV; 434 goto error; 435 } 436 437 if (ir->open) { 438 retval = -EBUSY; 439 goto error; 440 } 441 442 if (try_module_get(ir->d.owner)) { 443 ++ir->open; 444 retval = ir->d.set_use_inc(ir->d.data); 445 446 if (retval) { 447 module_put(ir->d.owner); 448 --ir->open; 449 } else { 450 lirc_buffer_clear(ir->buf); 451 } 452 if (ir->task) 453 wake_up_process(ir->task); 454 } 455 456error: 457 if (ir) 458 dev_dbg(ir->d.dev, LOGHEAD "open result = %d\n", 459 ir->d.name, ir->d.minor, retval); 460 461 mutex_unlock(&lirc_dev_lock); 462 463 return retval; 464} 465EXPORT_SYMBOL(lirc_dev_fop_open); 466 467int lirc_dev_fop_close(struct inode *inode, struct file *file) 468{ 469 struct irctl *ir = irctls[iminor(inode)]; 470 471 dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor); 472 473 WARN_ON(mutex_lock_killable(&lirc_dev_lock)); 474 475 --ir->open; 476 if (ir->attached) { 477 ir->d.set_use_dec(ir->d.data); 478 module_put(ir->d.owner); 479 } else { 480 cleanup(ir); 481 irctls[ir->d.minor] = NULL; 482 kfree(ir); 483 } 484 485 mutex_unlock(&lirc_dev_lock); 486 487 return 0; 488} 489EXPORT_SYMBOL(lirc_dev_fop_close); 490 491unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait) 492{ 493 struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; 494 unsigned int ret; 495 496 dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor); 497 498 if (!ir->attached) { 499 mutex_unlock(&ir->irctl_lock); 500 return POLLERR; 501 } 502 503 poll_wait(file, &ir->buf->wait_poll, wait); 504 505 if (ir->buf) 506 if (lirc_buffer_empty(ir->buf)) 507 ret = 0; 508 else 509 ret = POLLIN | POLLRDNORM; 510 else 511 ret = POLLERR; 512 513 dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n", 514 ir->d.name, ir->d.minor, ret); 515 516 return ret; 517} 518EXPORT_SYMBOL(lirc_dev_fop_poll); 519 520long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 521{ 522 unsigned long mode; 523 int result = 0; 524 struct irctl *ir = file->private_data; 525 526 dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n", 527 ir->d.name, ir->d.minor, cmd); 528 529 if (ir->d.minor == NOPLUG || !ir->attached) { 530 dev_dbg(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n", 531 ir->d.name, ir->d.minor); 532 return -ENODEV; 533 } 534 535 mutex_lock(&ir->irctl_lock); 536 537 switch (cmd) { 538 case LIRC_GET_FEATURES: 539 result = put_user(ir->d.features, (unsigned long *)arg); 540 break; 541 case LIRC_GET_REC_MODE: 542 if (!(ir->d.features & LIRC_CAN_REC_MASK)) { 543 result = -ENOSYS; 544 break; 545 } 546 547 result = put_user(LIRC_REC2MODE 548 (ir->d.features & LIRC_CAN_REC_MASK), 549 (unsigned long *)arg); 550 break; 551 case LIRC_SET_REC_MODE: 552 if (!(ir->d.features & LIRC_CAN_REC_MASK)) { 553 result = -ENOSYS; 554 break; 555 } 556 557 result = get_user(mode, (unsigned long *)arg); 558 if (!result && !(LIRC_MODE2REC(mode) & ir->d.features)) 559 result = -EINVAL; 560 break; 561 case LIRC_GET_LENGTH: 562 result = put_user(ir->d.code_length, (unsigned long *)arg); 563 break; 564 case LIRC_GET_MIN_TIMEOUT: 565 if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || 566 ir->d.min_timeout == 0) { 567 result = -ENOSYS; 568 break; 569 } 570 571 result = put_user(ir->d.min_timeout, (unsigned long *)arg); 572 break; 573 case LIRC_GET_MAX_TIMEOUT: 574 if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || 575 ir->d.max_timeout == 0) { 576 result = -ENOSYS; 577 break; 578 } 579 580 result = put_user(ir->d.max_timeout, (unsigned long *)arg); 581 break; 582 default: 583 result = -EINVAL; 584 } 585 586 dev_dbg(ir->d.dev, LOGHEAD "ioctl result = %d\n", 587 ir->d.name, ir->d.minor, result); 588 589 mutex_unlock(&ir->irctl_lock); 590 591 return result; 592} 593EXPORT_SYMBOL(lirc_dev_fop_ioctl); 594 595ssize_t lirc_dev_fop_read(struct file *file, 596 char *buffer, 597 size_t length, 598 loff_t *ppos) 599{ 600 struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; 601 unsigned char buf[ir->chunk_size]; 602 int ret = 0, written = 0; 603 DECLARE_WAITQUEUE(wait, current); 604 605 dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor); 606 607 if (mutex_lock_interruptible(&ir->irctl_lock)) 608 return -ERESTARTSYS; 609 if (!ir->attached) { 610 mutex_unlock(&ir->irctl_lock); 611 return -ENODEV; 612 } 613 614 if (length % ir->chunk_size) { 615 dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n", 616 ir->d.name, ir->d.minor); 617 mutex_unlock(&ir->irctl_lock); 618 return -EINVAL; 619 } 620 621 /* 622 * we add ourselves to the task queue before buffer check 623 * to avoid losing scan code (in case when queue is awaken somewhere 624 * between while condition checking and scheduling) 625 */ 626 add_wait_queue(&ir->buf->wait_poll, &wait); 627 set_current_state(TASK_INTERRUPTIBLE); 628 629 /* 630 * while we didn't provide 'length' bytes, device is opened in blocking 631 * mode and 'copy_to_user' is happy, wait for data. 632 */ 633 while (written < length && ret == 0) { 634 if (lirc_buffer_empty(ir->buf)) { 635 /* According to the read(2) man page, 'written' can be 636 * returned as less than 'length', instead of blocking 637 * again, returning -EWOULDBLOCK, or returning 638 * -ERESTARTSYS */ 639 if (written) 640 break; 641 if (file->f_flags & O_NONBLOCK) { 642 ret = -EWOULDBLOCK; 643 break; 644 } 645 if (signal_pending(current)) { 646 ret = -ERESTARTSYS; 647 break; 648 } 649 650 mutex_unlock(&ir->irctl_lock); 651 schedule(); 652 set_current_state(TASK_INTERRUPTIBLE); 653 654 if (mutex_lock_interruptible(&ir->irctl_lock)) { 655 ret = -ERESTARTSYS; 656 remove_wait_queue(&ir->buf->wait_poll, &wait); 657 set_current_state(TASK_RUNNING); 658 goto out_unlocked; 659 } 660 661 if (!ir->attached) { 662 ret = -ENODEV; 663 break; 664 } 665 } else { 666 lirc_buffer_read(ir->buf, buf); 667 ret = copy_to_user((void *)buffer+written, buf, 668 ir->buf->chunk_size); 669 written += ir->buf->chunk_size; 670 } 671 } 672 673 remove_wait_queue(&ir->buf->wait_poll, &wait); 674 set_current_state(TASK_RUNNING); 675 mutex_unlock(&ir->irctl_lock); 676 677out_unlocked: 678 dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n", 679 ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret); 680 681 return ret ? ret : written; 682} 683EXPORT_SYMBOL(lirc_dev_fop_read); 684 685void *lirc_get_pdata(struct file *file) 686{ 687 void *data = NULL; 688 689 if (file && file->f_dentry && file->f_dentry->d_inode && 690 file->f_dentry->d_inode->i_rdev) { 691 struct irctl *ir; 692 ir = irctls[iminor(file->f_dentry->d_inode)]; 693 data = ir->d.data; 694 } 695 696 return data; 697} 698EXPORT_SYMBOL(lirc_get_pdata); 699 700 701ssize_t lirc_dev_fop_write(struct file *file, const char *buffer, 702 size_t length, loff_t *ppos) 703{ 704 struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; 705 706 dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor); 707 708 if (!ir->attached) 709 return -ENODEV; 710 711 return -EINVAL; 712} 713EXPORT_SYMBOL(lirc_dev_fop_write); 714 715 716static int __init lirc_dev_init(void) 717{ 718 int retval; 719 720 lirc_class = class_create(THIS_MODULE, "lirc"); 721 if (IS_ERR(lirc_class)) { 722 retval = PTR_ERR(lirc_class); 723 printk(KERN_ERR "lirc_dev: class_create failed\n"); 724 goto error; 725 } 726 727 retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES, 728 IRCTL_DEV_NAME); 729 if (retval) { 730 class_destroy(lirc_class); 731 printk(KERN_ERR "lirc_dev: alloc_chrdev_region failed\n"); 732 goto error; 733 } 734 735 736 printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, " 737 "major %d \n", MAJOR(lirc_base_dev)); 738 739error: 740 return retval; 741} 742 743 744 745static void __exit lirc_dev_exit(void) 746{ 747 class_destroy(lirc_class); 748 unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES); 749 printk(KERN_INFO "lirc_dev: module unloaded\n"); 750} 751 752module_init(lirc_dev_init); 753module_exit(lirc_dev_exit); 754 755MODULE_DESCRIPTION("LIRC base driver module"); 756MODULE_AUTHOR("Artur Lipowski"); 757MODULE_LICENSE("GPL"); 758 759module_param(debug, bool, S_IRUGO | S_IWUSR); 760MODULE_PARM_DESC(debug, "Enable debugging messages"); 761