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.2" 58#define DRIVER_AUTHOR \ 59 "Jan M. Hochstein <hochstein@algo.informatik.tu-darmstadt.de>" 60#define DRIVER_DESC "Igorplug USB remote driver for LIRC" 61#define DRIVER_NAME "lirc_igorplugusb" 62 63/* One mode2 pulse/space has 4 bytes. */ 64#define CODE_LENGTH sizeof(int) 65 66/* Igor's firmware cannot record bursts longer than 36. */ 67#define DEVICE_BUFLEN 36 68 69/* 70 * Header at the beginning of the device's buffer: 71 * unsigned char data_length 72 * unsigned char data_start (!=0 means ring-buffer overrun) 73 * unsigned char counter (incremented by each burst) 74 */ 75#define DEVICE_HEADERLEN 3 76 77/* This is for the gap */ 78#define ADDITIONAL_LIRC_BYTES 2 79 80/* times to poll per second */ 81#define SAMPLE_RATE 100 82static int sample_rate = SAMPLE_RATE; 83 84 85/**** Igor's USB Request Codes */ 86 87#define SET_INFRABUFFER_EMPTY 1 88/** 89 * Params: none 90 * Answer: empty 91 */ 92 93#define GET_INFRACODE 2 94/** 95 * Params: 96 * wValue: offset to begin reading infra buffer 97 * 98 * Answer: infra data 99 */ 100 101#define SET_DATAPORT_DIRECTION 3 102/** 103 * Params: 104 * wValue: (byte) 1 bit for each data port pin (0=in, 1=out) 105 * 106 * Answer: empty 107 */ 108 109#define GET_DATAPORT_DIRECTION 4 110/** 111 * Params: none 112 * 113 * Answer: (byte) 1 bit for each data port pin (0=in, 1=out) 114 */ 115 116#define SET_OUT_DATAPORT 5 117/** 118 * Params: 119 * wValue: byte to write to output data port 120 * 121 * Answer: empty 122 */ 123 124#define GET_OUT_DATAPORT 6 125/** 126 * Params: none 127 * 128 * Answer: least significant 3 bits read from output data port 129 */ 130 131#define GET_IN_DATAPORT 7 132/** 133 * Params: none 134 * 135 * Answer: least significant 3 bits read from input data port 136 */ 137 138#define READ_EEPROM 8 139/** 140 * Params: 141 * wValue: offset to begin reading EEPROM 142 * 143 * Answer: EEPROM bytes 144 */ 145 146#define WRITE_EEPROM 9 147/** 148 * Params: 149 * wValue: offset to EEPROM byte 150 * wIndex: byte to write 151 * 152 * Answer: empty 153 */ 154 155#define SEND_RS232 10 156/** 157 * Params: 158 * wValue: byte to send 159 * 160 * Answer: empty 161 */ 162 163#define RECV_RS232 11 164/** 165 * Params: none 166 * 167 * Answer: byte received 168 */ 169 170#define SET_RS232_BAUD 12 171/** 172 * Params: 173 * wValue: byte to write to UART bit rate register (UBRR) 174 * 175 * Answer: empty 176 */ 177 178#define GET_RS232_BAUD 13 179/** 180 * Params: none 181 * 182 * Answer: byte read from UART bit rate register (UBRR) 183 */ 184 185 186/* data structure for each usb remote */ 187struct igorplug { 188 189 /* usb */ 190 struct usb_device *usbdev; 191 int devnum; 192 193 unsigned char *buf_in; 194 unsigned int len_in; 195 int in_space; 196 struct timeval last_time; 197 198 dma_addr_t dma_in; 199 200 /* lirc */ 201 struct lirc_driver *d; 202 203 /* handle sending (init strings) */ 204 int send_flags; 205}; 206 207static int unregister_from_lirc(struct igorplug *ir) 208{ 209 struct lirc_driver *d; 210 int devnum; 211 212 devnum = ir->devnum; 213 d = ir->d; 214 215 if (!d) { 216 dev_err(&ir->usbdev->dev, 217 "%s: called with NULL lirc driver struct!\n", __func__); 218 return -EINVAL; 219 } 220 221 dev_dbg(&ir->usbdev->dev, "calling lirc_unregister_driver\n"); 222 lirc_unregister_driver(d->minor); 223 224 return devnum; 225} 226 227static int set_use_inc(void *data) 228{ 229 struct igorplug *ir = data; 230 231 if (!ir) { 232 printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); 233 return -EIO; 234 } 235 236 dev_dbg(&ir->usbdev->dev, "set use inc\n"); 237 238 if (!ir->usbdev) 239 return -ENODEV; 240 241 return 0; 242} 243 244static void set_use_dec(void *data) 245{ 246 struct igorplug *ir = data; 247 248 if (!ir) { 249 printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); 250 return; 251 } 252 253 dev_dbg(&ir->usbdev->dev, "set use dec\n"); 254} 255 256static void send_fragment(struct igorplug *ir, struct lirc_buffer *buf, 257 int i, int max) 258{ 259 int code; 260 261 /* MODE2: pulse/space (PULSE_BIT) in 1us units */ 262 while (i < max) { 263 /* 1 Igor-tick = 85.333333 us */ 264 code = (unsigned int)ir->buf_in[i] * 85 + 265 (unsigned int)ir->buf_in[i] / 3; 266 ir->last_time.tv_usec += code; 267 if (ir->in_space) 268 code |= PULSE_BIT; 269 lirc_buffer_write(buf, (unsigned char *)&code); 270 /* 1 chunk = CODE_LENGTH bytes */ 271 ir->in_space ^= 1; 272 ++i; 273 } 274} 275 276/** 277 * Called in user context. 278 * return 0 if data was added to the buffer and 279 * -ENODATA if none was available. This should add some number of bits 280 * evenly divisible by code_length to the buffer 281 */ 282static int igorplugusb_remote_poll(void *data, struct lirc_buffer *buf) 283{ 284 int ret; 285 struct igorplug *ir = (struct igorplug *)data; 286 287 if (!ir || !ir->usbdev) /* Has the device been removed? */ 288 return -ENODEV; 289 290 memset(ir->buf_in, 0, ir->len_in); 291 292 ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), 293 GET_INFRACODE, USB_TYPE_VENDOR | USB_DIR_IN, 294 0/* offset */, /*unused*/0, 295 ir->buf_in, ir->len_in, 296 /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); 297 if (ret > 0) { 298 int code, timediff; 299 struct timeval now; 300 301 /* ACK packet has 1 byte --> ignore */ 302 if (ret < DEVICE_HEADERLEN) 303 return -ENODATA; 304 305 dev_dbg(&ir->usbdev->dev, "Got %d bytes. Header: %*ph\n", 306 ret, 3, ir->buf_in); 307 308 do_gettimeofday(&now); 309 timediff = now.tv_sec - ir->last_time.tv_sec; 310 if (timediff + 1 > PULSE_MASK / 1000000) 311 timediff = PULSE_MASK; 312 else { 313 timediff *= 1000000; 314 timediff += now.tv_usec - ir->last_time.tv_usec; 315 } 316 ir->last_time.tv_sec = now.tv_sec; 317 ir->last_time.tv_usec = now.tv_usec; 318 319 /* create leading gap */ 320 code = timediff; 321 lirc_buffer_write(buf, (unsigned char *)&code); 322 ir->in_space = 1; /* next comes a pulse */ 323 324 if (ir->buf_in[2] == 0) 325 send_fragment(ir, buf, DEVICE_HEADERLEN, ret); 326 else { 327 dev_warn(&ir->usbdev->dev, 328 "[%d]: Device buffer overrun.\n", ir->devnum); 329 /* HHHNNNNNNNNNNNOOOOOOOO H = header 330 <---[2]---> N = newer 331 <---------ret--------> O = older */ 332 ir->buf_in[2] %= ret - DEVICE_HEADERLEN; /* sanitize */ 333 /* keep even-ness to not desync pulse/pause */ 334 send_fragment(ir, buf, DEVICE_HEADERLEN + 335 ir->buf_in[2] - (ir->buf_in[2] & 1), ret); 336 send_fragment(ir, buf, DEVICE_HEADERLEN, 337 DEVICE_HEADERLEN + ir->buf_in[2]); 338 } 339 340 ret = usb_control_msg( 341 ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), 342 SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, 343 /*unused*/0, /*unused*/0, 344 /*dummy*/ir->buf_in, /*dummy*/ir->len_in, 345 /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); 346 if (ret < 0) 347 printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n", 348 ir->devnum, ret); 349 return 0; 350 } else if (ret < 0) 351 printk(DRIVER_NAME "[%d]: GET_INFRACODE: error %d\n", 352 ir->devnum, ret); 353 354 return -ENODATA; 355} 356 357static int igorplugusb_remote_probe(struct usb_interface *intf, 358 const struct usb_device_id *id) 359{ 360 struct usb_device *dev; 361 struct usb_host_interface *idesc = NULL; 362 struct usb_endpoint_descriptor *ep; 363 struct igorplug *ir = NULL; 364 struct lirc_driver *driver = NULL; 365 int devnum, pipe, maxp; 366 char buf[63], name[128] = ""; 367 int ret; 368 369 dev_dbg(&intf->dev, "%s: usb probe called.\n", __func__); 370 371 dev = interface_to_usbdev(intf); 372 373 idesc = intf->cur_altsetting; 374 375 if (idesc->desc.bNumEndpoints != 1) 376 return -ENODEV; 377 378 ep = &idesc->endpoint->desc; 379 if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) 380 != USB_DIR_IN) 381 || (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 382 != USB_ENDPOINT_XFER_CONTROL) 383 return -ENODEV; 384 385 pipe = usb_rcvctrlpipe(dev, ep->bEndpointAddress); 386 devnum = dev->devnum; 387 maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 388 389 dev_dbg(&intf->dev, "%s: bytes_in_key=%zu maxp=%d\n", 390 __func__, CODE_LENGTH, maxp); 391 392 ir = devm_kzalloc(&intf->dev, sizeof(*ir), GFP_KERNEL); 393 if (!ir) 394 return -ENOMEM; 395 396 driver = devm_kzalloc(&intf->dev, sizeof(*driver), GFP_KERNEL); 397 if (!driver) 398 return -ENOMEM; 399 400 ir->buf_in = usb_alloc_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN, 401 GFP_ATOMIC, &ir->dma_in); 402 if (!ir->buf_in) 403 return -ENOMEM; 404 405 strcpy(driver->name, DRIVER_NAME " "); 406 driver->minor = -1; 407 driver->code_length = CODE_LENGTH * 8; /* in bits */ 408 driver->features = LIRC_CAN_REC_MODE2; 409 driver->data = ir; 410 driver->chunk_size = CODE_LENGTH; 411 driver->buffer_size = DEVICE_BUFLEN + ADDITIONAL_LIRC_BYTES; 412 driver->set_use_inc = &set_use_inc; 413 driver->set_use_dec = &set_use_dec; 414 driver->sample_rate = sample_rate; /* per second */ 415 driver->add_to_buf = &igorplugusb_remote_poll; 416 driver->dev = &intf->dev; 417 driver->owner = THIS_MODULE; 418 419 ret = lirc_register_driver(driver); 420 if (ret < 0) { 421 usb_free_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN, 422 ir->buf_in, ir->dma_in); 423 return ret; 424 } 425 426 driver->minor = ret; 427 ir->d = driver; 428 ir->devnum = devnum; 429 ir->usbdev = dev; 430 ir->len_in = DEVICE_BUFLEN + DEVICE_HEADERLEN; 431 ir->in_space = 1; /* First mode2 event is a space. */ 432 do_gettimeofday(&ir->last_time); 433 434 if (dev->descriptor.iManufacturer 435 && usb_string(dev, dev->descriptor.iManufacturer, 436 buf, sizeof(buf)) > 0) 437 strlcpy(name, buf, sizeof(name)); 438 if (dev->descriptor.iProduct 439 && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) 440 snprintf(name + strlen(name), sizeof(name) - strlen(name), 441 " %s", buf); 442 printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name, 443 dev->bus->busnum, devnum); 444 445 /* clear device buffer */ 446 ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), 447 SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, 448 /*unused*/0, /*unused*/0, 449 /*dummy*/ir->buf_in, /*dummy*/ir->len_in, 450 /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); 451 if (ret < 0) 452 printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n", 453 devnum, ret); 454 455 usb_set_intfdata(intf, ir); 456 return 0; 457} 458 459static void igorplugusb_remote_disconnect(struct usb_interface *intf) 460{ 461 struct usb_device *usbdev = interface_to_usbdev(intf); 462 struct igorplug *ir = usb_get_intfdata(intf); 463 struct device *dev = &intf->dev; 464 int devnum; 465 466 usb_set_intfdata(intf, NULL); 467 468 if (!ir || !ir->d) 469 return; 470 471 ir->usbdev = NULL; 472 473 usb_free_coherent(usbdev, ir->len_in, ir->buf_in, ir->dma_in); 474 475 devnum = unregister_from_lirc(ir); 476 477 dev_info(dev, DRIVER_NAME "[%d]: %s done\n", devnum, __func__); 478} 479 480static struct usb_device_id igorplugusb_remote_id_table[] = { 481 /* Igor Plug USB (Atmel's Manufact. ID) */ 482 { USB_DEVICE(0x03eb, 0x0002) }, 483 /* Fit PC2 Infrared Adapter */ 484 { USB_DEVICE(0x03eb, 0x21fe) }, 485 486 /* Terminating entry */ 487 { } 488}; 489 490static struct usb_driver igorplugusb_remote_driver = { 491 .name = DRIVER_NAME, 492 .probe = igorplugusb_remote_probe, 493 .disconnect = igorplugusb_remote_disconnect, 494 .id_table = igorplugusb_remote_id_table 495}; 496 497module_usb_driver(igorplugusb_remote_driver); 498 499#include <linux/vermagic.h> 500MODULE_INFO(vermagic, VERMAGIC_STRING); 501 502MODULE_DESCRIPTION(DRIVER_DESC); 503MODULE_AUTHOR(DRIVER_AUTHOR); 504MODULE_LICENSE("GPL"); 505MODULE_DEVICE_TABLE(usb, igorplugusb_remote_id_table); 506 507module_param(sample_rate, int, S_IRUGO | S_IWUSR); 508MODULE_PARM_DESC(sample_rate, "Sampling rate in Hz (default: 100)"); 509