Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");