Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] staging: lirc_sasem: remove

This driver was merged in 2010 and never had the necessary work done
to promote it out of staging (port to rc-core), so remove it.

I have not managed to track down the hardware. If anyone has the
hardware and would like a driver for it, please contact me and
hopefully we can work together to write a new driver.

Signed-off-by: Sean Young <sean@mess.org>
Cc: Oliver Stabel <oliver.stabel@gmx.de>
Cc: Tim Davies <tim@opensystems.net.au>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Sean Young and committed by
Mauro Carvalho Chehab
51bb3fd7 e6626716

-906
-6
drivers/staging/media/lirc/Kconfig
··· 12 12 13 13 if LIRC_STAGING 14 14 15 - config LIRC_SASEM 16 - tristate "Sasem USB IR Remote" 17 - depends on LIRC && USB 18 - help 19 - Driver for the Sasem OnAir Remocon-V or Dign HV5 HTPC IR/VFD Module 20 - 21 15 config LIRC_ZILOG 22 16 tristate "Zilog/Hauppauge IR Transmitter" 23 17 depends on LIRC && I2C
-1
drivers/staging/media/lirc/Makefile
··· 3 3 4 4 # Each configuration option enables a list of files. 5 5 6 - obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o 7 6 obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o
-899
drivers/staging/media/lirc/lirc_sasem.c
··· 1 - /* 2 - * lirc_sasem.c - USB remote support for LIRC 3 - * Version 0.5 4 - * 5 - * Copyright (C) 2004-2005 Oliver Stabel <oliver.stabel@gmx.de> 6 - * Tim Davies <tim@opensystems.net.au> 7 - * 8 - * This driver was derived from: 9 - * Venky Raju <dev@venky.ws> 10 - * "lirc_imon - "LIRC/VFD driver for Ahanix/Soundgraph IMON IR/VFD" 11 - * Paul Miller <pmiller9@users.sourceforge.net>'s 2003-2004 12 - * "lirc_atiusb - USB remote support for LIRC" 13 - * Culver Consulting Services <henry@culcon.com>'s 2003 14 - * "Sasem OnAir VFD/IR USB driver" 15 - * 16 - * 17 - * NOTE - The LCDproc iMon driver should work with this module. More info at 18 - * http://www.frogstorm.info/sasem 19 - */ 20 - 21 - /* 22 - * This program is free software; you can redistribute it and/or modify 23 - * it under the terms of the GNU General Public License as published by 24 - * the Free Software Foundation; either version 2 of the License, or 25 - * (at your option) any later version. 26 - * 27 - * This program is distributed in the hope that it will be useful, 28 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 29 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 - * GNU General Public License for more details. 31 - * 32 - * You should have received a copy of the GNU General Public License 33 - * along with this program; if not, write to the Free Software 34 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 35 - */ 36 - 37 - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 38 - 39 - #include <linux/errno.h> 40 - #include <linux/kernel.h> 41 - #include <linux/module.h> 42 - #include <linux/slab.h> 43 - #include <linux/uaccess.h> 44 - #include <linux/usb.h> 45 - #include <linux/ktime.h> 46 - 47 - #include <media/lirc.h> 48 - #include <media/lirc_dev.h> 49 - 50 - #define MOD_AUTHOR "Oliver Stabel <oliver.stabel@gmx.de>, " \ 51 - "Tim Davies <tim@opensystems.net.au>" 52 - #define MOD_DESC "USB Driver for Sasem Remote Controller V1.1" 53 - #define MOD_NAME "lirc_sasem" 54 - #define MOD_VERSION "0.5" 55 - 56 - #define VFD_MINOR_BASE 144 /* Same as LCD */ 57 - #define DEVICE_NAME "lcd%d" 58 - 59 - #define BUF_CHUNK_SIZE 8 60 - #define BUF_SIZE 128 61 - 62 - #define IOCTL_LCD_CONTRAST 1 63 - 64 - /*** P R O T O T Y P E S ***/ 65 - 66 - /* USB Callback prototypes */ 67 - static int sasem_probe(struct usb_interface *interface, 68 - const struct usb_device_id *id); 69 - static void sasem_disconnect(struct usb_interface *interface); 70 - static void usb_rx_callback(struct urb *urb); 71 - static void usb_tx_callback(struct urb *urb); 72 - 73 - /* VFD file_operations function prototypes */ 74 - static int vfd_open(struct inode *inode, struct file *file); 75 - static long vfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 76 - static int vfd_close(struct inode *inode, struct file *file); 77 - static ssize_t vfd_write(struct file *file, const char __user *buf, 78 - size_t n_bytes, loff_t *pos); 79 - 80 - /* LIRC driver function prototypes */ 81 - static int ir_open(void *data); 82 - static void ir_close(void *data); 83 - 84 - /*** G L O B A L S ***/ 85 - #define SASEM_DATA_BUF_SZ 32 86 - 87 - struct sasem_context { 88 - struct usb_device *dev; 89 - int vfd_isopen; /* VFD port has been opened */ 90 - unsigned int vfd_contrast; /* VFD contrast */ 91 - int ir_isopen; /* IR port has been opened */ 92 - int dev_present; /* USB device presence */ 93 - struct mutex ctx_lock; /* to lock this object */ 94 - wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ 95 - 96 - struct lirc_driver *driver; 97 - struct usb_endpoint_descriptor *rx_endpoint; 98 - struct usb_endpoint_descriptor *tx_endpoint; 99 - struct urb *rx_urb; 100 - struct urb *tx_urb; 101 - unsigned char usb_rx_buf[8]; 102 - unsigned char usb_tx_buf[8]; 103 - 104 - struct tx_t { 105 - unsigned char data_buf[SASEM_DATA_BUF_SZ]; /* user data 106 - * buffer 107 - */ 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 - /* for dealing with repeat codes (wish there was a toggle bit!) */ 114 - ktime_t presstime; 115 - char lastcode[8]; 116 - int codesaved; 117 - }; 118 - 119 - /* VFD file operations */ 120 - static const struct file_operations vfd_fops = { 121 - .owner = THIS_MODULE, 122 - .open = &vfd_open, 123 - .write = vfd_write, 124 - .unlocked_ioctl = &vfd_ioctl, 125 - .release = &vfd_close, 126 - .llseek = noop_llseek, 127 - }; 128 - 129 - /* USB Device ID for Sasem USB Control Board */ 130 - static struct usb_device_id sasem_usb_id_table[] = { 131 - /* Sasem USB Control Board */ 132 - { USB_DEVICE(0x11ba, 0x0101) }, 133 - /* Terminating entry */ 134 - {} 135 - }; 136 - 137 - /* USB Device data */ 138 - static struct usb_driver sasem_driver = { 139 - .name = MOD_NAME, 140 - .probe = sasem_probe, 141 - .disconnect = sasem_disconnect, 142 - .id_table = sasem_usb_id_table, 143 - }; 144 - 145 - static struct usb_class_driver sasem_class = { 146 - .name = DEVICE_NAME, 147 - .fops = &vfd_fops, 148 - .minor_base = VFD_MINOR_BASE, 149 - }; 150 - 151 - /* to prevent races between open() and disconnect() */ 152 - static DEFINE_MUTEX(disconnect_lock); 153 - 154 - static int debug; 155 - 156 - 157 - /*** M O D U L E C O D E ***/ 158 - MODULE_AUTHOR(MOD_AUTHOR); 159 - MODULE_DESCRIPTION(MOD_DESC); 160 - MODULE_LICENSE("GPL"); 161 - module_param(debug, int, 0644); 162 - MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)"); 163 - 164 - static void delete_context(struct sasem_context *context) 165 - { 166 - usb_free_urb(context->tx_urb); /* VFD */ 167 - usb_free_urb(context->rx_urb); /* IR */ 168 - lirc_buffer_free(context->driver->rbuf); 169 - kfree(context->driver->rbuf); 170 - kfree(context->driver); 171 - kfree(context); 172 - } 173 - 174 - static void deregister_from_lirc(struct sasem_context *context) 175 - { 176 - int retval; 177 - int minor = context->driver->minor; 178 - 179 - retval = lirc_unregister_driver(minor); 180 - if (retval) 181 - dev_err(&context->dev->dev, 182 - "%s: unable to deregister from lirc (%d)\n", 183 - __func__, retval); 184 - else 185 - dev_info(&context->dev->dev, 186 - "Deregistered Sasem driver (minor:%d)\n", minor); 187 - } 188 - 189 - /** 190 - * Called when the VFD device (e.g. /dev/usb/lcd) 191 - * is opened by the application. 192 - */ 193 - static int vfd_open(struct inode *inode, struct file *file) 194 - { 195 - struct usb_interface *interface; 196 - struct sasem_context *context = NULL; 197 - int subminor; 198 - int retval = 0; 199 - 200 - /* prevent races with disconnect */ 201 - mutex_lock(&disconnect_lock); 202 - 203 - subminor = iminor(inode); 204 - interface = usb_find_interface(&sasem_driver, subminor); 205 - if (!interface) { 206 - pr_err("%s: could not find interface for minor %d\n", 207 - __func__, subminor); 208 - retval = -ENODEV; 209 - goto exit; 210 - } 211 - context = usb_get_intfdata(interface); 212 - 213 - if (!context) { 214 - dev_err(&interface->dev, "no context found for minor %d\n", 215 - subminor); 216 - retval = -ENODEV; 217 - goto exit; 218 - } 219 - 220 - mutex_lock(&context->ctx_lock); 221 - 222 - if (context->vfd_isopen) { 223 - dev_err(&interface->dev, 224 - "%s: VFD port is already open", __func__); 225 - retval = -EBUSY; 226 - } else { 227 - context->vfd_isopen = 1; 228 - file->private_data = context; 229 - dev_info(&interface->dev, "VFD port opened\n"); 230 - } 231 - 232 - mutex_unlock(&context->ctx_lock); 233 - 234 - exit: 235 - mutex_unlock(&disconnect_lock); 236 - return retval; 237 - } 238 - 239 - /** 240 - * Called when the VFD device (e.g. /dev/usb/lcd) 241 - * is closed by the application. 242 - */ 243 - static long vfd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 244 - { 245 - struct sasem_context *context; 246 - 247 - context = (struct sasem_context *) file->private_data; 248 - 249 - if (!context) { 250 - pr_err("%s: no context for device\n", __func__); 251 - return -ENODEV; 252 - } 253 - 254 - mutex_lock(&context->ctx_lock); 255 - 256 - switch (cmd) { 257 - case IOCTL_LCD_CONTRAST: 258 - if (arg > 1000) 259 - arg = 1000; 260 - context->vfd_contrast = (unsigned int)arg; 261 - break; 262 - default: 263 - pr_info("Unknown IOCTL command\n"); 264 - mutex_unlock(&context->ctx_lock); 265 - return -ENOIOCTLCMD; /* not supported */ 266 - } 267 - 268 - mutex_unlock(&context->ctx_lock); 269 - return 0; 270 - } 271 - 272 - /** 273 - * Called when the VFD device (e.g. /dev/usb/lcd) 274 - * is closed by the application. 275 - */ 276 - static int vfd_close(struct inode *inode, struct file *file) 277 - { 278 - struct sasem_context *context = NULL; 279 - int retval = 0; 280 - 281 - context = (struct sasem_context *) file->private_data; 282 - 283 - if (!context) { 284 - pr_err("%s: no context for device\n", __func__); 285 - return -ENODEV; 286 - } 287 - 288 - mutex_lock(&context->ctx_lock); 289 - 290 - if (!context->vfd_isopen) { 291 - dev_err(&context->dev->dev, "%s: VFD is not open\n", __func__); 292 - retval = -EIO; 293 - } else { 294 - context->vfd_isopen = 0; 295 - dev_info(&context->dev->dev, "VFD port closed\n"); 296 - if (!context->dev_present && !context->ir_isopen) { 297 - /* Device disconnected before close and IR port is 298 - * not open. If IR port is open, context will be 299 - * deleted by ir_close. 300 - */ 301 - mutex_unlock(&context->ctx_lock); 302 - delete_context(context); 303 - return retval; 304 - } 305 - } 306 - 307 - mutex_unlock(&context->ctx_lock); 308 - return retval; 309 - } 310 - 311 - /** 312 - * Sends a packet to the VFD. 313 - */ 314 - static int send_packet(struct sasem_context *context) 315 - { 316 - unsigned int pipe; 317 - int interval = 0; 318 - int retval = 0; 319 - 320 - pipe = usb_sndintpipe(context->dev, 321 - context->tx_endpoint->bEndpointAddress); 322 - interval = context->tx_endpoint->bInterval; 323 - 324 - usb_fill_int_urb(context->tx_urb, context->dev, pipe, 325 - context->usb_tx_buf, sizeof(context->usb_tx_buf), 326 - usb_tx_callback, context, interval); 327 - 328 - context->tx_urb->actual_length = 0; 329 - 330 - init_completion(&context->tx.finished); 331 - atomic_set(&context->tx.busy, 1); 332 - 333 - retval = usb_submit_urb(context->tx_urb, GFP_KERNEL); 334 - if (retval) { 335 - atomic_set(&context->tx.busy, 0); 336 - dev_err(&context->dev->dev, "error submitting urb (%d)\n", 337 - retval); 338 - } else { 339 - /* Wait for transmission to complete (or abort) */ 340 - mutex_unlock(&context->ctx_lock); 341 - wait_for_completion(&context->tx.finished); 342 - mutex_lock(&context->ctx_lock); 343 - 344 - retval = context->tx.status; 345 - if (retval) 346 - dev_err(&context->dev->dev, 347 - "packet tx failed (%d)\n", retval); 348 - } 349 - 350 - return retval; 351 - } 352 - 353 - /** 354 - * Writes data to the VFD. The Sasem VFD is 2x16 characters 355 - * and requires data in 9 consecutive USB interrupt packets, 356 - * each packet carrying 8 bytes. 357 - */ 358 - static ssize_t vfd_write(struct file *file, const char __user *buf, 359 - size_t n_bytes, loff_t *pos) 360 - { 361 - int i; 362 - int retval = 0; 363 - struct sasem_context *context; 364 - int *data_buf = NULL; 365 - 366 - context = (struct sasem_context *) file->private_data; 367 - if (!context) { 368 - pr_err("%s: no context for device\n", __func__); 369 - return -ENODEV; 370 - } 371 - 372 - mutex_lock(&context->ctx_lock); 373 - 374 - if (!context->dev_present) { 375 - pr_err("%s: no Sasem device present\n", __func__); 376 - retval = -ENODEV; 377 - goto exit; 378 - } 379 - 380 - if (n_bytes <= 0 || n_bytes > SASEM_DATA_BUF_SZ) { 381 - dev_err(&context->dev->dev, "%s: invalid payload size\n", 382 - __func__); 383 - retval = -EINVAL; 384 - goto exit; 385 - } 386 - 387 - data_buf = memdup_user(buf, n_bytes); 388 - if (IS_ERR(data_buf)) { 389 - mutex_unlock(&context->ctx_lock); 390 - return PTR_ERR(data_buf); 391 - } 392 - 393 - memcpy(context->tx.data_buf, data_buf, n_bytes); 394 - 395 - /* Pad with spaces */ 396 - for (i = n_bytes; i < SASEM_DATA_BUF_SZ; ++i) 397 - context->tx.data_buf[i] = ' '; 398 - 399 - /* Nine 8 byte packets to be sent */ 400 - /* NOTE: "\x07\x01\0\0\0\0\0\0" or "\x0c\0\0\0\0\0\0\0" 401 - * will clear the VFD 402 - */ 403 - for (i = 0; i < 9; i++) { 404 - switch (i) { 405 - case 0: 406 - memcpy(context->usb_tx_buf, "\x07\0\0\0\0\0\0\0", 8); 407 - context->usb_tx_buf[1] = (context->vfd_contrast) ? 408 - (0x2B - (context->vfd_contrast - 1) / 250) 409 - : 0x2B; 410 - break; 411 - case 1: 412 - memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8); 413 - break; 414 - case 2: 415 - memcpy(context->usb_tx_buf, "\x0b\x01\0\0\0\0\0\0", 8); 416 - break; 417 - case 3: 418 - memcpy(context->usb_tx_buf, context->tx.data_buf, 8); 419 - break; 420 - case 4: 421 - memcpy(context->usb_tx_buf, 422 - context->tx.data_buf + 8, 8); 423 - break; 424 - case 5: 425 - memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8); 426 - break; 427 - case 6: 428 - memcpy(context->usb_tx_buf, "\x0b\x02\0\0\0\0\0\0", 8); 429 - break; 430 - case 7: 431 - memcpy(context->usb_tx_buf, 432 - context->tx.data_buf + 16, 8); 433 - break; 434 - case 8: 435 - memcpy(context->usb_tx_buf, 436 - context->tx.data_buf + 24, 8); 437 - break; 438 - } 439 - retval = send_packet(context); 440 - if (retval) { 441 - dev_err(&context->dev->dev, 442 - "send packet failed for packet #%d\n", i); 443 - goto exit; 444 - } 445 - } 446 - exit: 447 - 448 - mutex_unlock(&context->ctx_lock); 449 - kfree(data_buf); 450 - 451 - return (!retval) ? n_bytes : retval; 452 - } 453 - 454 - /** 455 - * Callback function for USB core API: transmit data 456 - */ 457 - static void usb_tx_callback(struct urb *urb) 458 - { 459 - struct sasem_context *context; 460 - 461 - if (!urb) 462 - return; 463 - context = (struct sasem_context *) urb->context; 464 - if (!context) 465 - return; 466 - 467 - context->tx.status = urb->status; 468 - 469 - /* notify waiters that write has finished */ 470 - atomic_set(&context->tx.busy, 0); 471 - complete(&context->tx.finished); 472 - } 473 - 474 - /** 475 - * Called by lirc_dev when the application opens /dev/lirc 476 - */ 477 - static int ir_open(void *data) 478 - { 479 - int retval = 0; 480 - struct sasem_context *context; 481 - 482 - /* prevent races with disconnect */ 483 - mutex_lock(&disconnect_lock); 484 - 485 - context = data; 486 - 487 - mutex_lock(&context->ctx_lock); 488 - 489 - if (context->ir_isopen) { 490 - dev_err(&context->dev->dev, "%s: IR port is already open\n", 491 - __func__); 492 - retval = -EBUSY; 493 - goto exit; 494 - } 495 - 496 - usb_fill_int_urb(context->rx_urb, context->dev, 497 - usb_rcvintpipe(context->dev, 498 - context->rx_endpoint->bEndpointAddress), 499 - context->usb_rx_buf, sizeof(context->usb_rx_buf), 500 - usb_rx_callback, context, context->rx_endpoint->bInterval); 501 - 502 - retval = usb_submit_urb(context->rx_urb, GFP_KERNEL); 503 - 504 - if (retval) 505 - dev_err(&context->dev->dev, 506 - "usb_submit_urb failed for ir_open (%d)\n", retval); 507 - else { 508 - context->ir_isopen = 1; 509 - dev_info(&context->dev->dev, "IR port opened\n"); 510 - } 511 - 512 - exit: 513 - mutex_unlock(&context->ctx_lock); 514 - 515 - mutex_unlock(&disconnect_lock); 516 - return retval; 517 - } 518 - 519 - /** 520 - * Called by lirc_dev when the application closes /dev/lirc 521 - */ 522 - static void ir_close(void *data) 523 - { 524 - struct sasem_context *context; 525 - 526 - context = data; 527 - if (!context) { 528 - pr_err("%s: no context for device\n", __func__); 529 - return; 530 - } 531 - 532 - mutex_lock(&context->ctx_lock); 533 - 534 - usb_kill_urb(context->rx_urb); 535 - context->ir_isopen = 0; 536 - pr_info("IR port closed\n"); 537 - 538 - if (!context->dev_present) { 539 - 540 - /* 541 - * Device disconnected while IR port was 542 - * still open. Driver was not deregistered 543 - * at disconnect time, so do it now. 544 - */ 545 - deregister_from_lirc(context); 546 - if (!context->vfd_isopen) { 547 - mutex_unlock(&context->ctx_lock); 548 - delete_context(context); 549 - return; 550 - } 551 - /* If VFD port is open, context will be deleted by vfd_close */ 552 - } 553 - 554 - mutex_unlock(&context->ctx_lock); 555 - } 556 - 557 - /** 558 - * Process the incoming packet 559 - */ 560 - static void incoming_packet(struct sasem_context *context, 561 - struct urb *urb) 562 - { 563 - int len = urb->actual_length; 564 - unsigned char *buf = urb->transfer_buffer; 565 - u64 ns; 566 - ktime_t kt; 567 - 568 - if (len != 8) { 569 - dev_warn(&context->dev->dev, 570 - "%s: invalid incoming packet size (%d)\n", 571 - __func__, len); 572 - return; 573 - } 574 - 575 - if (debug) 576 - dev_info(&context->dev->dev, "Incoming data: %*ph\n", len, buf); 577 - /* 578 - * Lirc could deal with the repeat code, but we really need to block it 579 - * if it arrives too late. Otherwise we could repeat the wrong code. 580 - */ 581 - 582 - /* get the time since the last button press */ 583 - kt = ktime_get(); 584 - ns = ktime_to_ns(ktime_sub(kt, context->presstime)); 585 - 586 - if (memcmp(buf, "\x08\0\0\0\0\0\0\0", 8) == 0) { 587 - /* 588 - * the repeat code is being sent, so we copy 589 - * the old code to LIRC 590 - */ 591 - 592 - /* 593 - * NOTE: Only if the last code was less than 250ms ago 594 - * - no one should be able to push another (undetected) button 595 - * in that time and then get a false repeat of the previous 596 - * press but it is long enough for a genuine repeat 597 - */ 598 - if ((ns < 250 * NSEC_PER_MSEC) && (context->codesaved != 0)) { 599 - memcpy(buf, &context->lastcode, 8); 600 - context->presstime = kt; 601 - } 602 - } else { 603 - /* save the current valid code for repeats */ 604 - memcpy(&context->lastcode, buf, 8); 605 - /* 606 - * set flag to signal a valid code was save; 607 - * just for safety reasons 608 - */ 609 - context->codesaved = 1; 610 - context->presstime = kt; 611 - } 612 - 613 - lirc_buffer_write(context->driver->rbuf, buf); 614 - wake_up(&context->driver->rbuf->wait_poll); 615 - } 616 - 617 - /** 618 - * Callback function for USB core API: receive data 619 - */ 620 - static void usb_rx_callback(struct urb *urb) 621 - { 622 - struct sasem_context *context; 623 - 624 - if (!urb) 625 - return; 626 - context = (struct sasem_context *) urb->context; 627 - if (!context) 628 - return; 629 - 630 - switch (urb->status) { 631 - case -ENOENT: /* usbcore unlink successful! */ 632 - return; 633 - 634 - case 0: 635 - if (context->ir_isopen) 636 - incoming_packet(context, urb); 637 - break; 638 - 639 - default: 640 - dev_warn(&urb->dev->dev, "%s: status (%d): ignored", 641 - __func__, urb->status); 642 - break; 643 - } 644 - 645 - usb_submit_urb(context->rx_urb, GFP_ATOMIC); 646 - } 647 - 648 - /** 649 - * Callback function for USB core API: Probe 650 - */ 651 - static int sasem_probe(struct usb_interface *interface, 652 - const struct usb_device_id *id) 653 - { 654 - struct usb_device *dev = NULL; 655 - struct usb_host_interface *iface_desc = NULL; 656 - struct usb_endpoint_descriptor *rx_endpoint = NULL; 657 - struct usb_endpoint_descriptor *tx_endpoint = NULL; 658 - struct urb *rx_urb = NULL; 659 - struct urb *tx_urb = NULL; 660 - struct lirc_driver *driver = NULL; 661 - struct lirc_buffer *rbuf = NULL; 662 - int lirc_minor = 0; 663 - int num_endpoints; 664 - int retval = 0; 665 - int vfd_ep_found; 666 - int ir_ep_found; 667 - int alloc_status; 668 - struct sasem_context *context = NULL; 669 - int i; 670 - 671 - dev_info(&interface->dev, "%s: found Sasem device\n", __func__); 672 - 673 - 674 - dev = usb_get_dev(interface_to_usbdev(interface)); 675 - iface_desc = interface->cur_altsetting; 676 - num_endpoints = iface_desc->desc.bNumEndpoints; 677 - 678 - /* 679 - * Scan the endpoint list and set: 680 - * first input endpoint = IR endpoint 681 - * first output endpoint = VFD endpoint 682 - */ 683 - 684 - ir_ep_found = 0; 685 - vfd_ep_found = 0; 686 - 687 - for (i = 0; i < num_endpoints && !(ir_ep_found && vfd_ep_found); ++i) { 688 - 689 - struct usb_endpoint_descriptor *ep; 690 - 691 - ep = &iface_desc->endpoint [i].desc; 692 - 693 - if (!ir_ep_found && 694 - usb_endpoint_is_int_in(ep)) { 695 - 696 - rx_endpoint = ep; 697 - ir_ep_found = 1; 698 - if (debug) 699 - dev_info(&interface->dev, 700 - "%s: found IR endpoint\n", __func__); 701 - 702 - } else if (!vfd_ep_found && 703 - usb_endpoint_is_int_out(ep)) { 704 - tx_endpoint = ep; 705 - vfd_ep_found = 1; 706 - if (debug) 707 - dev_info(&interface->dev, 708 - "%s: found VFD endpoint\n", __func__); 709 - } 710 - } 711 - 712 - /* Input endpoint is mandatory */ 713 - if (!ir_ep_found) { 714 - dev_err(&interface->dev, 715 - "%s: no valid input (IR) endpoint found.\n", __func__); 716 - retval = -ENODEV; 717 - goto exit; 718 - } 719 - 720 - if (!vfd_ep_found) 721 - dev_info(&interface->dev, 722 - "%s: no valid output (VFD) endpoint found.\n", 723 - __func__); 724 - 725 - 726 - /* Allocate memory */ 727 - alloc_status = 0; 728 - 729 - context = kzalloc(sizeof(*context), GFP_KERNEL); 730 - if (!context) { 731 - alloc_status = 1; 732 - goto alloc_status_switch; 733 - } 734 - driver = kzalloc(sizeof(*driver), GFP_KERNEL); 735 - if (!driver) { 736 - alloc_status = 2; 737 - goto alloc_status_switch; 738 - } 739 - rbuf = kmalloc(sizeof(*rbuf), GFP_KERNEL); 740 - if (!rbuf) { 741 - alloc_status = 3; 742 - goto alloc_status_switch; 743 - } 744 - if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) { 745 - dev_err(&interface->dev, 746 - "%s: lirc_buffer_init failed\n", __func__); 747 - alloc_status = 4; 748 - goto alloc_status_switch; 749 - } 750 - rx_urb = usb_alloc_urb(0, GFP_KERNEL); 751 - if (!rx_urb) { 752 - alloc_status = 5; 753 - goto alloc_status_switch; 754 - } 755 - if (vfd_ep_found) { 756 - tx_urb = usb_alloc_urb(0, GFP_KERNEL); 757 - if (!tx_urb) { 758 - alloc_status = 6; 759 - goto alloc_status_switch; 760 - } 761 - } 762 - 763 - mutex_init(&context->ctx_lock); 764 - 765 - strcpy(driver->name, MOD_NAME); 766 - driver->minor = -1; 767 - driver->code_length = 64; 768 - driver->sample_rate = 0; 769 - driver->features = LIRC_CAN_REC_LIRCCODE; 770 - driver->data = context; 771 - driver->rbuf = rbuf; 772 - driver->set_use_inc = ir_open; 773 - driver->set_use_dec = ir_close; 774 - driver->dev = &interface->dev; 775 - driver->owner = THIS_MODULE; 776 - 777 - mutex_lock(&context->ctx_lock); 778 - 779 - lirc_minor = lirc_register_driver(driver); 780 - if (lirc_minor < 0) { 781 - dev_err(&interface->dev, 782 - "%s: lirc_register_driver failed\n", __func__); 783 - alloc_status = 7; 784 - retval = lirc_minor; 785 - goto unlock; 786 - } else 787 - dev_info(&interface->dev, 788 - "%s: Registered Sasem driver (minor:%d)\n", 789 - __func__, lirc_minor); 790 - 791 - /* Needed while unregistering! */ 792 - driver->minor = lirc_minor; 793 - 794 - context->dev = dev; 795 - context->dev_present = 1; 796 - context->rx_endpoint = rx_endpoint; 797 - context->rx_urb = rx_urb; 798 - if (vfd_ep_found) { 799 - context->tx_endpoint = tx_endpoint; 800 - context->tx_urb = tx_urb; 801 - context->vfd_contrast = 1000; /* range 0 - 1000 */ 802 - } 803 - context->driver = driver; 804 - 805 - usb_set_intfdata(interface, context); 806 - 807 - if (vfd_ep_found) { 808 - 809 - if (debug) 810 - dev_info(&interface->dev, 811 - "Registering VFD with sysfs\n"); 812 - if (usb_register_dev(interface, &sasem_class)) 813 - /* Not a fatal error, so ignore */ 814 - dev_info(&interface->dev, 815 - "%s: could not get a minor number for VFD\n", 816 - __func__); 817 - } 818 - 819 - dev_info(&interface->dev, 820 - "%s: Sasem device on usb<%d:%d> initialized\n", 821 - __func__, dev->bus->busnum, dev->devnum); 822 - unlock: 823 - mutex_unlock(&context->ctx_lock); 824 - 825 - alloc_status_switch: 826 - switch (alloc_status) { 827 - 828 - case 7: 829 - if (vfd_ep_found) 830 - usb_free_urb(tx_urb); 831 - case 6: 832 - usb_free_urb(rx_urb); 833 - /* fall-through */ 834 - case 5: 835 - lirc_buffer_free(rbuf); 836 - /* fall-through */ 837 - case 4: 838 - kfree(rbuf); 839 - /* fall-through */ 840 - case 3: 841 - kfree(driver); 842 - /* fall-through */ 843 - case 2: 844 - kfree(context); 845 - context = NULL; 846 - /* fall-through */ 847 - case 1: 848 - if (retval == 0) 849 - retval = -ENOMEM; 850 - } 851 - 852 - exit: 853 - return retval; 854 - } 855 - 856 - /** 857 - * Callback function for USB core API: disconnect 858 - */ 859 - static void sasem_disconnect(struct usb_interface *interface) 860 - { 861 - struct sasem_context *context; 862 - 863 - /* prevent races with ir_open()/vfd_open() */ 864 - mutex_lock(&disconnect_lock); 865 - 866 - context = usb_get_intfdata(interface); 867 - mutex_lock(&context->ctx_lock); 868 - 869 - dev_info(&interface->dev, "%s: Sasem device disconnected\n", 870 - __func__); 871 - 872 - usb_set_intfdata(interface, NULL); 873 - context->dev_present = 0; 874 - 875 - /* Stop reception */ 876 - usb_kill_urb(context->rx_urb); 877 - 878 - /* Abort ongoing write */ 879 - if (atomic_read(&context->tx.busy)) { 880 - 881 - usb_kill_urb(context->tx_urb); 882 - wait_for_completion(&context->tx.finished); 883 - } 884 - 885 - /* De-register from lirc_dev if IR port is not open */ 886 - if (!context->ir_isopen) 887 - deregister_from_lirc(context); 888 - 889 - usb_deregister_dev(interface, &sasem_class); 890 - 891 - mutex_unlock(&context->ctx_lock); 892 - 893 - if (!context->ir_isopen && !context->vfd_isopen) 894 - delete_context(context); 895 - 896 - mutex_unlock(&disconnect_lock); 897 - } 898 - 899 - module_usb_driver(sasem_driver);