linux/drivers/media/rc/ttusbir.c
<<
>>
Prefs
   1/*
   2 * TechnoTrend USB IR Receiver
   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/module.h>
  22#include <linux/usb.h>
  23#include <linux/usb/input.h>
  24#include <linux/slab.h>
  25#include <linux/leds.h>
  26#include <media/rc-core.h>
  27
  28#define DRIVER_NAME     "ttusbir"
  29#define DRIVER_DESC     "TechnoTrend USB IR Receiver"
  30/*
  31 * The Windows driver uses 8 URBS, the original lirc drivers has a
  32 * configurable amount (2 default, 4 max). This device generates about 125
  33 * messages per second (!), whether IR is idle or not.
  34 */
  35#define NUM_URBS        4
  36#define NS_PER_BYTE     62500
  37#define NS_PER_BIT      (NS_PER_BYTE/8)
  38
  39struct ttusbir {
  40        struct rc_dev *rc;
  41        struct device *dev;
  42        struct usb_device *udev;
  43
  44        struct urb *urb[NUM_URBS];
  45
  46        struct led_classdev led;
  47        struct urb *bulk_urb;
  48        uint8_t bulk_buffer[5];
  49        int bulk_out_endp, iso_in_endp;
  50        bool led_on, is_led_on;
  51        atomic_t led_complete;
  52
  53        char phys[64];
  54};
  55
  56static enum led_brightness ttusbir_brightness_get(struct led_classdev *led_dev)
  57{
  58        struct ttusbir *tt = container_of(led_dev, struct ttusbir, led);
  59
  60        return tt->led_on ? LED_FULL : LED_OFF;
  61}
  62
  63static void ttusbir_set_led(struct ttusbir *tt)
  64{
  65        int ret;
  66
  67        smp_mb();
  68
  69        if (tt->led_on != tt->is_led_on && tt->udev &&
  70                                atomic_add_unless(&tt->led_complete, 1, 1)) {
  71                tt->bulk_buffer[4] = tt->is_led_on = tt->led_on;
  72                ret = usb_submit_urb(tt->bulk_urb, GFP_ATOMIC);
  73                if (ret) {
  74                        dev_warn(tt->dev, "failed to submit bulk urb: %d\n",
  75                                                                        ret);
  76                        atomic_dec(&tt->led_complete);
  77                }
  78        }
  79}
  80
  81static void ttusbir_brightness_set(struct led_classdev *led_dev, enum
  82                                                led_brightness brightness)
  83{
  84        struct ttusbir *tt = container_of(led_dev, struct ttusbir, led);
  85
  86        tt->led_on = brightness != LED_OFF;
  87
  88        ttusbir_set_led(tt);
  89}
  90
  91/*
  92 * The urb cannot be reused until the urb completes
  93 */
  94static void ttusbir_bulk_complete(struct urb *urb)
  95{
  96        struct ttusbir *tt = urb->context;
  97
  98        atomic_dec(&tt->led_complete);
  99
 100        switch (urb->status) {
 101        case 0:
 102                break;
 103        case -ECONNRESET:
 104        case -ENOENT:
 105        case -ESHUTDOWN:
 106                usb_unlink_urb(urb);
 107                return;
 108        case -EPIPE:
 109        default:
 110                dev_dbg(tt->dev, "Error: urb status = %d\n", urb->status);
 111                break;
 112        }
 113
 114        ttusbir_set_led(tt);
 115}
 116
 117/*
 118 * The data is one bit per sample, a set bit signifying silence and samples
 119 * being MSB first. Bit 0 can contain garbage so take it to be whatever
 120 * bit 1 is, so we don't have unexpected edges.
 121 */
 122static void ttusbir_process_ir_data(struct ttusbir *tt, uint8_t *buf)
 123{
 124        struct ir_raw_event rawir;
 125        unsigned i, v, b;
 126        bool event = false;
 127
 128        init_ir_raw_event(&rawir);
 129
 130        for (i = 0; i < 128; i++) {
 131                v = buf[i] & 0xfe;
 132                switch (v) {
 133                case 0xfe:
 134                        rawir.pulse = false;
 135                        rawir.duration = NS_PER_BYTE;
 136                        if (ir_raw_event_store_with_filter(tt->rc, &rawir))
 137                                event = true;
 138                        break;
 139                case 0:
 140                        rawir.pulse = true;
 141                        rawir.duration = NS_PER_BYTE;
 142                        if (ir_raw_event_store_with_filter(tt->rc, &rawir))
 143                                event = true;
 144                        break;
 145                default:
 146                        /* one edge per byte */
 147                        if (v & 2) {
 148                                b = ffz(v | 1);
 149                                rawir.pulse = true;
 150                        } else {
 151                                b = ffs(v) - 1;
 152                                rawir.pulse = false;
 153                        }
 154
 155                        rawir.duration = NS_PER_BIT * (8 - b);
 156                        if (ir_raw_event_store_with_filter(tt->rc, &rawir))
 157                                event = true;
 158
 159                        rawir.pulse = !rawir.pulse;
 160                        rawir.duration = NS_PER_BIT * b;
 161                        if (ir_raw_event_store_with_filter(tt->rc, &rawir))
 162                                event = true;
 163                        break;
 164                }
 165        }
 166
 167        /* don't wakeup when there's nothing to do */
 168        if (event)
 169                ir_raw_event_handle(tt->rc);
 170}
 171
 172static void ttusbir_urb_complete(struct urb *urb)
 173{
 174        struct ttusbir *tt = urb->context;
 175        int rc;
 176
 177        switch (urb->status) {
 178        case 0:
 179                ttusbir_process_ir_data(tt, urb->transfer_buffer);
 180                break;
 181        case -ECONNRESET:
 182        case -ENOENT:
 183        case -ESHUTDOWN:
 184                usb_unlink_urb(urb);
 185                return;
 186        case -EPIPE:
 187        default:
 188                dev_dbg(tt->dev, "Error: urb status = %d\n", urb->status);
 189                break;
 190        }
 191
 192        rc = usb_submit_urb(urb, GFP_ATOMIC);
 193        if (rc && rc != -ENODEV)
 194                dev_warn(tt->dev, "failed to resubmit urb: %d\n", rc);
 195}
 196
 197static int ttusbir_probe(struct usb_interface *intf,
 198                         const struct usb_device_id *id)
 199{
 200        struct ttusbir *tt;
 201        struct usb_interface_descriptor *idesc;
 202        struct usb_endpoint_descriptor *desc;
 203        struct rc_dev *rc;
 204        int i, j, ret;
 205        int altsetting = -1;
 206
 207        tt = kzalloc(sizeof(*tt), GFP_KERNEL);
 208        rc = rc_allocate_device();
 209        if (!tt || !rc) {
 210                ret = -ENOMEM;
 211                goto out;
 212        }
 213
 214        /* find the correct alt setting */
 215        for (i = 0; i < intf->num_altsetting && altsetting == -1; i++) {
 216                int max_packet, bulk_out_endp = -1, iso_in_endp = -1;
 217
 218                idesc = &intf->altsetting[i].desc;
 219
 220                for (j = 0; j < idesc->bNumEndpoints; j++) {
 221                        desc = &intf->altsetting[i].endpoint[j].desc;
 222                        max_packet = le16_to_cpu(desc->wMaxPacketSize);
 223                        if (usb_endpoint_dir_in(desc) &&
 224                                        usb_endpoint_xfer_isoc(desc) &&
 225                                        max_packet == 0x10)
 226                                iso_in_endp = j;
 227                        else if (usb_endpoint_dir_out(desc) &&
 228                                        usb_endpoint_xfer_bulk(desc) &&
 229                                        max_packet == 0x20)
 230                                bulk_out_endp = j;
 231
 232                        if (bulk_out_endp != -1 && iso_in_endp != -1) {
 233                                tt->bulk_out_endp = bulk_out_endp;
 234                                tt->iso_in_endp = iso_in_endp;
 235                                altsetting = i;
 236                                break;
 237                        }
 238                }
 239        }
 240
 241        if (altsetting == -1) {
 242                dev_err(&intf->dev, "cannot find expected altsetting\n");
 243                ret = -ENODEV;
 244                goto out;
 245        }
 246
 247        tt->dev = &intf->dev;
 248        tt->udev = interface_to_usbdev(intf);
 249        tt->rc = rc;
 250
 251        ret = usb_set_interface(tt->udev, 0, altsetting);
 252        if (ret)
 253                goto out;
 254
 255        for (i = 0; i < NUM_URBS; i++) {
 256                struct urb *urb = usb_alloc_urb(8, GFP_KERNEL);
 257                void *buffer;
 258
 259                if (!urb) {
 260                        ret = -ENOMEM;
 261                        goto out;
 262                }
 263
 264                urb->dev = tt->udev;
 265                urb->context = tt;
 266                urb->pipe = usb_rcvisocpipe(tt->udev, tt->iso_in_endp);
 267                urb->interval = 1;
 268                buffer = usb_alloc_coherent(tt->udev, 128, GFP_KERNEL,
 269                                                &urb->transfer_dma);
 270                if (!buffer) {
 271                        usb_free_urb(urb);
 272                        ret = -ENOMEM;
 273                        goto out;
 274                }
 275                urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP | URB_ISO_ASAP;
 276                urb->transfer_buffer = buffer;
 277                urb->complete = ttusbir_urb_complete;
 278                urb->number_of_packets = 8;
 279                urb->transfer_buffer_length = 128;
 280
 281                for (j = 0; j < 8; j++) {
 282                        urb->iso_frame_desc[j].offset = j * 16;
 283                        urb->iso_frame_desc[j].length = 16;
 284                }
 285
 286                tt->urb[i] = urb;
 287        }
 288
 289        tt->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
 290        if (!tt->bulk_urb) {
 291                ret = -ENOMEM;
 292                goto out;
 293        }
 294
 295        tt->bulk_buffer[0] = 0xaa;
 296        tt->bulk_buffer[1] = 0x01;
 297        tt->bulk_buffer[2] = 0x05;
 298        tt->bulk_buffer[3] = 0x01;
 299
 300        usb_fill_bulk_urb(tt->bulk_urb, tt->udev, usb_sndbulkpipe(tt->udev,
 301                tt->bulk_out_endp), tt->bulk_buffer, sizeof(tt->bulk_buffer),
 302                                                ttusbir_bulk_complete, tt);
 303
 304        tt->led.name = "ttusbir:green:power";
 305        tt->led.default_trigger = "rc-feedback";
 306        tt->led.brightness_set = ttusbir_brightness_set;
 307        tt->led.brightness_get = ttusbir_brightness_get;
 308        tt->is_led_on = tt->led_on = true;
 309        atomic_set(&tt->led_complete, 0);
 310        ret = led_classdev_register(&intf->dev, &tt->led);
 311        if (ret)
 312                goto out;
 313
 314        usb_make_path(tt->udev, tt->phys, sizeof(tt->phys));
 315
 316        rc->input_name = DRIVER_DESC;
 317        rc->input_phys = tt->phys;
 318        usb_to_input_id(tt->udev, &rc->input_id);
 319        rc->dev.parent = &intf->dev;
 320        rc->driver_type = RC_DRIVER_IR_RAW;
 321        rc_set_allowed_protocols(rc, RC_BIT_ALL);
 322        rc->priv = tt;
 323        rc->driver_name = DRIVER_NAME;
 324        rc->map_name = RC_MAP_TT_1500;
 325        rc->timeout = MS_TO_NS(100);
 326        /*
 327         * The precision is NS_PER_BIT, but since every 8th bit can be
 328         * overwritten with garbage the accuracy is at best 2 * NS_PER_BIT.
 329         */
 330        rc->rx_resolution = NS_PER_BIT;
 331
 332        ret = rc_register_device(rc);
 333        if (ret) {
 334                dev_err(&intf->dev, "failed to register rc device %d\n", ret);
 335                goto out2;
 336        }
 337
 338        usb_set_intfdata(intf, tt);
 339
 340        for (i = 0; i < NUM_URBS; i++) {
 341                ret = usb_submit_urb(tt->urb[i], GFP_KERNEL);
 342                if (ret) {
 343                        dev_err(tt->dev, "failed to submit urb %d\n", ret);
 344                        goto out3;
 345                }
 346        }
 347
 348        return 0;
 349out3:
 350        rc_unregister_device(rc);
 351        rc = NULL;
 352out2:
 353        led_classdev_unregister(&tt->led);
 354out:
 355        if (tt) {
 356                for (i = 0; i < NUM_URBS && tt->urb[i]; i++) {
 357                        struct urb *urb = tt->urb[i];
 358
 359                        usb_kill_urb(urb);
 360                        usb_free_coherent(tt->udev, 128, urb->transfer_buffer,
 361                                                        urb->transfer_dma);
 362                        usb_free_urb(urb);
 363                }
 364                usb_kill_urb(tt->bulk_urb);
 365                usb_free_urb(tt->bulk_urb);
 366                kfree(tt);
 367        }
 368        rc_free_device(rc);
 369
 370        return ret;
 371}
 372
 373static void ttusbir_disconnect(struct usb_interface *intf)
 374{
 375        struct ttusbir *tt = usb_get_intfdata(intf);
 376        struct usb_device *udev = tt->udev;
 377        int i;
 378
 379        tt->udev = NULL;
 380
 381        rc_unregister_device(tt->rc);
 382        led_classdev_unregister(&tt->led);
 383        for (i = 0; i < NUM_URBS; i++) {
 384                usb_kill_urb(tt->urb[i]);
 385                usb_free_coherent(udev, 128, tt->urb[i]->transfer_buffer,
 386                                                tt->urb[i]->transfer_dma);
 387                usb_free_urb(tt->urb[i]);
 388        }
 389        usb_kill_urb(tt->bulk_urb);
 390        usb_free_urb(tt->bulk_urb);
 391        usb_set_intfdata(intf, NULL);
 392        kfree(tt);
 393}
 394
 395static int ttusbir_suspend(struct usb_interface *intf, pm_message_t message)
 396{
 397        struct ttusbir *tt = usb_get_intfdata(intf);
 398        int i;
 399
 400        for (i = 0; i < NUM_URBS; i++)
 401                usb_kill_urb(tt->urb[i]);
 402
 403        led_classdev_suspend(&tt->led);
 404        usb_kill_urb(tt->bulk_urb);
 405
 406        return 0;
 407}
 408
 409static int ttusbir_resume(struct usb_interface *intf)
 410{
 411        struct ttusbir *tt = usb_get_intfdata(intf);
 412        int i, rc;
 413
 414        tt->is_led_on = true;
 415        led_classdev_resume(&tt->led);
 416
 417        for (i = 0; i < NUM_URBS; i++) {
 418                rc = usb_submit_urb(tt->urb[i], GFP_KERNEL);
 419                if (rc) {
 420                        dev_warn(tt->dev, "failed to submit urb: %d\n", rc);
 421                        break;
 422                }
 423        }
 424
 425        return rc;
 426}
 427
 428static const struct usb_device_id ttusbir_table[] = {
 429        { USB_DEVICE(0x0b48, 0x2003) },
 430        { }
 431};
 432
 433static struct usb_driver ttusbir_driver = {
 434        .name = DRIVER_NAME,
 435        .id_table = ttusbir_table,
 436        .probe = ttusbir_probe,
 437        .suspend = ttusbir_suspend,
 438        .resume = ttusbir_resume,
 439        .reset_resume = ttusbir_resume,
 440        .disconnect = ttusbir_disconnect,
 441};
 442
 443module_usb_driver(ttusbir_driver);
 444
 445MODULE_DESCRIPTION(DRIVER_DESC);
 446MODULE_AUTHOR("Sean Young <sean@mess.org>");
 447MODULE_LICENSE("GPL");
 448MODULE_DEVICE_TABLE(usb, ttusbir_table);
 449
 450