linux/drivers/media/rc/iguanair.c
<<
>>
Prefs
   1/*
   2 * IguanaWorks USB IR Transceiver support
   3 *
   4 * Copyright (C) 2012 Sean Young <sean@mess.org>
   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#include <linux/device.h>
  22#include <linux/kernel.h>
  23#include <linux/module.h>
  24#include <linux/usb.h>
  25#include <linux/usb/input.h>
  26#include <linux/slab.h>
  27#include <linux/completion.h>
  28#include <media/rc-core.h>
  29
  30#define DRIVER_NAME "iguanair"
  31#define BUF_SIZE 152
  32
  33struct iguanair {
  34        struct rc_dev *rc;
  35
  36        struct device *dev;
  37        struct usb_device *udev;
  38
  39        uint16_t version;
  40        uint8_t bufsize;
  41        uint8_t cycle_overhead;
  42
  43        struct mutex lock;
  44
  45        /* receiver support */
  46        bool receiver_on;
  47        dma_addr_t dma_in, dma_out;
  48        uint8_t *buf_in;
  49        struct urb *urb_in, *urb_out;
  50        struct completion completion;
  51
  52        /* transmit support */
  53        bool tx_overflow;
  54        uint32_t carrier;
  55        struct send_packet *packet;
  56
  57        char name[64];
  58        char phys[64];
  59};
  60
  61#define CMD_NOP                 0x00
  62#define CMD_GET_VERSION         0x01
  63#define CMD_GET_BUFSIZE         0x11
  64#define CMD_GET_FEATURES        0x10
  65#define CMD_SEND                0x15
  66#define CMD_EXECUTE             0x1f
  67#define CMD_RX_OVERFLOW         0x31
  68#define CMD_TX_OVERFLOW         0x32
  69#define CMD_RECEIVER_ON         0x12
  70#define CMD_RECEIVER_OFF        0x14
  71
  72#define DIR_IN                  0xdc
  73#define DIR_OUT                 0xcd
  74
  75#define MAX_IN_PACKET           8u
  76#define MAX_OUT_PACKET          (sizeof(struct send_packet) + BUF_SIZE)
  77#define TIMEOUT                 1000
  78#define RX_RESOLUTION           21333
  79
  80struct packet {
  81        uint16_t start;
  82        uint8_t direction;
  83        uint8_t cmd;
  84};
  85
  86struct send_packet {
  87        struct packet header;
  88        uint8_t length;
  89        uint8_t channels;
  90        uint8_t busy7;
  91        uint8_t busy4;
  92        uint8_t payload[0];
  93};
  94
  95static void process_ir_data(struct iguanair *ir, unsigned len)
  96{
  97        if (len >= 4 && ir->buf_in[0] == 0 && ir->buf_in[1] == 0) {
  98                switch (ir->buf_in[3]) {
  99                case CMD_GET_VERSION:
 100                        if (len == 6) {
 101                                ir->version = (ir->buf_in[5] << 8) |
 102                                                        ir->buf_in[4];
 103                                complete(&ir->completion);
 104                        }
 105                        break;
 106                case CMD_GET_BUFSIZE:
 107                        if (len >= 5) {
 108                                ir->bufsize = ir->buf_in[4];
 109                                complete(&ir->completion);
 110                        }
 111                        break;
 112                case CMD_GET_FEATURES:
 113                        if (len > 5) {
 114                                ir->cycle_overhead = ir->buf_in[5];
 115                                complete(&ir->completion);
 116                        }
 117                        break;
 118                case CMD_TX_OVERFLOW:
 119                        ir->tx_overflow = true;
 120                case CMD_RECEIVER_OFF:
 121                case CMD_RECEIVER_ON:
 122                case CMD_SEND:
 123                        complete(&ir->completion);
 124                        break;
 125                case CMD_RX_OVERFLOW:
 126                        dev_warn(ir->dev, "receive overflow\n");
 127                        ir_raw_event_reset(ir->rc);
 128                        break;
 129                default:
 130                        dev_warn(ir->dev, "control code %02x received\n",
 131                                                        ir->buf_in[3]);
 132                        break;
 133                }
 134        } else if (len >= 7) {
 135                DEFINE_IR_RAW_EVENT(rawir);
 136                unsigned i;
 137                bool event = false;
 138
 139                init_ir_raw_event(&rawir);
 140
 141                for (i = 0; i < 7; i++) {
 142                        if (ir->buf_in[i] == 0x80) {
 143                                rawir.pulse = false;
 144                                rawir.duration = US_TO_NS(21845);
 145                        } else {
 146                                rawir.pulse = (ir->buf_in[i] & 0x80) == 0;
 147                                rawir.duration = ((ir->buf_in[i] & 0x7f) + 1) *
 148                                                                 RX_RESOLUTION;
 149                        }
 150
 151                        if (ir_raw_event_store_with_filter(ir->rc, &rawir))
 152                                event = true;
 153                }
 154
 155                if (event)
 156                        ir_raw_event_handle(ir->rc);
 157        }
 158}
 159
 160static void iguanair_rx(struct urb *urb)
 161{
 162        struct iguanair *ir;
 163        int rc;
 164
 165        if (!urb)
 166                return;
 167
 168        ir = urb->context;
 169        if (!ir) {
 170                usb_unlink_urb(urb);
 171                return;
 172        }
 173
 174        switch (urb->status) {
 175        case 0:
 176                process_ir_data(ir, urb->actual_length);
 177                break;
 178        case -ECONNRESET:
 179        case -ENOENT:
 180        case -ESHUTDOWN:
 181                usb_unlink_urb(urb);
 182                return;
 183        case -EPIPE:
 184        default:
 185                dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status);
 186                break;
 187        }
 188
 189        rc = usb_submit_urb(urb, GFP_ATOMIC);
 190        if (rc && rc != -ENODEV)
 191                dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc);
 192}
 193
 194static void iguanair_irq_out(struct urb *urb)
 195{
 196        struct iguanair *ir = urb->context;
 197
 198        if (urb->status)
 199                dev_dbg(ir->dev, "Error: out urb status = %d\n", urb->status);
 200
 201        /* if we sent an nop packet, do not expect a response */
 202        if (urb->status == 0 && ir->packet->header.cmd == CMD_NOP)
 203                complete(&ir->completion);
 204}
 205
 206static int iguanair_send(struct iguanair *ir, unsigned size)
 207{
 208        int rc;
 209
 210        reinit_completion(&ir->completion);
 211
 212        ir->urb_out->transfer_buffer_length = size;
 213        rc = usb_submit_urb(ir->urb_out, GFP_KERNEL);
 214        if (rc)
 215                return rc;
 216
 217        if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0)
 218                return -ETIMEDOUT;
 219
 220        return rc;
 221}
 222
 223static int iguanair_get_features(struct iguanair *ir)
 224{
 225        int rc;
 226
 227        /*
 228         * On cold boot, the iguanair initializes on the first packet
 229         * received but does not process that packet. Send an empty
 230         * packet.
 231         */
 232        ir->packet->header.start = 0;
 233        ir->packet->header.direction = DIR_OUT;
 234        ir->packet->header.cmd = CMD_NOP;
 235        iguanair_send(ir, sizeof(ir->packet->header));
 236
 237        ir->packet->header.cmd = CMD_GET_VERSION;
 238        rc = iguanair_send(ir, sizeof(ir->packet->header));
 239        if (rc) {
 240                dev_info(ir->dev, "failed to get version\n");
 241                goto out;
 242        }
 243
 244        if (ir->version < 0x205) {
 245                dev_err(ir->dev, "firmware 0x%04x is too old\n", ir->version);
 246                rc = -ENODEV;
 247                goto out;
 248        }
 249
 250        ir->bufsize = 150;
 251        ir->cycle_overhead = 65;
 252
 253        ir->packet->header.cmd = CMD_GET_BUFSIZE;
 254
 255        rc = iguanair_send(ir, sizeof(ir->packet->header));
 256        if (rc) {
 257                dev_info(ir->dev, "failed to get buffer size\n");
 258                goto out;
 259        }
 260
 261        if (ir->bufsize > BUF_SIZE) {
 262                dev_info(ir->dev, "buffer size %u larger than expected\n",
 263                                                                ir->bufsize);
 264                ir->bufsize = BUF_SIZE;
 265        }
 266
 267        ir->packet->header.cmd = CMD_GET_FEATURES;
 268
 269        rc = iguanair_send(ir, sizeof(ir->packet->header));
 270        if (rc)
 271                dev_info(ir->dev, "failed to get features\n");
 272out:
 273        return rc;
 274}
 275
 276static int iguanair_receiver(struct iguanair *ir, bool enable)
 277{
 278        ir->packet->header.start = 0;
 279        ir->packet->header.direction = DIR_OUT;
 280        ir->packet->header.cmd = enable ? CMD_RECEIVER_ON : CMD_RECEIVER_OFF;
 281
 282        if (enable)
 283                ir_raw_event_reset(ir->rc);
 284
 285        return iguanair_send(ir, sizeof(ir->packet->header));
 286}
 287
 288/*
 289 * The iguanair creates the carrier by busy spinning after each half period.
 290 * This is counted in CPU cycles, with the CPU running at 24MHz. It is
 291 * broken down into 7-cycles and 4-cyles delays, with a preference for
 292 * 4-cycle delays, minus the overhead of the loop itself (cycle_overhead).
 293 */
 294static int iguanair_set_tx_carrier(struct rc_dev *dev, uint32_t carrier)
 295{
 296        struct iguanair *ir = dev->priv;
 297
 298        if (carrier < 25000 || carrier > 150000)
 299                return -EINVAL;
 300
 301        mutex_lock(&ir->lock);
 302
 303        if (carrier != ir->carrier) {
 304                uint32_t cycles, fours, sevens;
 305
 306                ir->carrier = carrier;
 307
 308                cycles = DIV_ROUND_CLOSEST(24000000, carrier * 2) -
 309                                                        ir->cycle_overhead;
 310
 311                /*
 312                 * Calculate minimum number of 7 cycles needed so
 313                 * we are left with a multiple of 4; so we want to have
 314                 * (sevens * 7) & 3 == cycles & 3
 315                 */
 316                sevens = (4 - cycles) & 3;
 317                fours = (cycles - sevens * 7) / 4;
 318
 319                /*
 320                 * The firmware interprets these values as a relative offset
 321                 * for a branch. Immediately following the branches, there
 322                 * 4 instructions of 7 cycles (2 bytes each) and 110
 323                 * instructions of 4 cycles (1 byte each). A relative branch
 324                 * of 0 will execute all of them, branch further for less
 325                 * cycle burning.
 326                 */
 327                ir->packet->busy7 = (4 - sevens) * 2;
 328                ir->packet->busy4 = 110 - fours;
 329        }
 330
 331        mutex_unlock(&ir->lock);
 332
 333        return carrier;
 334}
 335
 336static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask)
 337{
 338        struct iguanair *ir = dev->priv;
 339
 340        if (mask > 15)
 341                return 4;
 342
 343        mutex_lock(&ir->lock);
 344        ir->packet->channels = mask << 4;
 345        mutex_unlock(&ir->lock);
 346
 347        return 0;
 348}
 349
 350static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
 351{
 352        struct iguanair *ir = dev->priv;
 353        uint8_t space;
 354        unsigned i, size, periods, bytes;
 355        int rc;
 356
 357        mutex_lock(&ir->lock);
 358
 359        /* convert from us to carrier periods */
 360        for (i = space = size = 0; i < count; i++) {
 361                periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
 362                bytes = DIV_ROUND_UP(periods, 127);
 363                if (size + bytes > ir->bufsize) {
 364                        rc = -EINVAL;
 365                        goto out;
 366                }
 367                while (periods) {
 368                        unsigned p = min(periods, 127u);
 369                        ir->packet->payload[size++] = p | space;
 370                        periods -= p;
 371                }
 372                space ^= 0x80;
 373        }
 374
 375        ir->packet->header.start = 0;
 376        ir->packet->header.direction = DIR_OUT;
 377        ir->packet->header.cmd = CMD_SEND;
 378        ir->packet->length = size;
 379
 380        ir->tx_overflow = false;
 381
 382        rc = iguanair_send(ir, sizeof(*ir->packet) + size);
 383
 384        if (rc == 0 && ir->tx_overflow)
 385                rc = -EOVERFLOW;
 386
 387out:
 388        mutex_unlock(&ir->lock);
 389
 390        return rc ? rc : count;
 391}
 392
 393static int iguanair_open(struct rc_dev *rdev)
 394{
 395        struct iguanair *ir = rdev->priv;
 396        int rc;
 397
 398        mutex_lock(&ir->lock);
 399
 400        rc = iguanair_receiver(ir, true);
 401        if (rc == 0)
 402                ir->receiver_on = true;
 403
 404        mutex_unlock(&ir->lock);
 405
 406        return rc;
 407}
 408
 409static void iguanair_close(struct rc_dev *rdev)
 410{
 411        struct iguanair *ir = rdev->priv;
 412        int rc;
 413
 414        mutex_lock(&ir->lock);
 415
 416        rc = iguanair_receiver(ir, false);
 417        ir->receiver_on = false;
 418        if (rc && rc != -ENODEV)
 419                dev_warn(ir->dev, "failed to disable receiver: %d\n", rc);
 420
 421        mutex_unlock(&ir->lock);
 422}
 423
 424static int iguanair_probe(struct usb_interface *intf,
 425                          const struct usb_device_id *id)
 426{
 427        struct usb_device *udev = interface_to_usbdev(intf);
 428        struct iguanair *ir;
 429        struct rc_dev *rc;
 430        int ret, pipein, pipeout;
 431        struct usb_host_interface *idesc;
 432
 433        ir = kzalloc(sizeof(*ir), GFP_KERNEL);
 434        rc = rc_allocate_device();
 435        if (!ir || !rc) {
 436                ret = -ENOMEM;
 437                goto out;
 438        }
 439
 440        ir->buf_in = usb_alloc_coherent(udev, MAX_IN_PACKET, GFP_KERNEL,
 441                                                                &ir->dma_in);
 442        ir->packet = usb_alloc_coherent(udev, MAX_OUT_PACKET, GFP_KERNEL,
 443                                                                &ir->dma_out);
 444        ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
 445        ir->urb_out = usb_alloc_urb(0, GFP_KERNEL);
 446
 447        if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out) {
 448                ret = -ENOMEM;
 449                goto out;
 450        }
 451
 452        idesc = intf->altsetting;
 453
 454        if (idesc->desc.bNumEndpoints < 2) {
 455                ret = -ENODEV;
 456                goto out;
 457        }
 458
 459        ir->rc = rc;
 460        ir->dev = &intf->dev;
 461        ir->udev = udev;
 462        mutex_init(&ir->lock);
 463
 464        init_completion(&ir->completion);
 465        pipeout = usb_sndintpipe(udev,
 466                                idesc->endpoint[1].desc.bEndpointAddress);
 467        usb_fill_int_urb(ir->urb_out, udev, pipeout, ir->packet, MAX_OUT_PACKET,
 468                                                iguanair_irq_out, ir, 1);
 469        ir->urb_out->transfer_dma = ir->dma_out;
 470        ir->urb_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 471
 472        pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress);
 473        usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_IN_PACKET,
 474                                                         iguanair_rx, ir, 1);
 475        ir->urb_in->transfer_dma = ir->dma_in;
 476        ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 477
 478        ret = usb_submit_urb(ir->urb_in, GFP_KERNEL);
 479        if (ret) {
 480                dev_warn(&intf->dev, "failed to submit urb: %d\n", ret);
 481                goto out;
 482        }
 483
 484        ret = iguanair_get_features(ir);
 485        if (ret)
 486                goto out2;
 487
 488        snprintf(ir->name, sizeof(ir->name),
 489                "IguanaWorks USB IR Transceiver version 0x%04x", ir->version);
 490
 491        usb_make_path(ir->udev, ir->phys, sizeof(ir->phys));
 492
 493        rc->input_name = ir->name;
 494        rc->input_phys = ir->phys;
 495        usb_to_input_id(ir->udev, &rc->input_id);
 496        rc->dev.parent = &intf->dev;
 497        rc->driver_type = RC_DRIVER_IR_RAW;
 498        rc->allowed_protocols = RC_BIT_ALL;
 499        rc->priv = ir;
 500        rc->open = iguanair_open;
 501        rc->close = iguanair_close;
 502        rc->s_tx_mask = iguanair_set_tx_mask;
 503        rc->s_tx_carrier = iguanair_set_tx_carrier;
 504        rc->tx_ir = iguanair_tx;
 505        rc->driver_name = DRIVER_NAME;
 506        rc->map_name = RC_MAP_RC6_MCE;
 507        rc->timeout = MS_TO_NS(100);
 508        rc->rx_resolution = RX_RESOLUTION;
 509
 510        iguanair_set_tx_carrier(rc, 38000);
 511        iguanair_set_tx_mask(rc, 0);
 512
 513        ret = rc_register_device(rc);
 514        if (ret < 0) {
 515                dev_err(&intf->dev, "failed to register rc device %d", ret);
 516                goto out2;
 517        }
 518
 519        usb_set_intfdata(intf, ir);
 520
 521        return 0;
 522out2:
 523        usb_kill_urb(ir->urb_in);
 524        usb_kill_urb(ir->urb_out);
 525out:
 526        if (ir) {
 527                usb_free_urb(ir->urb_in);
 528                usb_free_urb(ir->urb_out);
 529                usb_free_coherent(udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
 530                usb_free_coherent(udev, MAX_OUT_PACKET, ir->packet,
 531                                                                ir->dma_out);
 532        }
 533        rc_free_device(rc);
 534        kfree(ir);
 535        return ret;
 536}
 537
 538static void iguanair_disconnect(struct usb_interface *intf)
 539{
 540        struct iguanair *ir = usb_get_intfdata(intf);
 541
 542        rc_unregister_device(ir->rc);
 543        usb_set_intfdata(intf, NULL);
 544        usb_kill_urb(ir->urb_in);
 545        usb_kill_urb(ir->urb_out);
 546        usb_free_urb(ir->urb_in);
 547        usb_free_urb(ir->urb_out);
 548        usb_free_coherent(ir->udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
 549        usb_free_coherent(ir->udev, MAX_OUT_PACKET, ir->packet, ir->dma_out);
 550        kfree(ir);
 551}
 552
 553static int iguanair_suspend(struct usb_interface *intf, pm_message_t message)
 554{
 555        struct iguanair *ir = usb_get_intfdata(intf);
 556        int rc = 0;
 557
 558        mutex_lock(&ir->lock);
 559
 560        if (ir->receiver_on) {
 561                rc = iguanair_receiver(ir, false);
 562                if (rc)
 563                        dev_warn(ir->dev, "failed to disable receiver for suspend\n");
 564        }
 565
 566        usb_kill_urb(ir->urb_in);
 567        usb_kill_urb(ir->urb_out);
 568
 569        mutex_unlock(&ir->lock);
 570
 571        return rc;
 572}
 573
 574static int iguanair_resume(struct usb_interface *intf)
 575{
 576        struct iguanair *ir = usb_get_intfdata(intf);
 577        int rc = 0;
 578
 579        mutex_lock(&ir->lock);
 580
 581        rc = usb_submit_urb(ir->urb_in, GFP_KERNEL);
 582        if (rc)
 583                dev_warn(&intf->dev, "failed to submit urb: %d\n", rc);
 584
 585        if (ir->receiver_on) {
 586                rc = iguanair_receiver(ir, true);
 587                if (rc)
 588                        dev_warn(ir->dev, "failed to enable receiver after resume\n");
 589        }
 590
 591        mutex_unlock(&ir->lock);
 592
 593        return rc;
 594}
 595
 596static const struct usb_device_id iguanair_table[] = {
 597        { USB_DEVICE(0x1781, 0x0938) },
 598        { }
 599};
 600
 601static struct usb_driver iguanair_driver = {
 602        .name = DRIVER_NAME,
 603        .probe = iguanair_probe,
 604        .disconnect = iguanair_disconnect,
 605        .suspend = iguanair_suspend,
 606        .resume = iguanair_resume,
 607        .reset_resume = iguanair_resume,
 608        .id_table = iguanair_table,
 609        .soft_unbind = 1        /* we want to disable receiver on unbind */
 610};
 611
 612module_usb_driver(iguanair_driver);
 613
 614MODULE_DESCRIPTION("IguanaWorks USB IR Transceiver");
 615MODULE_AUTHOR("Sean Young <sean@mess.org>");
 616MODULE_LICENSE("GPL");
 617MODULE_DEVICE_TABLE(usb, iguanair_table);
 618
 619