Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Streamzap Remote Control driver
0004  *
0005  * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de>
0006  * Copyright (c) 2010 Jarod Wilson <jarod@wilsonet.com>
0007  *
0008  * This driver was based on the work of Greg Wickham and Adrian
0009  * Dewhurst. It was substantially rewritten to support correct signal
0010  * gaps and now maintains a delay buffer, which is used to present
0011  * consistent timing behaviour to user space applications. Without the
0012  * delay buffer an ugly hack would be required in lircd, which can
0013  * cause sluggish signal decoding in certain situations.
0014  *
0015  * Ported to in-kernel ir-core interface by Jarod Wilson
0016  *
0017  * This driver is based on the USB skeleton driver packaged with the
0018  * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
0019  */
0020 
0021 #include <linux/device.h>
0022 #include <linux/module.h>
0023 #include <linux/slab.h>
0024 #include <linux/usb.h>
0025 #include <linux/usb/input.h>
0026 #include <media/rc-core.h>
0027 
0028 #define DRIVER_NAME "streamzap"
0029 #define DRIVER_DESC "Streamzap Remote Control driver"
0030 
0031 #define USB_STREAMZAP_VENDOR_ID     0x0e9c
0032 #define USB_STREAMZAP_PRODUCT_ID    0x0000
0033 
0034 /* table of devices that work with this driver */
0035 static const struct usb_device_id streamzap_table[] = {
0036     /* Streamzap Remote Control */
0037     { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) },
0038     /* Terminating entry */
0039     { }
0040 };
0041 
0042 MODULE_DEVICE_TABLE(usb, streamzap_table);
0043 
0044 #define SZ_PULSE_MASK 0xf0
0045 #define SZ_SPACE_MASK 0x0f
0046 #define SZ_TIMEOUT    0xff
0047 #define SZ_RESOLUTION 256
0048 
0049 /* number of samples buffered */
0050 #define SZ_BUF_LEN 128
0051 
0052 enum StreamzapDecoderState {
0053     PulseSpace,
0054     FullPulse,
0055     FullSpace,
0056     IgnorePulse
0057 };
0058 
0059 /* structure to hold our device specific stuff */
0060 struct streamzap_ir {
0061     /* ir-core */
0062     struct rc_dev *rdev;
0063 
0064     /* core device info */
0065     struct device *dev;
0066 
0067     /* usb */
0068     struct urb      *urb_in;
0069 
0070     /* buffer & dma */
0071     unsigned char       *buf_in;
0072     dma_addr_t      dma_in;
0073     unsigned int        buf_in_len;
0074 
0075     /* track what state we're in */
0076     enum StreamzapDecoderState decoder_state;
0077 
0078     char            phys[64];
0079 };
0080 
0081 
0082 /* local function prototypes */
0083 static int streamzap_probe(struct usb_interface *interface,
0084                const struct usb_device_id *id);
0085 static void streamzap_disconnect(struct usb_interface *interface);
0086 static void streamzap_callback(struct urb *urb);
0087 static int streamzap_suspend(struct usb_interface *intf, pm_message_t message);
0088 static int streamzap_resume(struct usb_interface *intf);
0089 
0090 /* usb specific object needed to register this driver with the usb subsystem */
0091 static struct usb_driver streamzap_driver = {
0092     .name =     DRIVER_NAME,
0093     .probe =    streamzap_probe,
0094     .disconnect =   streamzap_disconnect,
0095     .suspend =  streamzap_suspend,
0096     .resume =   streamzap_resume,
0097     .id_table = streamzap_table,
0098 };
0099 
0100 static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
0101 {
0102     dev_dbg(sz->dev, "Storing %s with duration %u us\n",
0103         (rawir.pulse ? "pulse" : "space"), rawir.duration);
0104     ir_raw_event_store_with_filter(sz->rdev, &rawir);
0105 }
0106 
0107 static void sz_push_full_pulse(struct streamzap_ir *sz,
0108                    unsigned char value)
0109 {
0110     struct ir_raw_event rawir = {
0111         .pulse = true,
0112         .duration = value * SZ_RESOLUTION + SZ_RESOLUTION / 2,
0113     };
0114 
0115     sz_push(sz, rawir);
0116 }
0117 
0118 static void sz_push_half_pulse(struct streamzap_ir *sz,
0119                    unsigned char value)
0120 {
0121     sz_push_full_pulse(sz, (value & SZ_PULSE_MASK) >> 4);
0122 }
0123 
0124 static void sz_push_full_space(struct streamzap_ir *sz,
0125                    unsigned char value)
0126 {
0127     struct ir_raw_event rawir = {
0128         .pulse = false,
0129         .duration = value * SZ_RESOLUTION + SZ_RESOLUTION / 2,
0130     };
0131 
0132     sz_push(sz, rawir);
0133 }
0134 
0135 static void sz_push_half_space(struct streamzap_ir *sz,
0136                    unsigned long value)
0137 {
0138     sz_push_full_space(sz, value & SZ_SPACE_MASK);
0139 }
0140 
0141 /*
0142  * streamzap_callback - usb IRQ handler callback
0143  *
0144  * This procedure is invoked on reception of data from
0145  * the usb remote.
0146  */
0147 static void streamzap_callback(struct urb *urb)
0148 {
0149     struct streamzap_ir *sz;
0150     unsigned int i;
0151     int len;
0152 
0153     if (!urb)
0154         return;
0155 
0156     sz = urb->context;
0157     len = urb->actual_length;
0158 
0159     switch (urb->status) {
0160     case -ECONNRESET:
0161     case -ENOENT:
0162     case -ESHUTDOWN:
0163         /*
0164          * this urb is terminated, clean up.
0165          * sz might already be invalid at this point
0166          */
0167         dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
0168         return;
0169     default:
0170         break;
0171     }
0172 
0173     dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
0174     for (i = 0; i < len; i++) {
0175         dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",
0176             i, (unsigned char)sz->buf_in[i]);
0177         switch (sz->decoder_state) {
0178         case PulseSpace:
0179             if ((sz->buf_in[i] & SZ_PULSE_MASK) ==
0180                 SZ_PULSE_MASK) {
0181                 sz->decoder_state = FullPulse;
0182                 continue;
0183             } else if ((sz->buf_in[i] & SZ_SPACE_MASK)
0184                     == SZ_SPACE_MASK) {
0185                 sz_push_half_pulse(sz, sz->buf_in[i]);
0186                 sz->decoder_state = FullSpace;
0187                 continue;
0188             } else {
0189                 sz_push_half_pulse(sz, sz->buf_in[i]);
0190                 sz_push_half_space(sz, sz->buf_in[i]);
0191             }
0192             break;
0193         case FullPulse:
0194             sz_push_full_pulse(sz, sz->buf_in[i]);
0195             sz->decoder_state = IgnorePulse;
0196             break;
0197         case FullSpace:
0198             if (sz->buf_in[i] == SZ_TIMEOUT) {
0199                 struct ir_raw_event rawir = {
0200                     .pulse = false,
0201                     .duration = sz->rdev->timeout
0202                 };
0203                 sz_push(sz, rawir);
0204             } else {
0205                 sz_push_full_space(sz, sz->buf_in[i]);
0206             }
0207             sz->decoder_state = PulseSpace;
0208             break;
0209         case IgnorePulse:
0210             if ((sz->buf_in[i] & SZ_SPACE_MASK) ==
0211                 SZ_SPACE_MASK) {
0212                 sz->decoder_state = FullSpace;
0213                 continue;
0214             }
0215             sz_push_half_space(sz, sz->buf_in[i]);
0216             sz->decoder_state = PulseSpace;
0217             break;
0218         }
0219     }
0220 
0221     ir_raw_event_handle(sz->rdev);
0222     usb_submit_urb(urb, GFP_ATOMIC);
0223 }
0224 
0225 static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz,
0226                         struct usb_device *usbdev)
0227 {
0228     struct rc_dev *rdev;
0229     struct device *dev = sz->dev;
0230     int ret;
0231 
0232     rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
0233     if (!rdev)
0234         goto out;
0235 
0236     usb_make_path(usbdev, sz->phys, sizeof(sz->phys));
0237     strlcat(sz->phys, "/input0", sizeof(sz->phys));
0238 
0239     rdev->device_name = "Streamzap PC Remote Infrared Receiver";
0240     rdev->input_phys = sz->phys;
0241     usb_to_input_id(usbdev, &rdev->input_id);
0242     rdev->dev.parent = dev;
0243     rdev->priv = sz;
0244     rdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
0245     rdev->driver_name = DRIVER_NAME;
0246     rdev->map_name = RC_MAP_STREAMZAP;
0247     rdev->rx_resolution = SZ_RESOLUTION;
0248 
0249     ret = rc_register_device(rdev);
0250     if (ret < 0) {
0251         dev_err(dev, "remote input device register failed\n");
0252         goto out;
0253     }
0254 
0255     return rdev;
0256 
0257 out:
0258     rc_free_device(rdev);
0259     return NULL;
0260 }
0261 
0262 /*
0263  *  streamzap_probe
0264  *
0265  *  Called by usb-core to associated with a candidate device
0266  *  On any failure the return value is the ERROR
0267  *  On success return 0
0268  */
0269 static int streamzap_probe(struct usb_interface *intf,
0270                const struct usb_device_id *id)
0271 {
0272     struct usb_device *usbdev = interface_to_usbdev(intf);
0273     struct usb_endpoint_descriptor *endpoint;
0274     struct usb_host_interface *iface_host;
0275     struct streamzap_ir *sz = NULL;
0276     int retval = -ENOMEM;
0277     int pipe, maxp;
0278 
0279     /* Allocate space for device driver specific data */
0280     sz = kzalloc(sizeof(struct streamzap_ir), GFP_KERNEL);
0281     if (!sz)
0282         return -ENOMEM;
0283 
0284     /* Check to ensure endpoint information matches requirements */
0285     iface_host = intf->cur_altsetting;
0286 
0287     if (iface_host->desc.bNumEndpoints != 1) {
0288         dev_err(&intf->dev, "%s: Unexpected desc.bNumEndpoints (%d)\n",
0289             __func__, iface_host->desc.bNumEndpoints);
0290         retval = -ENODEV;
0291         goto free_sz;
0292     }
0293 
0294     endpoint = &iface_host->endpoint[0].desc;
0295     if (!usb_endpoint_dir_in(endpoint)) {
0296         dev_err(&intf->dev, "%s: endpoint doesn't match input device 02%02x\n",
0297             __func__, endpoint->bEndpointAddress);
0298         retval = -ENODEV;
0299         goto free_sz;
0300     }
0301 
0302     if (!usb_endpoint_xfer_int(endpoint)) {
0303         dev_err(&intf->dev, "%s: endpoint attributes don't match xfer 02%02x\n",
0304             __func__, endpoint->bmAttributes);
0305         retval = -ENODEV;
0306         goto free_sz;
0307     }
0308 
0309     pipe = usb_rcvintpipe(usbdev, endpoint->bEndpointAddress);
0310     maxp = usb_maxpacket(usbdev, pipe);
0311 
0312     if (maxp == 0) {
0313         dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n",
0314             __func__);
0315         retval = -ENODEV;
0316         goto free_sz;
0317     }
0318 
0319     /* Allocate the USB buffer and IRQ URB */
0320     sz->buf_in = usb_alloc_coherent(usbdev, maxp, GFP_ATOMIC, &sz->dma_in);
0321     if (!sz->buf_in)
0322         goto free_sz;
0323 
0324     sz->urb_in = usb_alloc_urb(0, GFP_KERNEL);
0325     if (!sz->urb_in)
0326         goto free_buf_in;
0327 
0328     sz->dev = &intf->dev;
0329     sz->buf_in_len = maxp;
0330 
0331     sz->rdev = streamzap_init_rc_dev(sz, usbdev);
0332     if (!sz->rdev)
0333         goto rc_dev_fail;
0334 
0335     sz->decoder_state = PulseSpace;
0336     /* FIXME: don't yet have a way to set this */
0337     sz->rdev->timeout = SZ_TIMEOUT * SZ_RESOLUTION;
0338     #if 0
0339     /* not yet supported, depends on patches from maxim */
0340     /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
0341     sz->min_timeout = SZ_TIMEOUT * SZ_RESOLUTION;
0342     sz->max_timeout = SZ_TIMEOUT * SZ_RESOLUTION;
0343     #endif
0344 
0345     /* Complete final initialisations */
0346     usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in,
0347              maxp, streamzap_callback, sz, endpoint->bInterval);
0348     sz->urb_in->transfer_dma = sz->dma_in;
0349     sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
0350 
0351     usb_set_intfdata(intf, sz);
0352 
0353     if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
0354         dev_err(sz->dev, "urb submit failed\n");
0355 
0356     return 0;
0357 
0358 rc_dev_fail:
0359     usb_free_urb(sz->urb_in);
0360 free_buf_in:
0361     usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in);
0362 free_sz:
0363     kfree(sz);
0364 
0365     return retval;
0366 }
0367 
0368 /*
0369  * streamzap_disconnect
0370  *
0371  * Called by the usb core when the device is removed from the system.
0372  *
0373  * This routine guarantees that the driver will not submit any more urbs
0374  * by clearing dev->usbdev.  It is also supposed to terminate any currently
0375  * active urbs.  Unfortunately, usb_bulk_msg(), used in streamzap_read(),
0376  * does not provide any way to do this.
0377  */
0378 static void streamzap_disconnect(struct usb_interface *interface)
0379 {
0380     struct streamzap_ir *sz = usb_get_intfdata(interface);
0381     struct usb_device *usbdev = interface_to_usbdev(interface);
0382 
0383     usb_set_intfdata(interface, NULL);
0384 
0385     if (!sz)
0386         return;
0387 
0388     rc_unregister_device(sz->rdev);
0389     usb_kill_urb(sz->urb_in);
0390     usb_free_urb(sz->urb_in);
0391     usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
0392 
0393     kfree(sz);
0394 }
0395 
0396 static int streamzap_suspend(struct usb_interface *intf, pm_message_t message)
0397 {
0398     struct streamzap_ir *sz = usb_get_intfdata(intf);
0399 
0400     usb_kill_urb(sz->urb_in);
0401 
0402     return 0;
0403 }
0404 
0405 static int streamzap_resume(struct usb_interface *intf)
0406 {
0407     struct streamzap_ir *sz = usb_get_intfdata(intf);
0408 
0409     if (usb_submit_urb(sz->urb_in, GFP_NOIO)) {
0410         dev_err(sz->dev, "Error submitting urb\n");
0411         return -EIO;
0412     }
0413 
0414     return 0;
0415 }
0416 
0417 module_usb_driver(streamzap_driver);
0418 
0419 MODULE_AUTHOR("Jarod Wilson <jarod@wilsonet.com>");
0420 MODULE_DESCRIPTION(DRIVER_DESC);
0421 MODULE_LICENSE("GPL");