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