^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Streamzap Remote Control driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2010 Jarod Wilson <jarod@wilsonet.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This driver was based on the work of Greg Wickham and Adrian
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Dewhurst. It was substantially rewritten to support correct signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * gaps and now maintains a delay buffer, which is used to present
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * consistent timing behaviour to user space applications. Without the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * delay buffer an ugly hack would be required in lircd, which can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * cause sluggish signal decoding in certain situations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Ported to in-kernel ir-core interface by Jarod Wilson
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * This driver is based on the USB skeleton driver packaged with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/ktime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/usb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/usb/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <media/rc-core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define DRIVER_VERSION "1.61"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define DRIVER_NAME "streamzap"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define DRIVER_DESC "Streamzap Remote Control driver"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define USB_STREAMZAP_VENDOR_ID 0x0e9c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define USB_STREAMZAP_PRODUCT_ID 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* table of devices that work with this driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static const struct usb_device_id streamzap_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* Streamzap Remote Control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* Terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) MODULE_DEVICE_TABLE(usb, streamzap_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define SZ_PULSE_MASK 0xf0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SZ_SPACE_MASK 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define SZ_TIMEOUT 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define SZ_RESOLUTION 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* number of samples buffered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define SZ_BUF_LEN 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) enum StreamzapDecoderState {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) PulseSpace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) FullPulse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) FullSpace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) IgnorePulse
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* structure to hold our device specific stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct streamzap_ir {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* ir-core */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct rc_dev *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* core device info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* usb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct usb_device *usbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct usb_interface *interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct usb_endpoint_descriptor *endpoint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct urb *urb_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* buffer & dma */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned char *buf_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) dma_addr_t dma_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned int buf_in_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* track what state we're in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) enum StreamzapDecoderState decoder_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* tracks whether we are currently receiving some signal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) bool idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* sum of signal lengths received since signal start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned long sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* start time of signal; necessary for gap tracking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) ktime_t signal_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ktime_t signal_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) bool timeout_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) char name[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) char phys[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /* local function prototypes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static int streamzap_probe(struct usb_interface *interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) const struct usb_device_id *id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static void streamzap_disconnect(struct usb_interface *interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static void streamzap_callback(struct urb *urb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int streamzap_suspend(struct usb_interface *intf, pm_message_t message);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int streamzap_resume(struct usb_interface *intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* usb specific object needed to register this driver with the usb subsystem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static struct usb_driver streamzap_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .name = DRIVER_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .probe = streamzap_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .disconnect = streamzap_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .suspend = streamzap_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) .resume = streamzap_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .id_table = streamzap_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) dev_dbg(sz->dev, "Storing %s with duration %u us\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) (rawir.pulse ? "pulse" : "space"), rawir.duration);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ir_raw_event_store_with_filter(sz->rdev, &rawir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static void sz_push_full_pulse(struct streamzap_ir *sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) unsigned char value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct ir_raw_event rawir = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (sz->idle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) sz->signal_last = sz->signal_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) sz->signal_start = ktime_get_real();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) delta = ktime_us_delta(sz->signal_start, sz->signal_last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) rawir.pulse = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (delta > (15 * USEC_PER_SEC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /* really long time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) rawir.duration = IR_MAX_DURATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) rawir.duration = delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) rawir.duration -= sz->sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) rawir.duration = (rawir.duration > IR_MAX_DURATION) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) IR_MAX_DURATION : rawir.duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) sz_push(sz, rawir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) sz->idle = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) sz->sum = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) rawir.pulse = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) rawir.duration = ((int) value) * SZ_RESOLUTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) rawir.duration += SZ_RESOLUTION / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) sz->sum += rawir.duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) rawir.duration = (rawir.duration > IR_MAX_DURATION) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) IR_MAX_DURATION : rawir.duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) sz_push(sz, rawir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static void sz_push_half_pulse(struct streamzap_ir *sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) unsigned char value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) sz_push_full_pulse(sz, (value & SZ_PULSE_MASK) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void sz_push_full_space(struct streamzap_ir *sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) unsigned char value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct ir_raw_event rawir = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) rawir.pulse = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) rawir.duration = ((int) value) * SZ_RESOLUTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) rawir.duration += SZ_RESOLUTION / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) sz->sum += rawir.duration;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) sz_push(sz, rawir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static void sz_push_half_space(struct streamzap_ir *sz,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) unsigned long value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) sz_push_full_space(sz, value & SZ_SPACE_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * streamzap_callback - usb IRQ handler callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * This procedure is invoked on reception of data from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * the usb remote.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static void streamzap_callback(struct urb *urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct streamzap_ir *sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (!urb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) sz = urb->context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) len = urb->actual_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) switch (urb->status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) case -ECONNRESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) case -ENOENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) case -ESHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * this urb is terminated, clean up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * sz might already be invalid at this point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) for (i = 0; i < len; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) i, (unsigned char)sz->buf_in[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) switch (sz->decoder_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case PulseSpace:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if ((sz->buf_in[i] & SZ_PULSE_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) SZ_PULSE_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) sz->decoder_state = FullPulse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) } else if ((sz->buf_in[i] & SZ_SPACE_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) == SZ_SPACE_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) sz_push_half_pulse(sz, sz->buf_in[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) sz->decoder_state = FullSpace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) sz_push_half_pulse(sz, sz->buf_in[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) sz_push_half_space(sz, sz->buf_in[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) case FullPulse:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) sz_push_full_pulse(sz, sz->buf_in[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) sz->decoder_state = IgnorePulse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) case FullSpace:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (sz->buf_in[i] == SZ_TIMEOUT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct ir_raw_event rawir = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .pulse = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .duration = sz->rdev->timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) sz->idle = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (sz->timeout_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) sz_push(sz, rawir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) ir_raw_event_handle(sz->rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ir_raw_event_reset(sz->rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) sz_push_full_space(sz, sz->buf_in[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) sz->decoder_state = PulseSpace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case IgnorePulse:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if ((sz->buf_in[i] & SZ_SPACE_MASK) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) SZ_SPACE_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) sz->decoder_state = FullSpace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) sz_push_half_space(sz, sz->buf_in[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) sz->decoder_state = PulseSpace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ir_raw_event_handle(sz->rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) usb_submit_urb(urb, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct rc_dev *rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct device *dev = sz->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (!rdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) dev_err(dev, "remote dev allocation failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared Receiver (%04x:%04x)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) le16_to_cpu(sz->usbdev->descriptor.idVendor),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) le16_to_cpu(sz->usbdev->descriptor.idProduct));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) strlcat(sz->phys, "/input0", sizeof(sz->phys));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) rdev->device_name = sz->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) rdev->input_phys = sz->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) usb_to_input_id(sz->usbdev, &rdev->input_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) rdev->dev.parent = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) rdev->priv = sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) rdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) rdev->driver_name = DRIVER_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) rdev->map_name = RC_MAP_STREAMZAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ret = rc_register_device(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) dev_err(dev, "remote input device register failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return rdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) rc_free_device(rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * streamzap_probe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * Called by usb-core to associated with a candidate device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) * On any failure the return value is the ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * On success return 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static int streamzap_probe(struct usb_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct usb_device *usbdev = interface_to_usbdev(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct usb_host_interface *iface_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct streamzap_ir *sz = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) char buf[63], name[128] = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) int retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) int pipe, maxp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* Allocate space for device driver specific data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) sz = kzalloc(sizeof(struct streamzap_ir), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (!sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) sz->usbdev = usbdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) sz->interface = intf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* Check to ensure endpoint information matches requirements */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) iface_host = intf->cur_altsetting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (iface_host->desc.bNumEndpoints != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) dev_err(&intf->dev, "%s: Unexpected desc.bNumEndpoints (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) __func__, iface_host->desc.bNumEndpoints);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) retval = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) goto free_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) sz->endpoint = &(iface_host->endpoint[0].desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (!usb_endpoint_dir_in(sz->endpoint)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) dev_err(&intf->dev, "%s: endpoint doesn't match input device 02%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) __func__, sz->endpoint->bEndpointAddress);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) retval = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) goto free_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (!usb_endpoint_xfer_int(sz->endpoint)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) dev_err(&intf->dev, "%s: endpoint attributes don't match xfer 02%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) __func__, sz->endpoint->bmAttributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) retval = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) goto free_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (maxp == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) retval = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) goto free_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* Allocate the USB buffer and IRQ URB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) sz->buf_in = usb_alloc_coherent(usbdev, maxp, GFP_ATOMIC, &sz->dma_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (!sz->buf_in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) goto free_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) sz->urb_in = usb_alloc_urb(0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (!sz->urb_in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) goto free_buf_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) sz->dev = &intf->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) sz->buf_in_len = maxp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (usbdev->descriptor.iManufacturer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) && usb_string(usbdev, usbdev->descriptor.iManufacturer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) buf, sizeof(buf)) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) strscpy(name, buf, sizeof(name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (usbdev->descriptor.iProduct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) && usb_string(usbdev, usbdev->descriptor.iProduct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) buf, sizeof(buf)) > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) snprintf(name + strlen(name), sizeof(name) - strlen(name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) " %s", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) sz->rdev = streamzap_init_rc_dev(sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (!sz->rdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) goto rc_dev_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) sz->idle = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) sz->decoder_state = PulseSpace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* FIXME: don't yet have a way to set this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) sz->timeout_enabled = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) sz->rdev->timeout = SZ_TIMEOUT * SZ_RESOLUTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* not yet supported, depends on patches from maxim */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) sz->min_timeout = SZ_TIMEOUT * SZ_RESOLUTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) sz->max_timeout = SZ_TIMEOUT * SZ_RESOLUTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) sz->signal_start = ktime_get_real();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /* Complete final initialisations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) maxp, (usb_complete_t)streamzap_callback,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) sz, sz->endpoint->bInterval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) sz->urb_in->transfer_dma = sz->dma_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) usb_set_intfdata(intf, sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) dev_err(sz->dev, "urb submit failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) usbdev->bus->busnum, usbdev->devnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) rc_dev_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) usb_free_urb(sz->urb_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) free_buf_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) free_sz:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) kfree(sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * streamzap_disconnect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * Called by the usb core when the device is removed from the system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * This routine guarantees that the driver will not submit any more urbs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * by clearing dev->usbdev. It is also supposed to terminate any currently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * active urbs. Unfortunately, usb_bulk_msg(), used in streamzap_read(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * does not provide any way to do this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static void streamzap_disconnect(struct usb_interface *interface)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct streamzap_ir *sz = usb_get_intfdata(interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct usb_device *usbdev = interface_to_usbdev(interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) usb_set_intfdata(interface, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (!sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) sz->usbdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) rc_unregister_device(sz->rdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) usb_kill_urb(sz->urb_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) usb_free_urb(sz->urb_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) kfree(sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) static int streamzap_suspend(struct usb_interface *intf, pm_message_t message)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) struct streamzap_ir *sz = usb_get_intfdata(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) usb_kill_urb(sz->urb_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static int streamzap_resume(struct usb_interface *intf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct streamzap_ir *sz = usb_get_intfdata(intf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) dev_err(sz->dev, "Error submitting urb\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) module_usb_driver(streamzap_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) MODULE_AUTHOR("Jarod Wilson <jarod@wilsonet.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) MODULE_DESCRIPTION(DRIVER_DESC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) MODULE_LICENSE("GPL");