1/* 2 * lirc_imon.c: LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD 3 * including the iMON PAD model 4 * 5 * Copyright(C) 2004 Venky Raju(dev@venky.ws) 6 * Copyright(C) 2009 Jarod Wilson <jarod@wilsonet.com> 7 * 8 * lirc_imon is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 23#include <linux/errno.h> 24#include <linux/init.h> 25#include <linux/kernel.h> 26#include <linux/module.h> 27#include <linux/slab.h> 28#include <linux/uaccess.h> 29#include <linux/usb.h> 30 31#include <media/lirc.h> 32#include <media/lirc_dev.h> 33 34 35#define MOD_AUTHOR "Venky Raju <dev@venky.ws>" 36#define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" 37#define MOD_NAME "lirc_imon" 38#define MOD_VERSION "0.8" 39 40#define DISPLAY_MINOR_BASE 144 41#define DEVICE_NAME "lcd%d" 42 43#define BUF_CHUNK_SIZE 4 44#define BUF_SIZE 128 45 46#define BIT_DURATION 250 /* each bit received is 250us */ 47 48/*** P R O T O T Y P E S ***/ 49 50/* USB Callback prototypes */ 51static int imon_probe(struct usb_interface *interface, 52 const struct usb_device_id *id); 53static void imon_disconnect(struct usb_interface *interface); 54static void usb_rx_callback(struct urb *urb); 55static void usb_tx_callback(struct urb *urb); 56 57/* suspend/resume support */ 58static int imon_resume(struct usb_interface *intf); 59static int imon_suspend(struct usb_interface *intf, pm_message_t message); 60 61/* Display file_operations function prototypes */ 62static int display_open(struct inode *inode, struct file *file); 63static int display_close(struct inode *inode, struct file *file); 64 65/* VFD write operation */ 66static ssize_t vfd_write(struct file *file, const char __user *buf, 67 size_t n_bytes, loff_t *pos); 68 69/* LIRC driver function prototypes */ 70static int ir_open(void *data); 71static void ir_close(void *data); 72 73/* Driver init/exit prototypes */ 74static int __init imon_init(void); 75static void __exit imon_exit(void); 76 77/*** G L O B A L S ***/ 78#define IMON_DATA_BUF_SZ 35 79 80struct imon_context { 81 struct usb_device *usbdev; 82 /* Newer devices have two interfaces */ 83 int display; /* not all controllers do */ 84 int display_isopen; /* display port has been opened */ 85 int ir_isopen; /* IR port open */ 86 int dev_present; /* USB device presence */ 87 struct mutex ctx_lock; /* to lock this object */ 88 wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ 89 90 int vfd_proto_6p; /* some VFD require a 6th packet */ 91 92 struct lirc_driver *driver; 93 struct usb_endpoint_descriptor *rx_endpoint; 94 struct usb_endpoint_descriptor *tx_endpoint; 95 struct urb *rx_urb; 96 struct urb *tx_urb; 97 unsigned char usb_rx_buf[8]; 98 unsigned char usb_tx_buf[8]; 99 100 struct rx_data { 101 int count; /* length of 0 or 1 sequence */ 102 int prev_bit; /* logic level of sequence */ 103 int initial_space; /* initial space flag */ 104 } rx; 105 106 struct tx_t { 107 unsigned char data_buf[IMON_DATA_BUF_SZ]; /* user data buffer */ 108 struct completion finished; /* wait for write to finish */ 109 atomic_t busy; /* write in progress */ 110 int status; /* status of tx completion */ 111 } tx; 112}; 113 114static const struct file_operations display_fops = { 115 .owner = THIS_MODULE, 116 .open = &display_open, 117 .write = &vfd_write, 118 .release = &display_close, 119 .llseek = noop_llseek, 120}; 121 122/* 123 * USB Device ID for iMON USB Control Boards 124 * 125 * The Windows drivers contain 6 different inf files, more or less one for 126 * each new device until the 0x0034-0x0046 devices, which all use the same 127 * driver. Some of the devices in the 34-46 range haven't been definitively 128 * identified yet. Early devices have either a TriGem Computer, Inc. or a 129 * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later 130 * devices use the SoundGraph vendor ID (0x15c2). 131 */ 132static struct usb_device_id imon_usb_id_table[] = { 133 /* TriGem iMON (IR only) -- TG_iMON.inf */ 134 { USB_DEVICE(0x0aa8, 0x8001) }, 135 136 /* SoundGraph iMON (IR only) -- sg_imon.inf */ 137 { USB_DEVICE(0x04e8, 0xff30) }, 138 139 /* SoundGraph iMON VFD (IR & VFD) -- iMON_VFD.inf */ 140 { USB_DEVICE(0x0aa8, 0xffda) }, 141 142 /* SoundGraph iMON SS (IR & VFD) -- iMON_SS.inf */ 143 { USB_DEVICE(0x15c2, 0xffda) }, 144 145 {} 146}; 147 148/* Some iMON VFD models requires a 6th packet for VFD writes */ 149static struct usb_device_id vfd_proto_6p_list[] = { 150 { USB_DEVICE(0x15c2, 0xffda) }, 151 {} 152}; 153 154/* Some iMON devices have no lcd/vfd, don't set one up */ 155static struct usb_device_id ir_only_list[] = { 156 { USB_DEVICE(0x0aa8, 0x8001) }, 157 { USB_DEVICE(0x04e8, 0xff30) }, 158 {} 159}; 160 161/* USB Device data */ 162static struct usb_driver imon_driver = { 163 .name = MOD_NAME, 164 .probe = imon_probe, 165 .disconnect = imon_disconnect, 166 .suspend = imon_suspend, 167 .resume = imon_resume, 168 .id_table = imon_usb_id_table, 169}; 170 171static struct usb_class_driver imon_class = { 172 .name = DEVICE_NAME, 173 .fops = &display_fops, 174 .minor_base = DISPLAY_MINOR_BASE, 175}; 176 177/* to prevent races between open() and disconnect(), probing, etc */ 178static DEFINE_MUTEX(driver_lock); 179 180static int debug; 181 182/*** M O D U L E C O D E ***/ 183 184MODULE_AUTHOR(MOD_AUTHOR); 185MODULE_DESCRIPTION(MOD_DESC); 186MODULE_VERSION(MOD_VERSION); 187MODULE_LICENSE("GPL"); 188MODULE_DEVICE_TABLE(usb, imon_usb_id_table); 189module_param(debug, int, S_IRUGO | S_IWUSR); 190MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)"); 191 192static void free_imon_context(struct imon_context *context) 193{ 194 struct device *dev = context->driver->dev; 195 usb_free_urb(context->tx_urb); 196 usb_free_urb(context->rx_urb); 197 lirc_buffer_free(context->driver->rbuf); 198 kfree(context->driver->rbuf); 199 kfree(context->driver); 200 kfree(context); 201 202 dev_dbg(dev, "%s: iMON context freed\n", __func__); 203} 204 205static void deregister_from_lirc(struct imon_context *context) 206{ 207 int retval; 208 int minor = context->driver->minor; 209 210 retval = lirc_unregister_driver(minor); 211 if (retval) 212 err("%s: unable to deregister from lirc(%d)", 213 __func__, retval); 214 else 215 printk(KERN_INFO MOD_NAME ": Deregistered iMON driver " 216 "(minor:%d)\n", minor); 217 218} 219 220/** 221 * Called when the Display device (e.g. /dev/lcd0) 222 * is opened by the application. 223 */ 224static int display_open(struct inode *inode, struct file *file) 225{ 226 struct usb_interface *interface; 227 struct imon_context *context = NULL; 228 int subminor; 229 int retval = 0; 230 231 /* prevent races with disconnect */ 232 mutex_lock(&driver_lock); 233 234 subminor = iminor(inode); 235 interface = usb_find_interface(&imon_driver, subminor); 236 if (!interface) { 237 err("%s: could not find interface for minor %d", 238 __func__, subminor); 239 retval = -ENODEV; 240 goto exit; 241 } 242 context = usb_get_intfdata(interface); 243 244 if (!context) { 245 err("%s: no context found for minor %d", 246 __func__, subminor); 247 retval = -ENODEV; 248 goto exit; 249 } 250 251 mutex_lock(&context->ctx_lock); 252 253 if (!context->display) { 254 err("%s: display not supported by device", __func__); 255 retval = -ENODEV; 256 } else if (context->display_isopen) { 257 err("%s: display port is already open", __func__); 258 retval = -EBUSY; 259 } else { 260 context->display_isopen = 1; 261 file->private_data = context; 262 dev_info(context->driver->dev, "display port opened\n"); 263 } 264 265 mutex_unlock(&context->ctx_lock); 266 267exit: 268 mutex_unlock(&driver_lock); 269 return retval; 270} 271 272/** 273 * Called when the display device (e.g. /dev/lcd0) 274 * is closed by the application. 275 */ 276static int display_close(struct inode *inode, struct file *file) 277{ 278 struct imon_context *context = NULL; 279 int retval = 0; 280 281 context = file->private_data; 282 283 if (!context) { 284 err("%s: no context for device", __func__); 285 return -ENODEV; 286 } 287 288 mutex_lock(&context->ctx_lock); 289 290 if (!context->display) { 291 err("%s: display not supported by device", __func__); 292 retval = -ENODEV; 293 } else if (!context->display_isopen) { 294 err("%s: display is not open", __func__); 295 retval = -EIO; 296 } else { 297 context->display_isopen = 0; 298 dev_info(context->driver->dev, "display port closed\n"); 299 if (!context->dev_present && !context->ir_isopen) { 300 /* 301 * Device disconnected before close and IR port is not 302 * open. If IR port is open, context will be deleted by 303 * ir_close. 304 */ 305 mutex_unlock(&context->ctx_lock); 306 free_imon_context(context); 307 return retval; 308 } 309 } 310 311 mutex_unlock(&context->ctx_lock); 312 return retval; 313} 314 315/** 316 * Sends a packet to the device -- this function must be called 317 * with context->ctx_lock held. 318 */ 319static int send_packet(struct imon_context *context) 320{ 321 unsigned int pipe; 322 int interval = 0; 323 int retval = 0; 324 325 /* Check if we need to use control or interrupt urb */ 326 pipe = usb_sndintpipe(context->usbdev, 327 context->tx_endpoint->bEndpointAddress); 328 interval = context->tx_endpoint->bInterval; 329 330 usb_fill_int_urb(context->tx_urb, context->usbdev, pipe, 331 context->usb_tx_buf, 332 sizeof(context->usb_tx_buf), 333 usb_tx_callback, context, interval); 334 335 context->tx_urb->actual_length = 0; 336 337 init_completion(&context->tx.finished); 338 atomic_set(&(context->tx.busy), 1); 339 340 retval = usb_submit_urb(context->tx_urb, GFP_KERNEL); 341 if (retval) { 342 atomic_set(&(context->tx.busy), 0); 343 err("%s: error submitting urb(%d)", __func__, retval); 344 } else { 345 /* Wait for transmission to complete (or abort) */ 346 mutex_unlock(&context->ctx_lock); 347 retval = wait_for_completion_interruptible( 348 &context->tx.finished); 349 if (retval) 350 err("%s: task interrupted", __func__); 351 mutex_lock(&context->ctx_lock); 352 353 retval = context->tx.status; 354 if (retval) 355 err("%s: packet tx failed (%d)", __func__, retval); 356 } 357 358 return retval; 359} 360 361/** 362 * Writes data to the VFD. The iMON VFD is 2x16 characters 363 * and requires data in 5 consecutive USB interrupt packets, 364 * each packet but the last carrying 7 bytes. 365 * 366 * I don't know if the VFD board supports features such as 367 * scrolling, clearing rows, blanking, etc. so at 368 * the caller must provide a full screen of data. If fewer 369 * than 32 bytes are provided spaces will be appended to 370 * generate a full screen. 371 */ 372static ssize_t vfd_write(struct file *file, const char __user *buf, 373 size_t n_bytes, loff_t *pos) 374{ 375 int i; 376 int offset; 377 int seq; 378 int retval = 0; 379 struct imon_context *context; 380 const unsigned char vfd_packet6[] = { 381 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; 382 int *data_buf = NULL; 383 384 context = file->private_data; 385 if (!context) { 386 err("%s: no context for device", __func__); 387 return -ENODEV; 388 } 389 390 mutex_lock(&context->ctx_lock); 391 392 if (!context->dev_present) { 393 err("%s: no iMON device present", __func__); 394 retval = -ENODEV; 395 goto exit; 396 } 397 398 if (n_bytes <= 0 || n_bytes > IMON_DATA_BUF_SZ - 3) { 399 err("%s: invalid payload size", __func__); 400 retval = -EINVAL; 401 goto exit; 402 } 403 404 data_buf = memdup_user(buf, n_bytes); 405 if (IS_ERR(data_buf)) { 406 retval = PTR_ERR(data_buf); 407 goto exit; 408 } 409 410 memcpy(context->tx.data_buf, data_buf, n_bytes); 411 412 /* Pad with spaces */ 413 for (i = n_bytes; i < IMON_DATA_BUF_SZ - 3; ++i) 414 context->tx.data_buf[i] = ' '; 415 416 for (i = IMON_DATA_BUF_SZ - 3; i < IMON_DATA_BUF_SZ; ++i) 417 context->tx.data_buf[i] = 0xFF; 418 419 offset = 0; 420 seq = 0; 421 422 do { 423 memcpy(context->usb_tx_buf, context->tx.data_buf + offset, 7); 424 context->usb_tx_buf[7] = (unsigned char) seq; 425 426 retval = send_packet(context); 427 if (retval) { 428 err("%s: send packet failed for packet #%d", 429 __func__, seq/2); 430 goto exit; 431 } else { 432 seq += 2; 433 offset += 7; 434 } 435 436 } while (offset < IMON_DATA_BUF_SZ); 437 438 if (context->vfd_proto_6p) { 439 /* Send packet #6 */ 440 memcpy(context->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6)); 441 context->usb_tx_buf[7] = (unsigned char) seq; 442 retval = send_packet(context); 443 if (retval) 444 err("%s: send packet failed for packet #%d", 445 __func__, seq/2); 446 } 447 448exit: 449 mutex_unlock(&context->ctx_lock); 450 kfree(data_buf); 451 452 return (!retval) ? n_bytes : retval; 453} 454 455/** 456 * Callback function for USB core API: transmit data 457 */ 458static void usb_tx_callback(struct urb *urb) 459{ 460 struct imon_context *context; 461 462 if (!urb) 463 return; 464 context = (struct imon_context *)urb->context; 465 if (!context) 466 return; 467 468 context->tx.status = urb->status; 469 470 /* notify waiters that write has finished */ 471 atomic_set(&context->tx.busy, 0); 472 complete(&context->tx.finished); 473 474 return; 475} 476 477/** 478 * Called by lirc_dev when the application opens /dev/lirc 479 */ 480static int ir_open(void *data) 481{ 482 int retval = 0; 483 struct imon_context *context; 484 485 /* prevent races with disconnect */ 486 mutex_lock(&driver_lock); 487 488 context = (struct imon_context *)data; 489 490 /* initial IR protocol decode variables */ 491 context->rx.count = 0; 492 context->rx.initial_space = 1; 493 context->rx.prev_bit = 0; 494 495 context->ir_isopen = 1; 496 dev_info(context->driver->dev, "IR port opened\n"); 497 498 mutex_unlock(&driver_lock); 499 return retval; 500} 501 502/** 503 * Called by lirc_dev when the application closes /dev/lirc 504 */ 505static void ir_close(void *data) 506{ 507 struct imon_context *context; 508 509 context = (struct imon_context *)data; 510 if (!context) { 511 err("%s: no context for device", __func__); 512 return; 513 } 514 515 mutex_lock(&context->ctx_lock); 516 517 context->ir_isopen = 0; 518 dev_info(context->driver->dev, "IR port closed\n"); 519 520 if (!context->dev_present) { 521 /* 522 * Device disconnected while IR port was still open. Driver 523 * was not deregistered at disconnect time, so do it now. 524 */ 525 deregister_from_lirc(context); 526 527 if (!context->display_isopen) { 528 mutex_unlock(&context->ctx_lock); 529 free_imon_context(context); 530 return; 531 } 532 /* 533 * If display port is open, context will be deleted by 534 * display_close 535 */ 536 } 537 538 mutex_unlock(&context->ctx_lock); 539 return; 540} 541 542/** 543 * Convert bit count to time duration (in us) and submit 544 * the value to lirc_dev. 545 */ 546static void submit_data(struct imon_context *context) 547{ 548 unsigned char buf[4]; 549 int value = context->rx.count; 550 int i; 551 552 dev_dbg(context->driver->dev, "submitting data to LIRC\n"); 553 554 value *= BIT_DURATION; 555 value &= PULSE_MASK; 556 if (context->rx.prev_bit) 557 value |= PULSE_BIT; 558 559 for (i = 0; i < 4; ++i) 560 buf[i] = value>>(i*8); 561 562 lirc_buffer_write(context->driver->rbuf, buf); 563 wake_up(&context->driver->rbuf->wait_poll); 564 return; 565} 566 567static inline int tv2int(const struct timeval *a, const struct timeval *b) 568{ 569 int usecs = 0; 570 int sec = 0; 571 572 if (b->tv_usec > a->tv_usec) { 573 usecs = 1000000; 574 sec--; 575 } 576 577 usecs += a->tv_usec - b->tv_usec; 578 579 sec += a->tv_sec - b->tv_sec; 580 sec *= 1000; 581 usecs /= 1000; 582 sec += usecs; 583 584 if (sec < 0) 585 sec = 1000; 586 587 return sec; 588} 589 590/** 591 * Process the incoming packet 592 */ 593static void imon_incoming_packet(struct imon_context *context, 594 struct urb *urb, int intf) 595{ 596 int len = urb->actual_length; 597 unsigned char *buf = urb->transfer_buffer; 598 struct device *dev = context->driver->dev; 599 int octet, bit; 600 unsigned char mask; 601 int i; 602 603 /* 604 * just bail out if no listening IR client 605 */ 606 if (!context->ir_isopen) 607 return; 608 609 if (len != 8) { 610 dev_warn(dev, "imon %s: invalid incoming packet " 611 "size (len = %d, intf%d)\n", __func__, len, intf); 612 return; 613 } 614 615 if (debug) { 616 printk(KERN_INFO "raw packet: "); 617 for (i = 0; i < len; ++i) 618 printk("%02x ", buf[i]); 619 printk("\n"); 620 } 621 622 /* 623 * Translate received data to pulse and space lengths. 624 * Received data is active low, i.e. pulses are 0 and 625 * spaces are 1. 626 * 627 * My original algorithm was essentially similar to 628 * Changwoo Ryu's with the exception that he switched 629 * the incoming bits to active high and also fed an 630 * initial space to LIRC at the start of a new sequence 631 * if the previous bit was a pulse. 632 * 633 * I've decided to adopt his algorithm. 634 */ 635 636 if (buf[7] == 1 && context->rx.initial_space) { 637 /* LIRC requires a leading space */ 638 context->rx.prev_bit = 0; 639 context->rx.count = 4; 640 submit_data(context); 641 context->rx.count = 0; 642 } 643 644 for (octet = 0; octet < 5; ++octet) { 645 mask = 0x80; 646 for (bit = 0; bit < 8; ++bit) { 647 int curr_bit = !(buf[octet] & mask); 648 if (curr_bit != context->rx.prev_bit) { 649 if (context->rx.count) { 650 submit_data(context); 651 context->rx.count = 0; 652 } 653 context->rx.prev_bit = curr_bit; 654 } 655 ++context->rx.count; 656 mask >>= 1; 657 } 658 } 659 660 if (buf[7] == 10) { 661 if (context->rx.count) { 662 submit_data(context); 663 context->rx.count = 0; 664 } 665 context->rx.initial_space = context->rx.prev_bit; 666 } 667} 668 669/** 670 * Callback function for USB core API: receive data 671 */ 672static void usb_rx_callback(struct urb *urb) 673{ 674 struct imon_context *context; 675 int intfnum = 0; 676 677 if (!urb) 678 return; 679 680 context = (struct imon_context *)urb->context; 681 if (!context) 682 return; 683 684 switch (urb->status) { 685 case -ENOENT: /* usbcore unlink successful! */ 686 return; 687 688 case 0: 689 imon_incoming_packet(context, urb, intfnum); 690 break; 691 692 default: 693 dev_warn(context->driver->dev, "imon %s: status(%d): ignored\n", 694 __func__, urb->status); 695 break; 696 } 697 698 usb_submit_urb(context->rx_urb, GFP_ATOMIC); 699 700 return; 701} 702 703/** 704 * Callback function for USB core API: Probe 705 */ 706static int imon_probe(struct usb_interface *interface, 707 const struct usb_device_id *id) 708{ 709 struct usb_device *usbdev = NULL; 710 struct usb_host_interface *iface_desc = NULL; 711 struct usb_endpoint_descriptor *rx_endpoint = NULL; 712 struct usb_endpoint_descriptor *tx_endpoint = NULL; 713 struct urb *rx_urb = NULL; 714 struct urb *tx_urb = NULL; 715 struct lirc_driver *driver = NULL; 716 struct lirc_buffer *rbuf = NULL; 717 struct device *dev = &interface->dev; 718 int ifnum; 719 int lirc_minor = 0; 720 int num_endpts; 721 int retval = 0; 722 int display_ep_found = 0; 723 int ir_ep_found = 0; 724 int alloc_status = 0; 725 int vfd_proto_6p = 0; 726 struct imon_context *context = NULL; 727 int i; 728 u16 vendor, product; 729 730 /* prevent races probing devices w/multiple interfaces */ 731 mutex_lock(&driver_lock); 732 733 context = kzalloc(sizeof(struct imon_context), GFP_KERNEL); 734 if (!context) { 735 err("%s: kzalloc failed for context", __func__); 736 alloc_status = 1; 737 goto alloc_status_switch; 738 } 739 740 /* 741 * Try to auto-detect the type of display if the user hasn't set 742 * it by hand via the display_type modparam. Default is VFD. 743 */ 744 if (usb_match_id(interface, ir_only_list)) 745 context->display = 0; 746 else 747 context->display = 1; 748 749 usbdev = usb_get_dev(interface_to_usbdev(interface)); 750 iface_desc = interface->cur_altsetting; 751 num_endpts = iface_desc->desc.bNumEndpoints; 752 ifnum = iface_desc->desc.bInterfaceNumber; 753 vendor = le16_to_cpu(usbdev->descriptor.idVendor); 754 product = le16_to_cpu(usbdev->descriptor.idProduct); 755 756 dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n", 757 __func__, vendor, product, ifnum); 758 759 /* 760 * Scan the endpoint list and set: 761 * first input endpoint = IR endpoint 762 * first output endpoint = display endpoint 763 */ 764 for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) { 765 struct usb_endpoint_descriptor *ep; 766 int ep_dir; 767 int ep_type; 768 ep = &iface_desc->endpoint[i].desc; 769 ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; 770 ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; 771 772 if (!ir_ep_found && 773 ep_dir == USB_DIR_IN && 774 ep_type == USB_ENDPOINT_XFER_INT) { 775 776 rx_endpoint = ep; 777 ir_ep_found = 1; 778 dev_dbg(dev, "%s: found IR endpoint\n", __func__); 779 780 } else if (!display_ep_found && ep_dir == USB_DIR_OUT && 781 ep_type == USB_ENDPOINT_XFER_INT) { 782 tx_endpoint = ep; 783 display_ep_found = 1; 784 dev_dbg(dev, "%s: found display endpoint\n", __func__); 785 } 786 } 787 788 /* 789 * Some iMON receivers have no display. Unfortunately, it seems 790 * that SoundGraph recycles device IDs between devices both with 791 * and without... :\ 792 */ 793 if (context->display == 0) { 794 display_ep_found = 0; 795 dev_dbg(dev, "%s: device has no display\n", __func__); 796 } 797 798 /* Input endpoint is mandatory */ 799 if (!ir_ep_found) { 800 err("%s: no valid input (IR) endpoint found.", __func__); 801 retval = -ENODEV; 802 alloc_status = 2; 803 goto alloc_status_switch; 804 } 805 806 /* Determine if display requires 6 packets */ 807 if (display_ep_found) { 808 if (usb_match_id(interface, vfd_proto_6p_list)) 809 vfd_proto_6p = 1; 810 811 dev_dbg(dev, "%s: vfd_proto_6p: %d\n", 812 __func__, vfd_proto_6p); 813 } 814 815 driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); 816 if (!driver) { 817 err("%s: kzalloc failed for lirc_driver", __func__); 818 alloc_status = 2; 819 goto alloc_status_switch; 820 } 821 rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); 822 if (!rbuf) { 823 err("%s: kmalloc failed for lirc_buffer", __func__); 824 alloc_status = 3; 825 goto alloc_status_switch; 826 } 827 if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) { 828 err("%s: lirc_buffer_init failed", __func__); 829 alloc_status = 4; 830 goto alloc_status_switch; 831 } 832 rx_urb = usb_alloc_urb(0, GFP_KERNEL); 833 if (!rx_urb) { 834 err("%s: usb_alloc_urb failed for IR urb", __func__); 835 alloc_status = 5; 836 goto alloc_status_switch; 837 } 838 tx_urb = usb_alloc_urb(0, GFP_KERNEL); 839 if (!tx_urb) { 840 err("%s: usb_alloc_urb failed for display urb", 841 __func__); 842 alloc_status = 6; 843 goto alloc_status_switch; 844 } 845 846 mutex_init(&context->ctx_lock); 847 context->vfd_proto_6p = vfd_proto_6p; 848 849 strcpy(driver->name, MOD_NAME); 850 driver->minor = -1; 851 driver->code_length = BUF_CHUNK_SIZE * 8; 852 driver->sample_rate = 0; 853 driver->features = LIRC_CAN_REC_MODE2; 854 driver->data = context; 855 driver->rbuf = rbuf; 856 driver->set_use_inc = ir_open; 857 driver->set_use_dec = ir_close; 858 driver->dev = &interface->dev; 859 driver->owner = THIS_MODULE; 860 861 mutex_lock(&context->ctx_lock); 862 863 context->driver = driver; 864 /* start out in keyboard mode */ 865 866 lirc_minor = lirc_register_driver(driver); 867 if (lirc_minor < 0) { 868 err("%s: lirc_register_driver failed", __func__); 869 alloc_status = 7; 870 goto unlock; 871 } else 872 dev_info(dev, "Registered iMON driver " 873 "(lirc minor: %d)\n", lirc_minor); 874 875 /* Needed while unregistering! */ 876 driver->minor = lirc_minor; 877 878 context->usbdev = usbdev; 879 context->dev_present = 1; 880 context->rx_endpoint = rx_endpoint; 881 context->rx_urb = rx_urb; 882 883 /* 884 * tx is used to send characters to lcd/vfd, associate RF 885 * remotes, set IR protocol, and maybe more... 886 */ 887 context->tx_endpoint = tx_endpoint; 888 context->tx_urb = tx_urb; 889 890 if (display_ep_found) 891 context->display = 1; 892 893 usb_fill_int_urb(context->rx_urb, context->usbdev, 894 usb_rcvintpipe(context->usbdev, 895 context->rx_endpoint->bEndpointAddress), 896 context->usb_rx_buf, sizeof(context->usb_rx_buf), 897 usb_rx_callback, context, 898 context->rx_endpoint->bInterval); 899 900 retval = usb_submit_urb(context->rx_urb, GFP_KERNEL); 901 902 if (retval) { 903 err("%s: usb_submit_urb failed for intf0 (%d)", 904 __func__, retval); 905 mutex_unlock(&context->ctx_lock); 906 goto exit; 907 } 908 909 usb_set_intfdata(interface, context); 910 911 if (context->display && ifnum == 0) { 912 dev_dbg(dev, "%s: Registering iMON display with sysfs\n", 913 __func__); 914 915 if (usb_register_dev(interface, &imon_class)) { 916 /* Not a fatal error, so ignore */ 917 dev_info(dev, "%s: could not get a minor number for " 918 "display\n", __func__); 919 } 920 } 921 922 dev_info(dev, "iMON device (%04x:%04x, intf%d) on " 923 "usb<%d:%d> initialized\n", vendor, product, ifnum, 924 usbdev->bus->busnum, usbdev->devnum); 925 926unlock: 927 mutex_unlock(&context->ctx_lock); 928alloc_status_switch: 929 930 switch (alloc_status) { 931 case 7: 932 usb_free_urb(tx_urb); 933 case 6: 934 usb_free_urb(rx_urb); 935 case 5: 936 if (rbuf) 937 lirc_buffer_free(rbuf); 938 case 4: 939 kfree(rbuf); 940 case 3: 941 kfree(driver); 942 case 2: 943 kfree(context); 944 context = NULL; 945 case 1: 946 if (retval != -ENODEV) 947 retval = -ENOMEM; 948 break; 949 case 0: 950 retval = 0; 951 } 952 953exit: 954 mutex_unlock(&driver_lock); 955 956 return retval; 957} 958 959/** 960 * Callback function for USB core API: disconnect 961 */ 962static void imon_disconnect(struct usb_interface *interface) 963{ 964 struct imon_context *context; 965 int ifnum; 966 967 /* prevent races with ir_open()/display_open() */ 968 mutex_lock(&driver_lock); 969 970 context = usb_get_intfdata(interface); 971 ifnum = interface->cur_altsetting->desc.bInterfaceNumber; 972 973 mutex_lock(&context->ctx_lock); 974 975 usb_set_intfdata(interface, NULL); 976 977 /* Abort ongoing write */ 978 if (atomic_read(&context->tx.busy)) { 979 usb_kill_urb(context->tx_urb); 980 complete_all(&context->tx.finished); 981 } 982 983 context->dev_present = 0; 984 usb_kill_urb(context->rx_urb); 985 if (context->display) 986 usb_deregister_dev(interface, &imon_class); 987 988 if (!context->ir_isopen && !context->dev_present) { 989 deregister_from_lirc(context); 990 mutex_unlock(&context->ctx_lock); 991 if (!context->display_isopen) 992 free_imon_context(context); 993 } else 994 mutex_unlock(&context->ctx_lock); 995 996 mutex_unlock(&driver_lock); 997 998 printk(KERN_INFO "%s: iMON device (intf%d) disconnected\n", 999 __func__, ifnum); 1000} 1001 1002static int imon_suspend(struct usb_interface *intf, pm_message_t message) 1003{ 1004 struct imon_context *context = usb_get_intfdata(intf); 1005 1006 usb_kill_urb(context->rx_urb); 1007 1008 return 0; 1009} 1010 1011static int imon_resume(struct usb_interface *intf) 1012{ 1013 int rc = 0; 1014 struct imon_context *context = usb_get_intfdata(intf); 1015 1016 usb_fill_int_urb(context->rx_urb, context->usbdev, 1017 usb_rcvintpipe(context->usbdev, 1018 context->rx_endpoint->bEndpointAddress), 1019 context->usb_rx_buf, sizeof(context->usb_rx_buf), 1020 usb_rx_callback, context, 1021 context->rx_endpoint->bInterval); 1022 1023 rc = usb_submit_urb(context->rx_urb, GFP_ATOMIC); 1024 1025 return rc; 1026} 1027 1028module_usb_driver(imon_driver); 1029