1/* 2 * lirc_igorplugusb - USB remote support for LIRC 3 * 4 * Supports the standard homebrew IgorPlugUSB receiver with Igor's firmware. 5 * See http://www.cesko.host.sk/IgorPlugUSB/IgorPlug-USB%20(AVR)_eng.htm 6 * 7 * The device can only record bursts of up to 36 pulses/spaces. 8 * Works fine with RC5. Longer commands lead to device buffer overrun. 9 * (Maybe a better firmware or a microcontroller with more ram can help?) 10 * 11 * Version 0.1 [beta status] 12 * 13 * Copyright (C) 2004 Jan M. Hochstein 14 * <hochstein@algo.informatik.tu-darmstadt.de> 15 * 16 * This driver was derived from: 17 * Paul Miller <pmiller9@users.sourceforge.net> 18 * "lirc_atiusb" module 19 * Vladimir Dergachev <volodya@minspring.com>'s 2002 20 * "USB ATI Remote support" (input device) 21 * Adrian Dewhurst <sailor-lk@sailorfrag.net>'s 2002 22 * "USB StreamZap remote driver" (LIRC) 23 * Artur Lipowski <alipowski@kki.net.pl>'s 2002 24 * "lirc_dev" and "lirc_gpio" LIRC modules 25 */ 26 27/* 28 * This program is free software; you can redistribute it and/or modify 29 * it under the terms of the GNU General Public License as published by 30 * the Free Software Foundation; either version 2 of the License, or 31 * (at your option) any later version. 32 * 33 * This program is distributed in the hope that it will be useful, 34 * but WITHOUT ANY WARRANTY; without even the implied warranty of 35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 36 * GNU General Public License for more details. 37 * 38 * You should have received a copy of the GNU General Public License 39 * along with this program; if not, write to the Free Software 40 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 41 */ 42 43#include <linux/module.h> 44#include <linux/kernel.h> 45#include <linux/kmod.h> 46#include <linux/sched.h> 47#include <linux/errno.h> 48#include <linux/fs.h> 49#include <linux/usb.h> 50#include <linux/time.h> 51 52#include <media/lirc.h> 53#include <media/lirc_dev.h> 54 55 56/* module identification */ 57#define DRIVER_VERSION "0.1" 58#define DRIVER_AUTHOR \ 59 "Jan M. Hochstein <hochstein@algo.informatik.tu-darmstadt.de>" 60#define DRIVER_DESC "USB remote driver for LIRC" 61#define DRIVER_NAME "lirc_igorplugusb" 62 63/* debugging support */ 64#ifdef CONFIG_USB_DEBUG 65static int debug = 1; 66#else 67static int debug; 68#endif 69 70#define dprintk(fmt, args...) \ 71 do { \ 72 if (debug) \ 73 printk(KERN_DEBUG fmt, ## args); \ 74 } while (0) 75 76/* One mode2 pulse/space has 4 bytes. */ 77#define CODE_LENGTH sizeof(int) 78 79/* Igor's firmware cannot record bursts longer than 36. */ 80#define DEVICE_BUFLEN 36 81 82/* 83 * Header at the beginning of the device's buffer: 84 * unsigned char data_length 85 * unsigned char data_start (!=0 means ring-buffer overrun) 86 * unsigned char counter (incremented by each burst) 87 */ 88#define DEVICE_HEADERLEN 3 89 90/* This is for the gap */ 91#define ADDITIONAL_LIRC_BYTES 2 92 93/* times to poll per second */ 94#define SAMPLE_RATE 100 95static int sample_rate = SAMPLE_RATE; 96 97 98/**** Igor's USB Request Codes */ 99 100#define SET_INFRABUFFER_EMPTY 1 101/** 102 * Params: none 103 * Answer: empty 104 */ 105 106#define GET_INFRACODE 2 107/** 108 * Params: 109 * wValue: offset to begin reading infra buffer 110 * 111 * Answer: infra data 112 */ 113 114#define SET_DATAPORT_DIRECTION 3 115/** 116 * Params: 117 * wValue: (byte) 1 bit for each data port pin (0=in, 1=out) 118 * 119 * Answer: empty 120 */ 121 122#define GET_DATAPORT_DIRECTION 4 123/** 124 * Params: none 125 * 126 * Answer: (byte) 1 bit for each data port pin (0=in, 1=out) 127 */ 128 129#define SET_OUT_DATAPORT 5 130/** 131 * Params: 132 * wValue: byte to write to output data port 133 * 134 * Answer: empty 135 */ 136 137#define GET_OUT_DATAPORT 6 138/** 139 * Params: none 140 * 141 * Answer: least significant 3 bits read from output data port 142 */ 143 144#define GET_IN_DATAPORT 7 145/** 146 * Params: none 147 * 148 * Answer: least significant 3 bits read from input data port 149 */ 150 151#define READ_EEPROM 8 152/** 153 * Params: 154 * wValue: offset to begin reading EEPROM 155 * 156 * Answer: EEPROM bytes 157 */ 158 159#define WRITE_EEPROM 9 160/** 161 * Params: 162 * wValue: offset to EEPROM byte 163 * wIndex: byte to write 164 * 165 * Answer: empty 166 */ 167 168#define SEND_RS232 10 169/** 170 * Params: 171 * wValue: byte to send 172 * 173 * Answer: empty 174 */ 175 176#define RECV_RS232 11 177/** 178 * Params: none 179 * 180 * Answer: byte received 181 */ 182 183#define SET_RS232_BAUD 12 184/** 185 * Params: 186 * wValue: byte to write to UART bit rate register (UBRR) 187 * 188 * Answer: empty 189 */ 190 191#define GET_RS232_BAUD 13 192/** 193 * Params: none 194 * 195 * Answer: byte read from UART bit rate register (UBRR) 196 */ 197 198 199/* data structure for each usb remote */ 200struct igorplug { 201 202 /* usb */ 203 struct usb_device *usbdev; 204 struct urb *urb_in; 205 int devnum; 206 207 unsigned char *buf_in; 208 unsigned int len_in; 209 int in_space; 210 struct timeval last_time; 211 212 dma_addr_t dma_in; 213 214 /* lirc */ 215 struct lirc_driver *d; 216 217 /* handle sending (init strings) */ 218 int send_flags; 219 wait_queue_head_t wait_out; 220}; 221 222static int unregister_from_lirc(struct igorplug *ir) 223{ 224 struct lirc_driver *d = ir->d; 225 int devnum; 226 227 if (!ir->d) 228 return -EINVAL; 229 230 devnum = ir->devnum; 231 dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); 232 233 lirc_unregister_driver(d->minor); 234 235 printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); 236 237 kfree(d); 238 ir->d = NULL; 239 kfree(ir); 240 return 0; 241} 242 243static int set_use_inc(void *data) 244{ 245 struct igorplug *ir = data; 246 247 if (!ir) { 248 printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); 249 return -EIO; 250 } 251 dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); 252 253 if (!ir->usbdev) 254 return -ENODEV; 255 256 return 0; 257} 258 259static void set_use_dec(void *data) 260{ 261 struct igorplug *ir = data; 262 263 if (!ir) { 264 printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); 265 return; 266 } 267 dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); 268} 269 270 271/** 272 * Called in user context. 273 * return 0 if data was added to the buffer and 274 * -ENODATA if none was available. This should add some number of bits 275 * evenly divisible by code_length to the buffer 276 */ 277static int usb_remote_poll(void *data, struct lirc_buffer *buf) 278{ 279 int ret; 280 struct igorplug *ir = (struct igorplug *)data; 281 282 if (!ir->usbdev) /* Has the device been removed? */ 283 return -ENODEV; 284 285 memset(ir->buf_in, 0, ir->len_in); 286 287 ret = usb_control_msg( 288 ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), 289 GET_INFRACODE, USB_TYPE_VENDOR|USB_DIR_IN, 290 0/* offset */, /*unused*/0, 291 ir->buf_in, ir->len_in, 292 /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); 293 if (ret > 0) { 294 int i = DEVICE_HEADERLEN; 295 int code, timediff; 296 struct timeval now; 297 298 if (ret <= 1) /* ACK packet has 1 byte --> ignore */ 299 return -ENODATA; 300 301 dprintk(DRIVER_NAME ": Got %d bytes. Header: %02x %02x %02x\n", 302 ret, ir->buf_in[0], ir->buf_in[1], ir->buf_in[2]); 303 304 if (ir->buf_in[2] != 0) { 305 printk(DRIVER_NAME "[%d]: Device buffer overrun.\n", 306 ir->devnum); 307 /* start at earliest byte */ 308 i = DEVICE_HEADERLEN + ir->buf_in[2]; 309 /* where are we now? space, gap or pulse? */ 310 } 311 312 do_gettimeofday(&now); 313 timediff = now.tv_sec - ir->last_time.tv_sec; 314 if (timediff + 1 > PULSE_MASK / 1000000) 315 timediff = PULSE_MASK; 316 else { 317 timediff *= 1000000; 318 timediff += now.tv_usec - ir->last_time.tv_usec; 319 } 320 ir->last_time.tv_sec = now.tv_sec; 321 ir->last_time.tv_usec = now.tv_usec; 322 323 /* create leading gap */ 324 code = timediff; 325 lirc_buffer_write(buf, (unsigned char *)&code); 326 ir->in_space = 1; /* next comes a pulse */ 327 328 /* MODE2: pulse/space (PULSE_BIT) in 1us units */ 329 330 while (i < ret) { 331 /* 1 Igor-tick = 85.333333 us */ 332 code = (unsigned int)ir->buf_in[i] * 85 333 + (unsigned int)ir->buf_in[i] / 3; 334 if (ir->in_space) 335 code |= PULSE_BIT; 336 lirc_buffer_write(buf, (unsigned char *)&code); 337 /* 1 chunk = CODE_LENGTH bytes */ 338 ir->in_space ^= 1; 339 ++i; 340 } 341 342 ret = usb_control_msg( 343 ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), 344 SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, 345 /*unused*/0, /*unused*/0, 346 /*dummy*/ir->buf_in, /*dummy*/ir->len_in, 347 /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); 348 if (ret < 0) 349 printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: " 350 "error %d\n", ir->devnum, ret); 351 return 0; 352 } else if (ret < 0) 353 printk(DRIVER_NAME "[%d]: GET_INFRACODE: error %d\n", 354 ir->devnum, ret); 355 356 return -ENODATA; 357} 358 359 360 361static int usb_remote_probe(struct usb_interface *intf, 362 const struct usb_device_id *id) 363{ 364 struct usb_device *dev = NULL; 365 struct usb_host_interface *idesc = NULL; 366 struct usb_host_endpoint *ep_ctl2; 367 struct igorplug *ir = NULL; 368 struct lirc_driver *driver = NULL; 369 int devnum, pipe, maxp; 370 int minor = 0; 371 char buf[63], name[128] = ""; 372 int mem_failure = 0; 373 int ret; 374 375 dprintk(DRIVER_NAME ": usb probe called.\n"); 376 377 dev = interface_to_usbdev(intf); 378 379 idesc = intf->cur_altsetting; 380 381 if (idesc->desc.bNumEndpoints != 1) 382 return -ENODEV; 383 ep_ctl2 = idesc->endpoint; 384 if (((ep_ctl2->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) 385 != USB_DIR_IN) 386 || (ep_ctl2->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 387 != USB_ENDPOINT_XFER_CONTROL) 388 return -ENODEV; 389 pipe = usb_rcvctrlpipe(dev, ep_ctl2->desc.bEndpointAddress); 390 devnum = dev->devnum; 391 maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 392 393 dprintk(DRIVER_NAME "[%d]: bytes_in_key=%lu maxp=%d\n", 394 devnum, CODE_LENGTH, maxp); 395 396 397 mem_failure = 0; 398 ir = kzalloc(sizeof(struct igorplug), GFP_KERNEL); 399 if (!ir) { 400 mem_failure = 1; 401 goto mem_failure_switch; 402 } 403 driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); 404 if (!driver) { 405 mem_failure = 2; 406 goto mem_failure_switch; 407 } 408 409 ir->buf_in = usb_alloc_coherent(dev, 410 DEVICE_BUFLEN+DEVICE_HEADERLEN, 411 GFP_ATOMIC, &ir->dma_in); 412 if (!ir->buf_in) { 413 mem_failure = 3; 414 goto mem_failure_switch; 415 } 416 417 strcpy(driver->name, DRIVER_NAME " "); 418 driver->minor = -1; 419 driver->code_length = CODE_LENGTH * 8; /* in bits */ 420 driver->features = LIRC_CAN_REC_MODE2; 421 driver->data = ir; 422 driver->chunk_size = CODE_LENGTH; 423 driver->buffer_size = DEVICE_BUFLEN + ADDITIONAL_LIRC_BYTES; 424 driver->set_use_inc = &set_use_inc; 425 driver->set_use_dec = &set_use_dec; 426 driver->sample_rate = sample_rate; /* per second */ 427 driver->add_to_buf = &usb_remote_poll; 428 driver->dev = &intf->dev; 429 driver->owner = THIS_MODULE; 430 431 init_waitqueue_head(&ir->wait_out); 432 433 minor = lirc_register_driver(driver); 434 if (minor < 0) 435 mem_failure = 9; 436 437mem_failure_switch: 438 439 switch (mem_failure) { 440 case 9: 441 usb_free_coherent(dev, DEVICE_BUFLEN+DEVICE_HEADERLEN, 442 ir->buf_in, ir->dma_in); 443 case 3: 444 kfree(driver); 445 case 2: 446 kfree(ir); 447 case 1: 448 printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", 449 devnum, mem_failure); 450 return -ENOMEM; 451 } 452 453 driver->minor = minor; 454 ir->d = driver; 455 ir->devnum = devnum; 456 ir->usbdev = dev; 457 ir->len_in = DEVICE_BUFLEN+DEVICE_HEADERLEN; 458 ir->in_space = 1; /* First mode2 event is a space. */ 459 do_gettimeofday(&ir->last_time); 460 461 if (dev->descriptor.iManufacturer 462 && usb_string(dev, dev->descriptor.iManufacturer, 463 buf, sizeof(buf)) > 0) 464 strlcpy(name, buf, sizeof(name)); 465 if (dev->descriptor.iProduct 466 && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) 467 snprintf(name + strlen(name), sizeof(name) - strlen(name), 468 " %s", buf); 469 printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name, 470 dev->bus->busnum, devnum); 471 472 /* clear device buffer */ 473 ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), 474 SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, 475 /*unused*/0, /*unused*/0, 476 /*dummy*/ir->buf_in, /*dummy*/ir->len_in, 477 /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); 478 if (ret < 0) 479 printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n", 480 devnum, ret); 481 482 usb_set_intfdata(intf, ir); 483 return 0; 484} 485 486 487static void usb_remote_disconnect(struct usb_interface *intf) 488{ 489 struct usb_device *dev = interface_to_usbdev(intf); 490 struct igorplug *ir = usb_get_intfdata(intf); 491 usb_set_intfdata(intf, NULL); 492 493 if (!ir || !ir->d) 494 return; 495 496 ir->usbdev = NULL; 497 wake_up_all(&ir->wait_out); 498 499 usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in); 500 501 unregister_from_lirc(ir); 502} 503 504static struct usb_device_id usb_remote_id_table[] = { 505 /* Igor Plug USB (Atmel's Manufact. ID) */ 506 { USB_DEVICE(0x03eb, 0x0002) }, 507 508 /* Terminating entry */ 509 { } 510}; 511 512static struct usb_driver usb_remote_driver = { 513 .name = DRIVER_NAME, 514 .probe = usb_remote_probe, 515 .disconnect = usb_remote_disconnect, 516 .id_table = usb_remote_id_table 517}; 518 519static int __init usb_remote_init(void) 520{ 521 int i; 522 523 printk(KERN_INFO "\n" 524 DRIVER_NAME ": " DRIVER_DESC " v" DRIVER_VERSION "\n"); 525 printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); 526 dprintk(DRIVER_NAME ": debug mode enabled\n"); 527 528 i = usb_register(&usb_remote_driver); 529 if (i < 0) { 530 printk(DRIVER_NAME ": usb register failed, result = %d\n", i); 531 return -ENODEV; 532 } 533 534 return 0; 535} 536 537static void __exit usb_remote_exit(void) 538{ 539 usb_deregister(&usb_remote_driver); 540} 541 542module_init(usb_remote_init); 543module_exit(usb_remote_exit); 544 545#include <linux/vermagic.h> 546MODULE_INFO(vermagic, VERMAGIC_STRING); 547 548MODULE_DESCRIPTION(DRIVER_DESC); 549MODULE_AUTHOR(DRIVER_AUTHOR); 550MODULE_LICENSE("GPL"); 551MODULE_DEVICE_TABLE(usb, usb_remote_id_table); 552 553module_param(sample_rate, int, S_IRUGO | S_IWUSR); 554MODULE_PARM_DESC(sample_rate, "Sampling rate in Hz (default: 100)"); 555