diff options
author | Jarod Wilson <jarod@redhat.com> | 2010-08-03 00:07:04 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-08-08 22:42:58 -0400 |
commit | 8e9e60640067858e8036d4d43bbf725c60613359 (patch) | |
tree | 612a944b44ec346eb3bda77417d4eb036891676e /drivers | |
parent | 7c294402d58e22bb760c0e1a825eea5d582a8f2d (diff) |
V4L/DVB: staging/lirc: port lirc_streamzap to ir-core
This ports lirc_streamzap.c over to ir-core in-place, to be followed by
a patch moving the driver over to drivers/media/IR/streamzap.c and
enabling the proper Kconfig bits.
Presently, the in-kernel keymap doesn't work, as the stock Streamzap
remote uses an RC-5-like, but not-quite-RC-5 protocol, which the
in-kernel RC-5 decoder doesn't cope with. The remote can be used right
now with the lirc bridge driver though, and other remotes (at least an
RC-6(A) MCE remote) work perfectly with the driver.
I'll take a look at making the existing RC-5 decoder cope with this odd
duck, possibly implement another standalone decoder engine, or just
throw up my hands and say "meh, use lirc"... But the driver itself
should be perfectly sound.
Remaining items on the streamzap TODO list:
- add LIRC_SET_REC_TIMEOUT-alike support
- add LIRC_GET_M{AX,IN}_TIMEOUT-alike support
- add LIRC_GET_REC_RESOLUTION-alike support
All of the above should be trivial to add. There are patches pending to
add this support to ir-core from Maxim Levitsky, and I'll take care of
these once his patches get integrated. None of them are currently
essential though.
Signed-off-by: Jarod Wilson <jarod@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/IR/keymaps/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/IR/keymaps/rc-rc5-streamzap.c | 81 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_streamzap.c | 812 |
3 files changed, 448 insertions, 446 deletions
diff --git a/drivers/media/IR/keymaps/Makefile b/drivers/media/IR/keymaps/Makefile index cbee06243b51..c9fcc41944e9 100644 --- a/drivers/media/IR/keymaps/Makefile +++ b/drivers/media/IR/keymaps/Makefile | |||
@@ -59,6 +59,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ | |||
59 | rc-purpletv.o \ | 59 | rc-purpletv.o \ |
60 | rc-pv951.o \ | 60 | rc-pv951.o \ |
61 | rc-rc5-hauppauge-new.o \ | 61 | rc-rc5-hauppauge-new.o \ |
62 | rc-rc5-streamzap.o \ | ||
62 | rc-rc5-tv.o \ | 63 | rc-rc5-tv.o \ |
63 | rc-rc6-mce.o \ | 64 | rc-rc6-mce.o \ |
64 | rc-real-audio-220-32-keys.o \ | 65 | rc-real-audio-220-32-keys.o \ |
diff --git a/drivers/media/IR/keymaps/rc-rc5-streamzap.c b/drivers/media/IR/keymaps/rc-rc5-streamzap.c new file mode 100644 index 000000000000..4c19c58b46d8 --- /dev/null +++ b/drivers/media/IR/keymaps/rc-rc5-streamzap.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* rc-rc5-streamzap.c - Keytable for Streamzap PC Remote, for use | ||
2 | * with the Streamzap PC Remote IR Receiver. | ||
3 | * | ||
4 | * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <media/rc-map.h> | ||
13 | |||
14 | static struct ir_scancode rc5_streamzap[] = { | ||
15 | /* | ||
16 | * FIXME: The Streamzap remote isn't actually true RC-5, it has an extra | ||
17 | * bit in it, which presently throws the in-kernel RC-5 decoder for a loop. | ||
18 | * We either have to enhance the decoder to support it, add a new decoder, | ||
19 | * or just rely on lirc userspace decoding. | ||
20 | */ | ||
21 | { 0x00, KEY_NUMERIC_0 }, | ||
22 | { 0x01, KEY_NUMERIC_1 }, | ||
23 | { 0x02, KEY_NUMERIC_2 }, | ||
24 | { 0x03, KEY_NUMERIC_3 }, | ||
25 | { 0x04, KEY_NUMERIC_4 }, | ||
26 | { 0x05, KEY_NUMERIC_5 }, | ||
27 | { 0x06, KEY_NUMERIC_6 }, | ||
28 | { 0x07, KEY_NUMERIC_7 }, | ||
29 | { 0x08, KEY_NUMERIC_8 }, | ||
30 | { 0x0a, KEY_POWER }, | ||
31 | { 0x0b, KEY_MUTE }, | ||
32 | { 0x0c, KEY_CHANNELUP }, | ||
33 | { 0x0d, KEY_VOLUMEUP }, | ||
34 | { 0x0e, KEY_CHANNELDOWN }, | ||
35 | { 0x0f, KEY_VOLUMEDOWN }, | ||
36 | { 0x10, KEY_UP }, | ||
37 | { 0x11, KEY_LEFT }, | ||
38 | { 0x12, KEY_OK }, | ||
39 | { 0x13, KEY_RIGHT }, | ||
40 | { 0x14, KEY_DOWN }, | ||
41 | { 0x15, KEY_MENU }, | ||
42 | { 0x16, KEY_EXIT }, | ||
43 | { 0x17, KEY_PLAY }, | ||
44 | { 0x18, KEY_PAUSE }, | ||
45 | { 0x19, KEY_STOP }, | ||
46 | { 0x1a, KEY_BACK }, | ||
47 | { 0x1b, KEY_FORWARD }, | ||
48 | { 0x1c, KEY_RECORD }, | ||
49 | { 0x1d, KEY_REWIND }, | ||
50 | { 0x1e, KEY_FASTFORWARD }, | ||
51 | { 0x20, KEY_RED }, | ||
52 | { 0x21, KEY_GREEN }, | ||
53 | { 0x22, KEY_YELLOW }, | ||
54 | { 0x23, KEY_BLUE }, | ||
55 | |||
56 | }; | ||
57 | |||
58 | static struct rc_keymap rc5_streamzap_map = { | ||
59 | .map = { | ||
60 | .scan = rc5_streamzap, | ||
61 | .size = ARRAY_SIZE(rc5_streamzap), | ||
62 | .ir_type = IR_TYPE_RC5, | ||
63 | .name = RC_MAP_RC5_STREAMZAP, | ||
64 | } | ||
65 | }; | ||
66 | |||
67 | static int __init init_rc_map_rc5_streamzap(void) | ||
68 | { | ||
69 | return ir_register_map(&rc5_streamzap_map); | ||
70 | } | ||
71 | |||
72 | static void __exit exit_rc_map_rc5_streamzap(void) | ||
73 | { | ||
74 | ir_unregister_map(&rc5_streamzap_map); | ||
75 | } | ||
76 | |||
77 | module_init(init_rc_map_rc5_streamzap) | ||
78 | module_exit(exit_rc_map_rc5_streamzap) | ||
79 | |||
80 | MODULE_LICENSE("GPL"); | ||
81 | MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); | ||
diff --git a/drivers/staging/lirc/lirc_streamzap.c b/drivers/staging/lirc/lirc_streamzap.c index be09c103f0c9..058e29fd478c 100644 --- a/drivers/staging/lirc/lirc_streamzap.c +++ b/drivers/staging/lirc/lirc_streamzap.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Streamzap Remote Control driver | 2 | * Streamzap Remote Control driver |
3 | * | 3 | * |
4 | * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de> | 4 | * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de> |
5 | * Copyright (c) 2010 Jarod Wilson <jarod@wilsonet.com> | ||
5 | * | 6 | * |
6 | * This driver was based on the work of Greg Wickham and Adrian | 7 | * This driver was based on the work of Greg Wickham and Adrian |
7 | * Dewhurst. It was substantially rewritten to support correct signal | 8 | * Dewhurst. It was substantially rewritten to support correct signal |
@@ -10,6 +11,8 @@ | |||
10 | * delay buffer an ugly hack would be required in lircd, which can | 11 | * delay buffer an ugly hack would be required in lircd, which can |
11 | * cause sluggish signal decoding in certain situations. | 12 | * cause sluggish signal decoding in certain situations. |
12 | * | 13 | * |
14 | * Ported to in-kernel ir-core interface by Jarod Wilson | ||
15 | * | ||
13 | * This driver is based on the USB skeleton driver packaged with the | 16 | * This driver is based on the USB skeleton driver packaged with the |
14 | * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com) | 17 | * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com) |
15 | * | 18 | * |
@@ -28,36 +31,26 @@ | |||
28 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
29 | */ | 32 | */ |
30 | 33 | ||
31 | #include <linux/kernel.h> | 34 | #include <linux/device.h> |
32 | #include <linux/errno.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/smp_lock.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/completion.h> | ||
38 | #include <linux/uaccess.h> | ||
39 | #include <linux/usb.h> | 37 | #include <linux/usb.h> |
38 | #include <linux/input.h> | ||
39 | #include <media/ir-core.h> | ||
40 | 40 | ||
41 | #include <media/lirc.h> | 41 | #define DRIVER_VERSION "1.60" |
42 | #include <media/lirc_dev.h> | 42 | #define DRIVER_NAME "streamzap" |
43 | |||
44 | #define DRIVER_VERSION "1.28" | ||
45 | #define DRIVER_NAME "lirc_streamzap" | ||
46 | #define DRIVER_DESC "Streamzap Remote Control driver" | 43 | #define DRIVER_DESC "Streamzap Remote Control driver" |
47 | 44 | ||
45 | #ifdef CONFIG_USB_DEBUG | ||
46 | static int debug = 1; | ||
47 | #else | ||
48 | static int debug; | 48 | static int debug; |
49 | #endif | ||
49 | 50 | ||
50 | #define USB_STREAMZAP_VENDOR_ID 0x0e9c | 51 | #define USB_STREAMZAP_VENDOR_ID 0x0e9c |
51 | #define USB_STREAMZAP_PRODUCT_ID 0x0000 | 52 | #define USB_STREAMZAP_PRODUCT_ID 0x0000 |
52 | 53 | ||
53 | /* Use our own dbg macro */ | ||
54 | #define dprintk(fmt, args...) \ | ||
55 | do { \ | ||
56 | if (debug) \ | ||
57 | printk(KERN_DEBUG DRIVER_NAME "[%d]: " \ | ||
58 | fmt "\n", ## args); \ | ||
59 | } while (0) | ||
60 | |||
61 | /* table of devices that work with this driver */ | 54 | /* table of devices that work with this driver */ |
62 | static struct usb_device_id streamzap_table[] = { | 55 | static struct usb_device_id streamzap_table[] = { |
63 | /* Streamzap Remote Control */ | 56 | /* Streamzap Remote Control */ |
@@ -74,7 +67,7 @@ MODULE_DEVICE_TABLE(usb, streamzap_table); | |||
74 | #define STREAMZAP_RESOLUTION 256 | 67 | #define STREAMZAP_RESOLUTION 256 |
75 | 68 | ||
76 | /* number of samples buffered */ | 69 | /* number of samples buffered */ |
77 | #define STREAMZAP_BUF_LEN 128 | 70 | #define SZ_BUF_LEN 128 |
78 | 71 | ||
79 | enum StreamzapDecoderState { | 72 | enum StreamzapDecoderState { |
80 | PulseSpace, | 73 | PulseSpace, |
@@ -83,65 +76,52 @@ enum StreamzapDecoderState { | |||
83 | IgnorePulse | 76 | IgnorePulse |
84 | }; | 77 | }; |
85 | 78 | ||
86 | /* Structure to hold all of our device specific stuff | 79 | /* structure to hold our device specific stuff */ |
87 | * | 80 | struct streamzap_ir { |
88 | * some remarks regarding locking: | 81 | |
89 | * theoretically this struct can be accessed from three threads: | 82 | /* ir-core */ |
90 | * | 83 | struct ir_dev_props *props; |
91 | * - from lirc_dev through set_use_inc/set_use_dec | 84 | struct ir_raw_event rawir; |
92 | * | 85 | |
93 | * - from the USB layer throuh probe/disconnect/irq | 86 | /* core device info */ |
94 | * | 87 | struct device *dev; |
95 | * Careful placement of lirc_register_driver/lirc_unregister_driver | 88 | struct input_dev *idev; |
96 | * calls will prevent conflicts. lirc_dev makes sure that | ||
97 | * set_use_inc/set_use_dec are not being executed and will not be | ||
98 | * called after lirc_unregister_driver returns. | ||
99 | * | ||
100 | * - by the timer callback | ||
101 | * | ||
102 | * The timer is only running when the device is connected and the | ||
103 | * LIRC device is open. Making sure the timer is deleted by | ||
104 | * set_use_dec will make conflicts impossible. | ||
105 | */ | ||
106 | struct usb_streamzap { | ||
107 | 89 | ||
108 | /* usb */ | 90 | /* usb */ |
109 | /* save off the usb device pointer */ | 91 | struct usb_device *usbdev; |
110 | struct usb_device *udev; | ||
111 | /* the interface for this device */ | ||
112 | struct usb_interface *interface; | 92 | struct usb_interface *interface; |
93 | struct usb_endpoint_descriptor *endpoint; | ||
94 | struct urb *urb_in; | ||
113 | 95 | ||
114 | /* buffer & dma */ | 96 | /* buffer & dma */ |
115 | unsigned char *buf_in; | 97 | unsigned char *buf_in; |
116 | dma_addr_t dma_in; | 98 | dma_addr_t dma_in; |
117 | unsigned int buf_in_len; | 99 | unsigned int buf_in_len; |
118 | 100 | ||
119 | struct usb_endpoint_descriptor *endpoint; | ||
120 | |||
121 | /* IRQ */ | ||
122 | struct urb *urb_in; | ||
123 | |||
124 | /* lirc */ | ||
125 | struct lirc_driver *driver; | ||
126 | struct lirc_buffer *delay_buf; | ||
127 | |||
128 | /* timer used to support delay buffering */ | 101 | /* timer used to support delay buffering */ |
129 | struct timer_list delay_timer; | 102 | struct timer_list delay_timer; |
130 | int timer_running; | 103 | bool timer_running; |
131 | spinlock_t timer_lock; | 104 | spinlock_t timer_lock; |
105 | struct timer_list flush_timer; | ||
106 | bool flush; | ||
107 | |||
108 | /* delay buffer */ | ||
109 | struct kfifo fifo; | ||
110 | bool fifo_initialized; | ||
132 | 111 | ||
112 | /* track what state we're in */ | ||
113 | enum StreamzapDecoderState decoder_state; | ||
133 | /* tracks whether we are currently receiving some signal */ | 114 | /* tracks whether we are currently receiving some signal */ |
134 | int idle; | 115 | bool idle; |
135 | /* sum of signal lengths received since signal start */ | 116 | /* sum of signal lengths received since signal start */ |
136 | unsigned long sum; | 117 | unsigned long sum; |
137 | /* start time of signal; necessary for gap tracking */ | 118 | /* start time of signal; necessary for gap tracking */ |
138 | struct timeval signal_last; | 119 | struct timeval signal_last; |
139 | struct timeval signal_start; | 120 | struct timeval signal_start; |
140 | enum StreamzapDecoderState decoder_state; | 121 | /* bool timeout_enabled; */ |
141 | struct timer_list flush_timer; | 122 | |
142 | int flush; | 123 | char name[128]; |
143 | int in_use; | 124 | char phys[64]; |
144 | int timeout_enabled; | ||
145 | }; | 125 | }; |
146 | 126 | ||
147 | 127 | ||
@@ -149,16 +129,11 @@ struct usb_streamzap { | |||
149 | static int streamzap_probe(struct usb_interface *interface, | 129 | static int streamzap_probe(struct usb_interface *interface, |
150 | const struct usb_device_id *id); | 130 | const struct usb_device_id *id); |
151 | static void streamzap_disconnect(struct usb_interface *interface); | 131 | static void streamzap_disconnect(struct usb_interface *interface); |
152 | static void usb_streamzap_irq(struct urb *urb); | 132 | static void streamzap_callback(struct urb *urb); |
153 | static int streamzap_use_inc(void *data); | ||
154 | static void streamzap_use_dec(void *data); | ||
155 | static long streamzap_ioctl(struct file *filep, unsigned int cmd, | ||
156 | unsigned long arg); | ||
157 | static int streamzap_suspend(struct usb_interface *intf, pm_message_t message); | 133 | static int streamzap_suspend(struct usb_interface *intf, pm_message_t message); |
158 | static int streamzap_resume(struct usb_interface *intf); | 134 | static int streamzap_resume(struct usb_interface *intf); |
159 | 135 | ||
160 | /* usb specific object needed to register this driver with the usb subsystem */ | 136 | /* usb specific object needed to register this driver with the usb subsystem */ |
161 | |||
162 | static struct usb_driver streamzap_driver = { | 137 | static struct usb_driver streamzap_driver = { |
163 | .name = DRIVER_NAME, | 138 | .name = DRIVER_NAME, |
164 | .probe = streamzap_probe, | 139 | .probe = streamzap_probe, |
@@ -168,13 +143,13 @@ static struct usb_driver streamzap_driver = { | |||
168 | .id_table = streamzap_table, | 143 | .id_table = streamzap_table, |
169 | }; | 144 | }; |
170 | 145 | ||
171 | static void stop_timer(struct usb_streamzap *sz) | 146 | static void streamzap_stop_timer(struct streamzap_ir *sz) |
172 | { | 147 | { |
173 | unsigned long flags; | 148 | unsigned long flags; |
174 | 149 | ||
175 | spin_lock_irqsave(&sz->timer_lock, flags); | 150 | spin_lock_irqsave(&sz->timer_lock, flags); |
176 | if (sz->timer_running) { | 151 | if (sz->timer_running) { |
177 | sz->timer_running = 0; | 152 | sz->timer_running = false; |
178 | spin_unlock_irqrestore(&sz->timer_lock, flags); | 153 | spin_unlock_irqrestore(&sz->timer_lock, flags); |
179 | del_timer_sync(&sz->delay_timer); | 154 | del_timer_sync(&sz->delay_timer); |
180 | } else { | 155 | } else { |
@@ -182,175 +157,183 @@ static void stop_timer(struct usb_streamzap *sz) | |||
182 | } | 157 | } |
183 | } | 158 | } |
184 | 159 | ||
185 | static void flush_timeout(unsigned long arg) | 160 | static void streamzap_flush_timeout(unsigned long arg) |
186 | { | 161 | { |
187 | struct usb_streamzap *sz = (struct usb_streamzap *) arg; | 162 | struct streamzap_ir *sz = (struct streamzap_ir *)arg; |
163 | |||
164 | dev_info(sz->dev, "%s: callback firing\n", __func__); | ||
188 | 165 | ||
189 | /* finally start accepting data */ | 166 | /* finally start accepting data */ |
190 | sz->flush = 0; | 167 | sz->flush = false; |
191 | } | 168 | } |
192 | static void delay_timeout(unsigned long arg) | 169 | |
170 | static void streamzap_delay_timeout(unsigned long arg) | ||
193 | { | 171 | { |
172 | struct streamzap_ir *sz = (struct streamzap_ir *)arg; | ||
173 | struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; | ||
194 | unsigned long flags; | 174 | unsigned long flags; |
175 | int len, ret; | ||
176 | static unsigned long delay; | ||
177 | bool wake = false; | ||
178 | |||
195 | /* deliver data every 10 ms */ | 179 | /* deliver data every 10 ms */ |
196 | static unsigned long timer_inc = | 180 | delay = msecs_to_jiffies(10); |
197 | (10000/(1000000/HZ)) == 0 ? 1 : (10000/(1000000/HZ)); | ||
198 | struct usb_streamzap *sz = (struct usb_streamzap *) arg; | ||
199 | int data; | ||
200 | 181 | ||
201 | spin_lock_irqsave(&sz->timer_lock, flags); | 182 | spin_lock_irqsave(&sz->timer_lock, flags); |
202 | 183 | ||
203 | if (!lirc_buffer_empty(sz->delay_buf) && | 184 | if (kfifo_len(&sz->fifo) > 0) { |
204 | !lirc_buffer_full(sz->driver->rbuf)) { | 185 | ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir)); |
205 | lirc_buffer_read(sz->delay_buf, (unsigned char *) &data); | 186 | if (ret != sizeof(rawir)) |
206 | lirc_buffer_write(sz->driver->rbuf, (unsigned char *) &data); | 187 | dev_err(sz->dev, "Problem w/kfifo_out...\n"); |
188 | ir_raw_event_store(sz->idev, &rawir); | ||
189 | wake = true; | ||
207 | } | 190 | } |
208 | if (!lirc_buffer_empty(sz->delay_buf)) { | 191 | |
209 | while (lirc_buffer_available(sz->delay_buf) < | 192 | len = kfifo_len(&sz->fifo); |
210 | STREAMZAP_BUF_LEN / 2 && | 193 | if (len > 0) { |
211 | !lirc_buffer_full(sz->driver->rbuf)) { | 194 | while ((len < SZ_BUF_LEN / 2) && |
212 | lirc_buffer_read(sz->delay_buf, | 195 | (len < SZ_BUF_LEN * sizeof(int))) { |
213 | (unsigned char *) &data); | 196 | ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir)); |
214 | lirc_buffer_write(sz->driver->rbuf, | 197 | if (ret != sizeof(rawir)) |
215 | (unsigned char *) &data); | 198 | dev_err(sz->dev, "Problem w/kfifo_out...\n"); |
216 | } | 199 | ir_raw_event_store(sz->idev, &rawir); |
217 | if (sz->timer_running) { | 200 | wake = true; |
218 | sz->delay_timer.expires = jiffies + timer_inc; | 201 | len = kfifo_len(&sz->fifo); |
219 | add_timer(&sz->delay_timer); | ||
220 | } | 202 | } |
203 | if (sz->timer_running) | ||
204 | mod_timer(&sz->delay_timer, jiffies + delay); | ||
205 | |||
221 | } else { | 206 | } else { |
222 | sz->timer_running = 0; | 207 | sz->timer_running = false; |
223 | } | 208 | } |
224 | 209 | ||
225 | if (!lirc_buffer_empty(sz->driver->rbuf)) | 210 | if (wake) |
226 | wake_up(&sz->driver->rbuf->wait_poll); | 211 | ir_raw_event_handle(sz->idev); |
227 | 212 | ||
228 | spin_unlock_irqrestore(&sz->timer_lock, flags); | 213 | spin_unlock_irqrestore(&sz->timer_lock, flags); |
229 | } | 214 | } |
230 | 215 | ||
231 | static void flush_delay_buffer(struct usb_streamzap *sz) | 216 | static void streamzap_flush_delay_buffer(struct streamzap_ir *sz) |
232 | { | 217 | { |
233 | int data; | 218 | struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; |
234 | int empty = 1; | 219 | bool wake = false; |
235 | 220 | int ret; | |
236 | while (!lirc_buffer_empty(sz->delay_buf)) { | 221 | |
237 | empty = 0; | 222 | while (kfifo_len(&sz->fifo) > 0) { |
238 | lirc_buffer_read(sz->delay_buf, (unsigned char *) &data); | 223 | ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir)); |
239 | if (!lirc_buffer_full(sz->driver->rbuf)) { | 224 | if (ret != sizeof(rawir)) |
240 | lirc_buffer_write(sz->driver->rbuf, | 225 | dev_err(sz->dev, "Problem w/kfifo_out...\n"); |
241 | (unsigned char *) &data); | 226 | ir_raw_event_store(sz->idev, &rawir); |
242 | } else { | 227 | wake = true; |
243 | dprintk("buffer overflow", sz->driver->minor); | ||
244 | } | ||
245 | } | 228 | } |
246 | if (!empty) | 229 | |
247 | wake_up(&sz->driver->rbuf->wait_poll); | 230 | if (wake) |
231 | ir_raw_event_handle(sz->idev); | ||
248 | } | 232 | } |
249 | 233 | ||
250 | static void push(struct usb_streamzap *sz, unsigned char *data) | 234 | static void sz_push(struct streamzap_ir *sz) |
251 | { | 235 | { |
236 | struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; | ||
252 | unsigned long flags; | 237 | unsigned long flags; |
238 | int ret; | ||
253 | 239 | ||
254 | spin_lock_irqsave(&sz->timer_lock, flags); | 240 | spin_lock_irqsave(&sz->timer_lock, flags); |
255 | if (lirc_buffer_full(sz->delay_buf)) { | 241 | if (kfifo_len(&sz->fifo) >= sizeof(int) * SZ_BUF_LEN) { |
256 | int read_data; | 242 | ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir)); |
257 | 243 | if (ret != sizeof(rawir)) | |
258 | lirc_buffer_read(sz->delay_buf, | 244 | dev_err(sz->dev, "Problem w/kfifo_out...\n"); |
259 | (unsigned char *) &read_data); | 245 | ir_raw_event_store(sz->idev, &rawir); |
260 | if (!lirc_buffer_full(sz->driver->rbuf)) { | ||
261 | lirc_buffer_write(sz->driver->rbuf, | ||
262 | (unsigned char *) &read_data); | ||
263 | } else { | ||
264 | dprintk("buffer overflow", sz->driver->minor); | ||
265 | } | ||
266 | } | 246 | } |
267 | 247 | ||
268 | lirc_buffer_write(sz->delay_buf, data); | 248 | kfifo_in(&sz->fifo, &sz->rawir, sizeof(rawir)); |
269 | 249 | ||
270 | if (!sz->timer_running) { | 250 | if (!sz->timer_running) { |
271 | sz->delay_timer.expires = jiffies + HZ/10; | 251 | sz->delay_timer.expires = jiffies + (HZ / 10); |
272 | add_timer(&sz->delay_timer); | 252 | add_timer(&sz->delay_timer); |
273 | sz->timer_running = 1; | 253 | sz->timer_running = true; |
274 | } | 254 | } |
275 | 255 | ||
276 | spin_unlock_irqrestore(&sz->timer_lock, flags); | 256 | spin_unlock_irqrestore(&sz->timer_lock, flags); |
277 | } | 257 | } |
278 | 258 | ||
279 | static void push_full_pulse(struct usb_streamzap *sz, | 259 | static void sz_push_full_pulse(struct streamzap_ir *sz, |
280 | unsigned char value) | 260 | unsigned char value) |
281 | { | 261 | { |
282 | int pulse; | ||
283 | |||
284 | if (sz->idle) { | 262 | if (sz->idle) { |
285 | long deltv; | 263 | long deltv; |
286 | int tmp; | ||
287 | 264 | ||
288 | sz->signal_last = sz->signal_start; | 265 | sz->signal_last = sz->signal_start; |
289 | do_gettimeofday(&sz->signal_start); | 266 | do_gettimeofday(&sz->signal_start); |
290 | 267 | ||
291 | deltv = sz->signal_start.tv_sec-sz->signal_last.tv_sec; | 268 | deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec; |
269 | sz->rawir.pulse = false; | ||
292 | if (deltv > 15) { | 270 | if (deltv > 15) { |
293 | /* really long time */ | 271 | /* really long time */ |
294 | tmp = LIRC_SPACE(LIRC_VALUE_MASK); | 272 | sz->rawir.duration = IR_MAX_DURATION; |
295 | } else { | 273 | } else { |
296 | tmp = (int) (deltv*1000000+ | 274 | sz->rawir.duration = (int)(deltv * 1000000 + |
297 | sz->signal_start.tv_usec - | 275 | sz->signal_start.tv_usec - |
298 | sz->signal_last.tv_usec); | 276 | sz->signal_last.tv_usec); |
299 | tmp -= sz->sum; | 277 | sz->rawir.duration -= sz->sum; |
300 | tmp = LIRC_SPACE(tmp); | 278 | sz->rawir.duration *= 1000; |
279 | sz->rawir.duration &= IR_MAX_DURATION; | ||
301 | } | 280 | } |
302 | dprintk("ls %u", sz->driver->minor, tmp); | 281 | dev_dbg(sz->dev, "ls %u\n", sz->rawir.duration); |
303 | push(sz, (char *)&tmp); | 282 | sz_push(sz); |
304 | 283 | ||
305 | sz->idle = 0; | 284 | sz->idle = 0; |
306 | sz->sum = 0; | 285 | sz->sum = 0; |
307 | } | 286 | } |
308 | 287 | ||
309 | pulse = ((int) value) * STREAMZAP_RESOLUTION; | 288 | sz->rawir.pulse = true; |
310 | pulse += STREAMZAP_RESOLUTION / 2; | 289 | sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION; |
311 | sz->sum += pulse; | 290 | sz->rawir.duration += STREAMZAP_RESOLUTION / 2; |
312 | pulse = LIRC_PULSE(pulse); | 291 | sz->sum += sz->rawir.duration; |
313 | 292 | sz->rawir.duration *= 1000; | |
314 | dprintk("p %u", sz->driver->minor, pulse & PULSE_MASK); | 293 | sz->rawir.duration &= IR_MAX_DURATION; |
315 | push(sz, (char *)&pulse); | 294 | dev_dbg(sz->dev, "p %u\n", sz->rawir.duration); |
295 | sz_push(sz); | ||
316 | } | 296 | } |
317 | 297 | ||
318 | static void push_half_pulse(struct usb_streamzap *sz, | 298 | static void sz_push_half_pulse(struct streamzap_ir *sz, |
319 | unsigned char value) | 299 | unsigned char value) |
320 | { | 300 | { |
321 | push_full_pulse(sz, (value & STREAMZAP_PULSE_MASK)>>4); | 301 | sz_push_full_pulse(sz, (value & STREAMZAP_PULSE_MASK) >> 4); |
322 | } | 302 | } |
323 | 303 | ||
324 | static void push_full_space(struct usb_streamzap *sz, | 304 | static void sz_push_full_space(struct streamzap_ir *sz, |
325 | unsigned char value) | 305 | unsigned char value) |
326 | { | 306 | { |
327 | int space; | 307 | sz->rawir.pulse = false; |
328 | 308 | sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION; | |
329 | space = ((int) value)*STREAMZAP_RESOLUTION; | 309 | sz->rawir.duration += STREAMZAP_RESOLUTION / 2; |
330 | space += STREAMZAP_RESOLUTION/2; | 310 | sz->sum += sz->rawir.duration; |
331 | sz->sum += space; | 311 | sz->rawir.duration *= 1000; |
332 | space = LIRC_SPACE(space); | 312 | dev_dbg(sz->dev, "s %u\n", sz->rawir.duration); |
333 | dprintk("s %u", sz->driver->minor, space); | 313 | sz_push(sz); |
334 | push(sz, (char *)&space); | ||
335 | } | 314 | } |
336 | 315 | ||
337 | static void push_half_space(struct usb_streamzap *sz, | 316 | static void sz_push_half_space(struct streamzap_ir *sz, |
338 | unsigned char value) | 317 | unsigned long value) |
339 | { | 318 | { |
340 | push_full_space(sz, value & STREAMZAP_SPACE_MASK); | 319 | sz_push_full_space(sz, value & STREAMZAP_SPACE_MASK); |
341 | } | 320 | } |
342 | 321 | ||
343 | /** | 322 | /** |
344 | * usb_streamzap_irq - IRQ handler | 323 | * streamzap_callback - usb IRQ handler callback |
345 | * | 324 | * |
346 | * This procedure is invoked on reception of data from | 325 | * This procedure is invoked on reception of data from |
347 | * the usb remote. | 326 | * the usb remote. |
348 | */ | 327 | */ |
349 | static void usb_streamzap_irq(struct urb *urb) | 328 | static void streamzap_callback(struct urb *urb) |
350 | { | 329 | { |
351 | struct usb_streamzap *sz; | 330 | struct streamzap_ir *sz; |
352 | int len; | 331 | unsigned int i; |
353 | unsigned int i = 0; | 332 | int len; |
333 | #if 0 | ||
334 | static int timeout = (((STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION) & | ||
335 | IR_MAX_DURATION) | 0x03000000); | ||
336 | #endif | ||
354 | 337 | ||
355 | if (!urb) | 338 | if (!urb) |
356 | return; | 339 | return; |
@@ -366,51 +349,52 @@ static void usb_streamzap_irq(struct urb *urb) | |||
366 | * this urb is terminated, clean up. | 349 | * this urb is terminated, clean up. |
367 | * sz might already be invalid at this point | 350 | * sz might already be invalid at this point |
368 | */ | 351 | */ |
369 | dprintk("urb status: %d", -1, urb->status); | 352 | dev_err(sz->dev, "urb terminated, status: %d\n", urb->status); |
370 | return; | 353 | return; |
371 | default: | 354 | default: |
372 | break; | 355 | break; |
373 | } | 356 | } |
374 | 357 | ||
375 | dprintk("received %d", sz->driver->minor, urb->actual_length); | 358 | dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len); |
376 | if (!sz->flush) { | 359 | if (!sz->flush) { |
377 | for (i = 0; i < urb->actual_length; i++) { | 360 | for (i = 0; i < urb->actual_length; i++) { |
378 | dprintk("%d: %x", sz->driver->minor, | 361 | dev_dbg(sz->dev, "%d: %x\n", i, |
379 | i, (unsigned char) sz->buf_in[i]); | 362 | (unsigned char)sz->buf_in[i]); |
380 | switch (sz->decoder_state) { | 363 | switch (sz->decoder_state) { |
381 | case PulseSpace: | 364 | case PulseSpace: |
382 | if ((sz->buf_in[i]&STREAMZAP_PULSE_MASK) == | 365 | if ((sz->buf_in[i] & STREAMZAP_PULSE_MASK) == |
383 | STREAMZAP_PULSE_MASK) { | 366 | STREAMZAP_PULSE_MASK) { |
384 | sz->decoder_state = FullPulse; | 367 | sz->decoder_state = FullPulse; |
385 | continue; | 368 | continue; |
386 | } else if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) | 369 | } else if ((sz->buf_in[i] & STREAMZAP_SPACE_MASK) |
387 | == STREAMZAP_SPACE_MASK) { | 370 | == STREAMZAP_SPACE_MASK) { |
388 | push_half_pulse(sz, sz->buf_in[i]); | 371 | sz_push_half_pulse(sz, sz->buf_in[i]); |
389 | sz->decoder_state = FullSpace; | 372 | sz->decoder_state = FullSpace; |
390 | continue; | 373 | continue; |
391 | } else { | 374 | } else { |
392 | push_half_pulse(sz, sz->buf_in[i]); | 375 | sz_push_half_pulse(sz, sz->buf_in[i]); |
393 | push_half_space(sz, sz->buf_in[i]); | 376 | sz_push_half_space(sz, sz->buf_in[i]); |
394 | } | 377 | } |
395 | break; | 378 | break; |
396 | case FullPulse: | 379 | case FullPulse: |
397 | push_full_pulse(sz, sz->buf_in[i]); | 380 | sz_push_full_pulse(sz, sz->buf_in[i]); |
398 | sz->decoder_state = IgnorePulse; | 381 | sz->decoder_state = IgnorePulse; |
399 | break; | 382 | break; |
400 | case FullSpace: | 383 | case FullSpace: |
401 | if (sz->buf_in[i] == STREAMZAP_TIMEOUT) { | 384 | if (sz->buf_in[i] == STREAMZAP_TIMEOUT) { |
402 | sz->idle = 1; | 385 | sz->idle = 1; |
403 | stop_timer(sz); | 386 | streamzap_stop_timer(sz); |
387 | #if 0 | ||
404 | if (sz->timeout_enabled) { | 388 | if (sz->timeout_enabled) { |
405 | int timeout = | 389 | sz->rawir.pulse = false; |
406 | LIRC_TIMEOUT | 390 | sz->rawir.duration = timeout; |
407 | (STREAMZAP_TIMEOUT * | 391 | sz->rawir.duration *= 1000; |
408 | STREAMZAP_RESOLUTION); | 392 | sz_push(sz); |
409 | push(sz, (char *)&timeout); | ||
410 | } | 393 | } |
411 | flush_delay_buffer(sz); | 394 | #endif |
395 | streamzap_flush_delay_buffer(sz); | ||
412 | } else | 396 | } else |
413 | push_full_space(sz, sz->buf_in[i]); | 397 | sz_push_full_space(sz, sz->buf_in[i]); |
414 | sz->decoder_state = PulseSpace; | 398 | sz->decoder_state = PulseSpace; |
415 | break; | 399 | break; |
416 | case IgnorePulse: | 400 | case IgnorePulse: |
@@ -419,7 +403,7 @@ static void usb_streamzap_irq(struct urb *urb) | |||
419 | sz->decoder_state = FullSpace; | 403 | sz->decoder_state = FullSpace; |
420 | continue; | 404 | continue; |
421 | } | 405 | } |
422 | push_half_space(sz, sz->buf_in[i]); | 406 | sz_push_half_space(sz, sz->buf_in[i]); |
423 | sz->decoder_state = PulseSpace; | 407 | sz->decoder_state = PulseSpace; |
424 | break; | 408 | break; |
425 | } | 409 | } |
@@ -431,16 +415,80 @@ static void usb_streamzap_irq(struct urb *urb) | |||
431 | return; | 415 | return; |
432 | } | 416 | } |
433 | 417 | ||
434 | static const struct file_operations streamzap_fops = { | 418 | static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz) |
435 | .owner = THIS_MODULE, | 419 | { |
436 | .unlocked_ioctl = streamzap_ioctl, | 420 | struct input_dev *idev; |
437 | .read = lirc_dev_fop_read, | 421 | struct ir_dev_props *props; |
438 | .write = lirc_dev_fop_write, | 422 | struct device *dev = sz->dev; |
439 | .poll = lirc_dev_fop_poll, | 423 | int ret; |
440 | .open = lirc_dev_fop_open, | 424 | |
441 | .release = lirc_dev_fop_close, | 425 | idev = input_allocate_device(); |
442 | }; | 426 | if (!idev) { |
427 | dev_err(dev, "remote input dev allocation failed\n"); | ||
428 | goto idev_alloc_failed; | ||
429 | } | ||
430 | |||
431 | props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); | ||
432 | if (!props) { | ||
433 | dev_err(dev, "remote ir dev props allocation failed\n"); | ||
434 | goto props_alloc_failed; | ||
435 | } | ||
436 | |||
437 | snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared " | ||
438 | "Receiver (%04x:%04x)", | ||
439 | le16_to_cpu(sz->usbdev->descriptor.idVendor), | ||
440 | le16_to_cpu(sz->usbdev->descriptor.idProduct)); | ||
441 | |||
442 | idev->name = sz->name; | ||
443 | usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys)); | ||
444 | strlcat(sz->phys, "/input0", sizeof(sz->phys)); | ||
445 | idev->phys = sz->phys; | ||
446 | |||
447 | props->priv = sz; | ||
448 | props->driver_type = RC_DRIVER_IR_RAW; | ||
449 | /* FIXME: not sure about supported protocols, check on this */ | ||
450 | props->allowed_protos = IR_TYPE_RC5 | IR_TYPE_RC6; | ||
451 | |||
452 | sz->props = props; | ||
453 | |||
454 | ret = ir_input_register(idev, RC_MAP_RC5_STREAMZAP, props, DRIVER_NAME); | ||
455 | if (ret < 0) { | ||
456 | dev_err(dev, "remote input device register failed\n"); | ||
457 | goto irdev_failed; | ||
458 | } | ||
459 | |||
460 | return idev; | ||
461 | |||
462 | irdev_failed: | ||
463 | kfree(props); | ||
464 | props_alloc_failed: | ||
465 | input_free_device(idev); | ||
466 | idev_alloc_failed: | ||
467 | return NULL; | ||
468 | } | ||
469 | |||
470 | static int streamzap_delay_buf_init(struct streamzap_ir *sz) | ||
471 | { | ||
472 | int ret; | ||
473 | |||
474 | ret = kfifo_alloc(&sz->fifo, sizeof(int) * SZ_BUF_LEN, | ||
475 | GFP_KERNEL); | ||
476 | if (ret == 0) | ||
477 | sz->fifo_initialized = 1; | ||
443 | 478 | ||
479 | return ret; | ||
480 | } | ||
481 | |||
482 | static void streamzap_start_flush_timer(struct streamzap_ir *sz) | ||
483 | { | ||
484 | sz->flush_timer.expires = jiffies + HZ; | ||
485 | sz->flush = true; | ||
486 | add_timer(&sz->flush_timer); | ||
487 | |||
488 | sz->urb_in->dev = sz->usbdev; | ||
489 | if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) | ||
490 | dev_err(sz->dev, "urb submit failed\n"); | ||
491 | } | ||
444 | 492 | ||
445 | /** | 493 | /** |
446 | * streamzap_probe | 494 | * streamzap_probe |
@@ -449,33 +497,30 @@ static const struct file_operations streamzap_fops = { | |||
449 | * On any failure the return value is the ERROR | 497 | * On any failure the return value is the ERROR |
450 | * On success return 0 | 498 | * On success return 0 |
451 | */ | 499 | */ |
452 | static int streamzap_probe(struct usb_interface *interface, | 500 | static int __devinit streamzap_probe(struct usb_interface *intf, |
453 | const struct usb_device_id *id) | 501 | const struct usb_device_id *id) |
454 | { | 502 | { |
455 | struct usb_device *udev = interface_to_usbdev(interface); | 503 | struct usb_device *usbdev = interface_to_usbdev(intf); |
456 | struct usb_host_interface *iface_host; | 504 | struct usb_host_interface *iface_host; |
457 | struct usb_streamzap *sz; | 505 | struct streamzap_ir *sz = NULL; |
458 | struct lirc_driver *driver; | ||
459 | struct lirc_buffer *lirc_buf; | ||
460 | struct lirc_buffer *delay_buf; | ||
461 | char buf[63], name[128] = ""; | 506 | char buf[63], name[128] = ""; |
462 | int retval = -ENOMEM; | 507 | int retval = -ENOMEM; |
463 | int minor = 0; | 508 | int pipe, maxp; |
464 | 509 | ||
465 | /* Allocate space for device driver specific data */ | 510 | /* Allocate space for device driver specific data */ |
466 | sz = kzalloc(sizeof(struct usb_streamzap), GFP_KERNEL); | 511 | sz = kzalloc(sizeof(struct streamzap_ir), GFP_KERNEL); |
467 | if (sz == NULL) | 512 | if (!sz) |
468 | return -ENOMEM; | 513 | return -ENOMEM; |
469 | 514 | ||
470 | sz->udev = udev; | 515 | sz->usbdev = usbdev; |
471 | sz->interface = interface; | 516 | sz->interface = intf; |
472 | 517 | ||
473 | /* Check to ensure endpoint information matches requirements */ | 518 | /* Check to ensure endpoint information matches requirements */ |
474 | iface_host = interface->cur_altsetting; | 519 | iface_host = intf->cur_altsetting; |
475 | 520 | ||
476 | if (iface_host->desc.bNumEndpoints != 1) { | 521 | if (iface_host->desc.bNumEndpoints != 1) { |
477 | err("%s: Unexpected desc.bNumEndpoints (%d)", __func__, | 522 | dev_err(&intf->dev, "%s: Unexpected desc.bNumEndpoints (%d)\n", |
478 | iface_host->desc.bNumEndpoints); | 523 | __func__, iface_host->desc.bNumEndpoints); |
479 | retval = -ENODEV; | 524 | retval = -ENODEV; |
480 | goto free_sz; | 525 | goto free_sz; |
481 | } | 526 | } |
@@ -483,219 +528,110 @@ static int streamzap_probe(struct usb_interface *interface, | |||
483 | sz->endpoint = &(iface_host->endpoint[0].desc); | 528 | sz->endpoint = &(iface_host->endpoint[0].desc); |
484 | if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | 529 | if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) |
485 | != USB_DIR_IN) { | 530 | != USB_DIR_IN) { |
486 | err("%s: endpoint doesn't match input device 02%02x", | 531 | dev_err(&intf->dev, "%s: endpoint doesn't match input device " |
487 | __func__, sz->endpoint->bEndpointAddress); | 532 | "02%02x\n", __func__, sz->endpoint->bEndpointAddress); |
488 | retval = -ENODEV; | 533 | retval = -ENODEV; |
489 | goto free_sz; | 534 | goto free_sz; |
490 | } | 535 | } |
491 | 536 | ||
492 | if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | 537 | if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) |
493 | != USB_ENDPOINT_XFER_INT) { | 538 | != USB_ENDPOINT_XFER_INT) { |
494 | err("%s: endpoint attributes don't match xfer 02%02x", | 539 | dev_err(&intf->dev, "%s: endpoint attributes don't match xfer " |
495 | __func__, sz->endpoint->bmAttributes); | 540 | "02%02x\n", __func__, sz->endpoint->bmAttributes); |
496 | retval = -ENODEV; | 541 | retval = -ENODEV; |
497 | goto free_sz; | 542 | goto free_sz; |
498 | } | 543 | } |
499 | 544 | ||
500 | if (sz->endpoint->wMaxPacketSize == 0) { | 545 | pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress); |
501 | err("%s: endpoint message size==0? ", __func__); | 546 | maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe)); |
547 | |||
548 | if (maxp == 0) { | ||
549 | dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n", | ||
550 | __func__); | ||
502 | retval = -ENODEV; | 551 | retval = -ENODEV; |
503 | goto free_sz; | 552 | goto free_sz; |
504 | } | 553 | } |
505 | 554 | ||
506 | /* Allocate the USB buffer and IRQ URB */ | 555 | /* Allocate the USB buffer and IRQ URB */ |
507 | 556 | sz->buf_in = usb_alloc_coherent(usbdev, maxp, GFP_ATOMIC, &sz->dma_in); | |
508 | sz->buf_in_len = sz->endpoint->wMaxPacketSize; | 557 | if (!sz->buf_in) |
509 | sz->buf_in = usb_alloc_coherent(sz->udev, sz->buf_in_len, | ||
510 | GFP_ATOMIC, &sz->dma_in); | ||
511 | if (sz->buf_in == NULL) | ||
512 | goto free_sz; | 558 | goto free_sz; |
513 | 559 | ||
514 | sz->urb_in = usb_alloc_urb(0, GFP_KERNEL); | 560 | sz->urb_in = usb_alloc_urb(0, GFP_KERNEL); |
515 | if (sz->urb_in == NULL) | 561 | if (!sz->urb_in) |
516 | goto free_sz; | 562 | goto free_buf_in; |
517 | |||
518 | /* Connect this device to the LIRC sub-system */ | ||
519 | driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); | ||
520 | if (!driver) | ||
521 | goto free_sz; | ||
522 | 563 | ||
523 | lirc_buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); | 564 | sz->dev = &intf->dev; |
524 | if (!lirc_buf) | 565 | sz->buf_in_len = maxp; |
525 | goto free_driver; | ||
526 | if (lirc_buffer_init(lirc_buf, sizeof(int), STREAMZAP_BUF_LEN)) | ||
527 | goto kfree_lirc_buf; | ||
528 | |||
529 | delay_buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); | ||
530 | if (!delay_buf) | ||
531 | goto free_lirc_buf; | ||
532 | if (lirc_buffer_init(delay_buf, sizeof(int), STREAMZAP_BUF_LEN)) | ||
533 | goto kfree_delay_buf; | ||
534 | |||
535 | sz->driver = driver; | ||
536 | strcpy(sz->driver->name, DRIVER_NAME); | ||
537 | sz->driver->minor = -1; | ||
538 | sz->driver->sample_rate = 0; | ||
539 | sz->driver->code_length = sizeof(int) * 8; | ||
540 | sz->driver->features = LIRC_CAN_REC_MODE2 | | ||
541 | LIRC_CAN_GET_REC_RESOLUTION | | ||
542 | LIRC_CAN_SET_REC_TIMEOUT; | ||
543 | sz->driver->data = sz; | ||
544 | sz->driver->min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION; | ||
545 | sz->driver->max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION; | ||
546 | sz->driver->rbuf = lirc_buf; | ||
547 | sz->delay_buf = delay_buf; | ||
548 | sz->driver->set_use_inc = &streamzap_use_inc; | ||
549 | sz->driver->set_use_dec = &streamzap_use_dec; | ||
550 | sz->driver->fops = &streamzap_fops; | ||
551 | sz->driver->dev = &interface->dev; | ||
552 | sz->driver->owner = THIS_MODULE; | ||
553 | |||
554 | sz->idle = 1; | ||
555 | sz->decoder_state = PulseSpace; | ||
556 | init_timer(&sz->delay_timer); | ||
557 | sz->delay_timer.function = delay_timeout; | ||
558 | sz->delay_timer.data = (unsigned long) sz; | ||
559 | sz->timer_running = 0; | ||
560 | spin_lock_init(&sz->timer_lock); | ||
561 | |||
562 | init_timer(&sz->flush_timer); | ||
563 | sz->flush_timer.function = flush_timeout; | ||
564 | sz->flush_timer.data = (unsigned long) sz; | ||
565 | /* Complete final initialisations */ | ||
566 | 566 | ||
567 | usb_fill_int_urb(sz->urb_in, udev, | 567 | if (usbdev->descriptor.iManufacturer |
568 | usb_rcvintpipe(udev, sz->endpoint->bEndpointAddress), | 568 | && usb_string(usbdev, usbdev->descriptor.iManufacturer, |
569 | sz->buf_in, sz->buf_in_len, usb_streamzap_irq, sz, | ||
570 | sz->endpoint->bInterval); | ||
571 | sz->urb_in->transfer_dma = sz->dma_in; | ||
572 | sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
573 | |||
574 | if (udev->descriptor.iManufacturer | ||
575 | && usb_string(udev, udev->descriptor.iManufacturer, | ||
576 | buf, sizeof(buf)) > 0) | 569 | buf, sizeof(buf)) > 0) |
577 | strlcpy(name, buf, sizeof(name)); | 570 | strlcpy(name, buf, sizeof(name)); |
578 | 571 | ||
579 | if (udev->descriptor.iProduct | 572 | if (usbdev->descriptor.iProduct |
580 | && usb_string(udev, udev->descriptor.iProduct, | 573 | && usb_string(usbdev, usbdev->descriptor.iProduct, |
581 | buf, sizeof(buf)) > 0) | 574 | buf, sizeof(buf)) > 0) |
582 | snprintf(name + strlen(name), sizeof(name) - strlen(name), | 575 | snprintf(name + strlen(name), sizeof(name) - strlen(name), |
583 | " %s", buf); | 576 | " %s", buf); |
584 | 577 | ||
585 | minor = lirc_register_driver(driver); | 578 | retval = streamzap_delay_buf_init(sz); |
586 | 579 | if (retval) { | |
587 | if (minor < 0) | 580 | dev_err(&intf->dev, "%s: delay buffer init failed\n", __func__); |
588 | goto free_delay_buf; | 581 | goto free_urb_in; |
589 | |||
590 | sz->driver->minor = minor; | ||
591 | |||
592 | usb_set_intfdata(interface, sz); | ||
593 | |||
594 | printk(KERN_INFO DRIVER_NAME "[%d]: %s on usb%d:%d attached\n", | ||
595 | sz->driver->minor, name, | ||
596 | udev->bus->busnum, sz->udev->devnum); | ||
597 | |||
598 | return 0; | ||
599 | |||
600 | free_delay_buf: | ||
601 | lirc_buffer_free(sz->delay_buf); | ||
602 | kfree_delay_buf: | ||
603 | kfree(delay_buf); | ||
604 | free_lirc_buf: | ||
605 | lirc_buffer_free(sz->driver->rbuf); | ||
606 | kfree_lirc_buf: | ||
607 | kfree(lirc_buf); | ||
608 | free_driver: | ||
609 | kfree(driver); | ||
610 | free_sz: | ||
611 | if (retval == -ENOMEM) | ||
612 | err("Out of memory"); | ||
613 | |||
614 | if (sz) { | ||
615 | usb_free_urb(sz->urb_in); | ||
616 | usb_free_coherent(udev, sz->buf_in_len, sz->buf_in, sz->dma_in); | ||
617 | kfree(sz); | ||
618 | } | ||
619 | |||
620 | return retval; | ||
621 | } | ||
622 | |||
623 | static int streamzap_use_inc(void *data) | ||
624 | { | ||
625 | struct usb_streamzap *sz = data; | ||
626 | |||
627 | if (!sz) { | ||
628 | dprintk("%s called with no context", -1, __func__); | ||
629 | return -EINVAL; | ||
630 | } | 582 | } |
631 | dprintk("set use inc", sz->driver->minor); | ||
632 | 583 | ||
633 | lirc_buffer_clear(sz->driver->rbuf); | 584 | sz->idev = streamzap_init_input_dev(sz); |
634 | lirc_buffer_clear(sz->delay_buf); | 585 | if (!sz->idev) |
586 | goto input_dev_fail; | ||
635 | 587 | ||
636 | sz->flush_timer.expires = jiffies + HZ; | 588 | sz->idle = true; |
637 | sz->flush = 1; | 589 | sz->decoder_state = PulseSpace; |
638 | add_timer(&sz->flush_timer); | 590 | #if 0 |
591 | /* not yet supported, depends on patches from maxim */ | ||
592 | /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */ | ||
593 | sz->timeout_enabled = false; | ||
594 | sz->min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000; | ||
595 | sz->max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000; | ||
596 | #endif | ||
639 | 597 | ||
640 | sz->urb_in->dev = sz->udev; | 598 | init_timer(&sz->delay_timer); |
641 | if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { | 599 | sz->delay_timer.function = streamzap_delay_timeout; |
642 | dprintk("open result = -EIO error submitting urb", | 600 | sz->delay_timer.data = (unsigned long)sz; |
643 | sz->driver->minor); | 601 | spin_lock_init(&sz->timer_lock); |
644 | return -EIO; | ||
645 | } | ||
646 | sz->in_use++; | ||
647 | 602 | ||
648 | return 0; | 603 | init_timer(&sz->flush_timer); |
649 | } | 604 | sz->flush_timer.function = streamzap_flush_timeout; |
605 | sz->flush_timer.data = (unsigned long)sz; | ||
650 | 606 | ||
651 | static void streamzap_use_dec(void *data) | 607 | do_gettimeofday(&sz->signal_start); |
652 | { | ||
653 | struct usb_streamzap *sz = data; | ||
654 | 608 | ||
655 | if (!sz) { | 609 | /* Complete final initialisations */ |
656 | dprintk("%s called with no context", -1, __func__); | 610 | usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in, |
657 | return; | 611 | maxp, (usb_complete_t)streamzap_callback, |
658 | } | 612 | sz, sz->endpoint->bInterval); |
659 | dprintk("set use dec", sz->driver->minor); | 613 | sz->urb_in->transfer_dma = sz->dma_in; |
614 | sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
660 | 615 | ||
661 | if (sz->flush) { | 616 | usb_set_intfdata(intf, sz); |
662 | sz->flush = 0; | ||
663 | del_timer_sync(&sz->flush_timer); | ||
664 | } | ||
665 | 617 | ||
666 | usb_kill_urb(sz->urb_in); | 618 | streamzap_start_flush_timer(sz); |
667 | 619 | ||
668 | stop_timer(sz); | 620 | dev_info(sz->dev, "Registered %s on usb%d:%d\n", name, |
621 | usbdev->bus->busnum, usbdev->devnum); | ||
669 | 622 | ||
670 | sz->in_use--; | 623 | return 0; |
671 | } | ||
672 | 624 | ||
673 | static long streamzap_ioctl(struct file *filep, unsigned int cmd, | 625 | input_dev_fail: |
674 | unsigned long arg) | 626 | kfifo_free(&sz->fifo); |
675 | { | 627 | free_urb_in: |
676 | int result = 0; | 628 | usb_free_urb(sz->urb_in); |
677 | int val; | 629 | free_buf_in: |
678 | struct usb_streamzap *sz = lirc_get_pdata(filep); | 630 | usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in); |
631 | free_sz: | ||
632 | kfree(sz); | ||
679 | 633 | ||
680 | switch (cmd) { | 634 | return retval; |
681 | case LIRC_GET_REC_RESOLUTION: | ||
682 | result = put_user(STREAMZAP_RESOLUTION, (unsigned int *) arg); | ||
683 | break; | ||
684 | case LIRC_SET_REC_TIMEOUT: | ||
685 | result = get_user(val, (int *)arg); | ||
686 | if (result == 0) { | ||
687 | if (val == STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION) | ||
688 | sz->timeout_enabled = 1; | ||
689 | else if (val == 0) | ||
690 | sz->timeout_enabled = 0; | ||
691 | else | ||
692 | result = -EINVAL; | ||
693 | } | ||
694 | break; | ||
695 | default: | ||
696 | return lirc_dev_fop_ioctl(filep, cmd, arg); | ||
697 | } | ||
698 | return result; | ||
699 | } | 635 | } |
700 | 636 | ||
701 | /** | 637 | /** |
@@ -704,116 +640,100 @@ static long streamzap_ioctl(struct file *filep, unsigned int cmd, | |||
704 | * Called by the usb core when the device is removed from the system. | 640 | * Called by the usb core when the device is removed from the system. |
705 | * | 641 | * |
706 | * This routine guarantees that the driver will not submit any more urbs | 642 | * This routine guarantees that the driver will not submit any more urbs |
707 | * by clearing dev->udev. It is also supposed to terminate any currently | 643 | * by clearing dev->usbdev. It is also supposed to terminate any currently |
708 | * active urbs. Unfortunately, usb_bulk_msg(), used in streamzap_read(), | 644 | * active urbs. Unfortunately, usb_bulk_msg(), used in streamzap_read(), |
709 | * does not provide any way to do this. | 645 | * does not provide any way to do this. |
710 | */ | 646 | */ |
711 | static void streamzap_disconnect(struct usb_interface *interface) | 647 | static void streamzap_disconnect(struct usb_interface *interface) |
712 | { | 648 | { |
713 | struct usb_streamzap *sz; | 649 | struct streamzap_ir *sz = usb_get_intfdata(interface); |
714 | int errnum; | 650 | struct usb_device *usbdev = interface_to_usbdev(interface); |
715 | int minor; | ||
716 | |||
717 | sz = usb_get_intfdata(interface); | ||
718 | 651 | ||
719 | /* unregister from the LIRC sub-system */ | 652 | usb_set_intfdata(interface, NULL); |
720 | 653 | ||
721 | errnum = lirc_unregister_driver(sz->driver->minor); | 654 | if (!sz) |
722 | if (errnum != 0) | 655 | return; |
723 | dprintk("error in lirc_unregister: (returned %d)", | ||
724 | sz->driver->minor, errnum); | ||
725 | 656 | ||
726 | lirc_buffer_free(sz->delay_buf); | 657 | if (sz->flush) { |
727 | lirc_buffer_free(sz->driver->rbuf); | 658 | sz->flush = false; |
659 | del_timer_sync(&sz->flush_timer); | ||
660 | } | ||
728 | 661 | ||
729 | /* unregister from the USB sub-system */ | 662 | streamzap_stop_timer(sz); |
730 | 663 | ||
664 | sz->usbdev = NULL; | ||
665 | ir_input_unregister(sz->idev); | ||
666 | usb_kill_urb(sz->urb_in); | ||
731 | usb_free_urb(sz->urb_in); | 667 | usb_free_urb(sz->urb_in); |
668 | usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in); | ||
732 | 669 | ||
733 | usb_free_coherent(sz->udev, sz->buf_in_len, sz->buf_in, sz->dma_in); | ||
734 | |||
735 | minor = sz->driver->minor; | ||
736 | kfree(sz->driver->rbuf); | ||
737 | kfree(sz->driver); | ||
738 | kfree(sz->delay_buf); | ||
739 | kfree(sz); | 670 | kfree(sz); |
740 | |||
741 | printk(KERN_INFO DRIVER_NAME "[%d]: disconnected\n", minor); | ||
742 | } | 671 | } |
743 | 672 | ||
744 | static int streamzap_suspend(struct usb_interface *intf, pm_message_t message) | 673 | static int streamzap_suspend(struct usb_interface *intf, pm_message_t message) |
745 | { | 674 | { |
746 | struct usb_streamzap *sz = usb_get_intfdata(intf); | 675 | struct streamzap_ir *sz = usb_get_intfdata(intf); |
747 | 676 | ||
748 | printk(KERN_INFO DRIVER_NAME "[%d]: suspend\n", sz->driver->minor); | 677 | if (sz->flush) { |
749 | if (sz->in_use) { | 678 | sz->flush = false; |
750 | if (sz->flush) { | 679 | del_timer_sync(&sz->flush_timer); |
751 | sz->flush = 0; | 680 | } |
752 | del_timer_sync(&sz->flush_timer); | ||
753 | } | ||
754 | 681 | ||
755 | stop_timer(sz); | 682 | streamzap_stop_timer(sz); |
683 | |||
684 | usb_kill_urb(sz->urb_in); | ||
756 | 685 | ||
757 | usb_kill_urb(sz->urb_in); | ||
758 | } | ||
759 | return 0; | 686 | return 0; |
760 | } | 687 | } |
761 | 688 | ||
762 | static int streamzap_resume(struct usb_interface *intf) | 689 | static int streamzap_resume(struct usb_interface *intf) |
763 | { | 690 | { |
764 | struct usb_streamzap *sz = usb_get_intfdata(intf); | 691 | struct streamzap_ir *sz = usb_get_intfdata(intf); |
765 | 692 | ||
766 | lirc_buffer_clear(sz->driver->rbuf); | 693 | if (sz->fifo_initialized) |
767 | lirc_buffer_clear(sz->delay_buf); | 694 | kfifo_reset(&sz->fifo); |
768 | 695 | ||
769 | if (sz->in_use) { | 696 | sz->flush_timer.expires = jiffies + HZ; |
770 | sz->flush_timer.expires = jiffies + HZ; | 697 | sz->flush = true; |
771 | sz->flush = 1; | 698 | add_timer(&sz->flush_timer); |
772 | add_timer(&sz->flush_timer); | ||
773 | 699 | ||
774 | sz->urb_in->dev = sz->udev; | 700 | if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { |
775 | if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { | 701 | dev_err(sz->dev, "Error sumbiting urb\n"); |
776 | dprintk("open result = -EIO error submitting urb", | 702 | return -EIO; |
777 | sz->driver->minor); | ||
778 | return -EIO; | ||
779 | } | ||
780 | } | 703 | } |
704 | |||
781 | return 0; | 705 | return 0; |
782 | } | 706 | } |
783 | 707 | ||
784 | /** | 708 | /** |
785 | * usb_streamzap_init | 709 | * streamzap_init |
786 | */ | 710 | */ |
787 | static int __init usb_streamzap_init(void) | 711 | static int __init streamzap_init(void) |
788 | { | 712 | { |
789 | int result; | 713 | int ret; |
790 | 714 | ||
791 | /* register this driver with the USB subsystem */ | 715 | /* register this driver with the USB subsystem */ |
792 | result = usb_register(&streamzap_driver); | 716 | ret = usb_register(&streamzap_driver); |
793 | 717 | if (ret < 0) | |
794 | if (result) { | 718 | printk(KERN_ERR DRIVER_NAME ": usb register failed, " |
795 | err("usb_register failed. Error number %d", | 719 | "result = %d\n", ret); |
796 | result); | ||
797 | return result; | ||
798 | } | ||
799 | 720 | ||
800 | printk(KERN_INFO DRIVER_NAME " " DRIVER_VERSION " registered\n"); | 721 | return ret; |
801 | return 0; | ||
802 | } | 722 | } |
803 | 723 | ||
804 | /** | 724 | /** |
805 | * usb_streamzap_exit | 725 | * streamzap_exit |
806 | */ | 726 | */ |
807 | static void __exit usb_streamzap_exit(void) | 727 | static void __exit streamzap_exit(void) |
808 | { | 728 | { |
809 | usb_deregister(&streamzap_driver); | 729 | usb_deregister(&streamzap_driver); |
810 | } | 730 | } |
811 | 731 | ||
812 | 732 | ||
813 | module_init(usb_streamzap_init); | 733 | module_init(streamzap_init); |
814 | module_exit(usb_streamzap_exit); | 734 | module_exit(streamzap_exit); |
815 | 735 | ||
816 | MODULE_AUTHOR("Christoph Bartelmus, Greg Wickham, Adrian Dewhurst"); | 736 | MODULE_AUTHOR("Jarod Wilson <jarod@wilsonet.com>"); |
817 | MODULE_DESCRIPTION(DRIVER_DESC); | 737 | MODULE_DESCRIPTION(DRIVER_DESC); |
818 | MODULE_LICENSE("GPL"); | 738 | MODULE_LICENSE("GPL"); |
819 | 739 | ||