• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/media/IR/
1/*
2 * Streamzap Remote Control driver
3 *
4 * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de>
5 * Copyright (c) 2010 Jarod Wilson <jarod@wilsonet.com>
6 *
7 * This driver was based on the work of Greg Wickham and Adrian
8 * Dewhurst. It was substantially rewritten to support correct signal
9 * gaps and now maintains a delay buffer, which is used to present
10 * consistent timing behaviour to user space applications. Without the
11 * delay buffer an ugly hack would be required in lircd, which can
12 * cause sluggish signal decoding in certain situations.
13 *
14 * Ported to in-kernel ir-core interface by Jarod Wilson
15 *
16 * This driver is based on the USB skeleton driver packaged with the
17 * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
18 *
19 *  This program is free software; you can redistribute it and/or modify
20 *  it under the terms of the GNU General Public License as published by
21 *  the Free Software Foundation; either version 2 of the License, or
22 *  (at your option) any later version.
23 *
24 *  This program is distributed in the hope that it will be useful,
25 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
26 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27 *  GNU General Public License for more details.
28 *
29 *  You should have received a copy of the GNU General Public License
30 *  along with this program; if not, write to the Free Software
31 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
32 */
33
34#include <linux/device.h>
35#include <linux/module.h>
36#include <linux/slab.h>
37#include <linux/usb.h>
38#include <linux/input.h>
39#include <media/ir-core.h>
40
41#define DRIVER_VERSION	"1.60"
42#define DRIVER_NAME	"streamzap"
43#define DRIVER_DESC	"Streamzap Remote Control driver"
44
45#ifdef CONFIG_USB_DEBUG
46static int debug = 1;
47#else
48static int debug;
49#endif
50
51#define USB_STREAMZAP_VENDOR_ID		0x0e9c
52#define USB_STREAMZAP_PRODUCT_ID	0x0000
53
54/* table of devices that work with this driver */
55static struct usb_device_id streamzap_table[] = {
56	/* Streamzap Remote Control */
57	{ USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) },
58	/* Terminating entry */
59	{ }
60};
61
62MODULE_DEVICE_TABLE(usb, streamzap_table);
63
64#define STREAMZAP_PULSE_MASK 0xf0
65#define STREAMZAP_SPACE_MASK 0x0f
66#define STREAMZAP_TIMEOUT    0xff
67#define STREAMZAP_RESOLUTION 256
68
69/* number of samples buffered */
70#define SZ_BUF_LEN 128
71
72enum StreamzapDecoderState {
73	PulseSpace,
74	FullPulse,
75	FullSpace,
76	IgnorePulse
77};
78
79/* structure to hold our device specific stuff */
80struct streamzap_ir {
81
82	/* ir-core */
83	struct ir_dev_props *props;
84	struct ir_raw_event rawir;
85
86	/* core device info */
87	struct device *dev;
88	struct input_dev *idev;
89
90	/* usb */
91	struct usb_device	*usbdev;
92	struct usb_interface	*interface;
93	struct usb_endpoint_descriptor *endpoint;
94	struct urb		*urb_in;
95
96	/* buffer & dma */
97	unsigned char		*buf_in;
98	dma_addr_t		dma_in;
99	unsigned int		buf_in_len;
100
101	/* timer used to support delay buffering */
102	struct timer_list	delay_timer;
103	bool			timer_running;
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;
111
112	/* track what state we're in */
113	enum StreamzapDecoderState decoder_state;
114	/* tracks whether we are currently receiving some signal */
115	bool			idle;
116	/* sum of signal lengths received since signal start */
117	unsigned long		sum;
118	/* start time of signal; necessary for gap tracking */
119	struct timeval		signal_last;
120	struct timeval		signal_start;
121	/* bool			timeout_enabled; */
122
123	char			name[128];
124	char			phys[64];
125};
126
127
128/* local function prototypes */
129static int streamzap_probe(struct usb_interface *interface,
130			   const struct usb_device_id *id);
131static void streamzap_disconnect(struct usb_interface *interface);
132static void streamzap_callback(struct urb *urb);
133static int streamzap_suspend(struct usb_interface *intf, pm_message_t message);
134static int streamzap_resume(struct usb_interface *intf);
135
136/* usb specific object needed to register this driver with the usb subsystem */
137static struct usb_driver streamzap_driver = {
138	.name =		DRIVER_NAME,
139	.probe =	streamzap_probe,
140	.disconnect =	streamzap_disconnect,
141	.suspend =	streamzap_suspend,
142	.resume =	streamzap_resume,
143	.id_table =	streamzap_table,
144};
145
146static void streamzap_stop_timer(struct streamzap_ir *sz)
147{
148	unsigned long flags;
149
150	spin_lock_irqsave(&sz->timer_lock, flags);
151	if (sz->timer_running) {
152		sz->timer_running = false;
153		spin_unlock_irqrestore(&sz->timer_lock, flags);
154		del_timer_sync(&sz->delay_timer);
155	} else {
156		spin_unlock_irqrestore(&sz->timer_lock, flags);
157	}
158}
159
160static void streamzap_flush_timeout(unsigned long arg)
161{
162	struct streamzap_ir *sz = (struct streamzap_ir *)arg;
163
164	dev_info(sz->dev, "%s: callback firing\n", __func__);
165
166	/* finally start accepting data */
167	sz->flush = false;
168}
169
170static void streamzap_delay_timeout(unsigned long arg)
171{
172	struct streamzap_ir *sz = (struct streamzap_ir *)arg;
173	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
174	unsigned long flags;
175	int len, ret;
176	static unsigned long delay;
177	bool wake = false;
178
179	/* deliver data every 10 ms */
180	delay = msecs_to_jiffies(10);
181
182	spin_lock_irqsave(&sz->timer_lock, flags);
183
184	if (kfifo_len(&sz->fifo) > 0) {
185		ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
186		if (ret != sizeof(rawir))
187			dev_err(sz->dev, "Problem w/kfifo_out...\n");
188		ir_raw_event_store(sz->idev, &rawir);
189		wake = true;
190	}
191
192	len = kfifo_len(&sz->fifo);
193	if (len > 0) {
194		while ((len < SZ_BUF_LEN / 2) &&
195		       (len < SZ_BUF_LEN * sizeof(int))) {
196			ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
197			if (ret != sizeof(rawir))
198				dev_err(sz->dev, "Problem w/kfifo_out...\n");
199			ir_raw_event_store(sz->idev, &rawir);
200			wake = true;
201			len = kfifo_len(&sz->fifo);
202		}
203		if (sz->timer_running)
204			mod_timer(&sz->delay_timer, jiffies + delay);
205
206	} else {
207		sz->timer_running = false;
208	}
209
210	if (wake)
211		ir_raw_event_handle(sz->idev);
212
213	spin_unlock_irqrestore(&sz->timer_lock, flags);
214}
215
216static void streamzap_flush_delay_buffer(struct streamzap_ir *sz)
217{
218	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
219	bool wake = false;
220	int ret;
221
222	while (kfifo_len(&sz->fifo) > 0) {
223		ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
224		if (ret != sizeof(rawir))
225			dev_err(sz->dev, "Problem w/kfifo_out...\n");
226		ir_raw_event_store(sz->idev, &rawir);
227		wake = true;
228	}
229
230	if (wake)
231		ir_raw_event_handle(sz->idev);
232}
233
234static void sz_push(struct streamzap_ir *sz)
235{
236	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
237	unsigned long flags;
238	int ret;
239
240	spin_lock_irqsave(&sz->timer_lock, flags);
241	if (kfifo_len(&sz->fifo) >= sizeof(int) * SZ_BUF_LEN) {
242		ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
243		if (ret != sizeof(rawir))
244			dev_err(sz->dev, "Problem w/kfifo_out...\n");
245		ir_raw_event_store(sz->idev, &rawir);
246	}
247
248	kfifo_in(&sz->fifo, &sz->rawir, sizeof(rawir));
249
250	if (!sz->timer_running) {
251		sz->delay_timer.expires = jiffies + (HZ / 10);
252		add_timer(&sz->delay_timer);
253		sz->timer_running = true;
254	}
255
256	spin_unlock_irqrestore(&sz->timer_lock, flags);
257}
258
259static void sz_push_full_pulse(struct streamzap_ir *sz,
260			       unsigned char value)
261{
262	if (sz->idle) {
263		long deltv;
264
265		sz->signal_last = sz->signal_start;
266		do_gettimeofday(&sz->signal_start);
267
268		deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec;
269		sz->rawir.pulse = false;
270		if (deltv > 15) {
271			/* really long time */
272			sz->rawir.duration = IR_MAX_DURATION;
273		} else {
274			sz->rawir.duration = (int)(deltv * 1000000 +
275				sz->signal_start.tv_usec -
276				sz->signal_last.tv_usec);
277			sz->rawir.duration -= sz->sum;
278			sz->rawir.duration *= 1000;
279			sz->rawir.duration &= IR_MAX_DURATION;
280		}
281		dev_dbg(sz->dev, "ls %u\n", sz->rawir.duration);
282		sz_push(sz);
283
284		sz->idle = 0;
285		sz->sum = 0;
286	}
287
288	sz->rawir.pulse = true;
289	sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION;
290	sz->rawir.duration += STREAMZAP_RESOLUTION / 2;
291	sz->sum += sz->rawir.duration;
292	sz->rawir.duration *= 1000;
293	sz->rawir.duration &= IR_MAX_DURATION;
294	dev_dbg(sz->dev, "p %u\n", sz->rawir.duration);
295	sz_push(sz);
296}
297
298static void sz_push_half_pulse(struct streamzap_ir *sz,
299			       unsigned char value)
300{
301	sz_push_full_pulse(sz, (value & STREAMZAP_PULSE_MASK) >> 4);
302}
303
304static void sz_push_full_space(struct streamzap_ir *sz,
305			       unsigned char value)
306{
307	sz->rawir.pulse = false;
308	sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION;
309	sz->rawir.duration += STREAMZAP_RESOLUTION / 2;
310	sz->sum += sz->rawir.duration;
311	sz->rawir.duration *= 1000;
312	dev_dbg(sz->dev, "s %u\n", sz->rawir.duration);
313	sz_push(sz);
314}
315
316static void sz_push_half_space(struct streamzap_ir *sz,
317			       unsigned long value)
318{
319	sz_push_full_space(sz, value & STREAMZAP_SPACE_MASK);
320}
321
322/**
323 * streamzap_callback - usb IRQ handler callback
324 *
325 * This procedure is invoked on reception of data from
326 * the usb remote.
327 */
328static void streamzap_callback(struct urb *urb)
329{
330	struct streamzap_ir *sz;
331	unsigned int i;
332	int len;
333
334	if (!urb)
335		return;
336
337	sz = urb->context;
338	len = urb->actual_length;
339
340	switch (urb->status) {
341	case -ECONNRESET:
342	case -ENOENT:
343	case -ESHUTDOWN:
344		/*
345		 * this urb is terminated, clean up.
346		 * sz might already be invalid at this point
347		 */
348		dev_err(sz->dev, "urb terminated, status: %d\n", urb->status);
349		return;
350	default:
351		break;
352	}
353
354	dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
355	if (!sz->flush) {
356		for (i = 0; i < urb->actual_length; i++) {
357			dev_dbg(sz->dev, "%d: %x\n", i,
358				(unsigned char)sz->buf_in[i]);
359			switch (sz->decoder_state) {
360			case PulseSpace:
361				if ((sz->buf_in[i] & STREAMZAP_PULSE_MASK) ==
362				    STREAMZAP_PULSE_MASK) {
363					sz->decoder_state = FullPulse;
364					continue;
365				} else if ((sz->buf_in[i] & STREAMZAP_SPACE_MASK)
366					   == STREAMZAP_SPACE_MASK) {
367					sz_push_half_pulse(sz, sz->buf_in[i]);
368					sz->decoder_state = FullSpace;
369					continue;
370				} else {
371					sz_push_half_pulse(sz, sz->buf_in[i]);
372					sz_push_half_space(sz, sz->buf_in[i]);
373				}
374				break;
375			case FullPulse:
376				sz_push_full_pulse(sz, sz->buf_in[i]);
377				sz->decoder_state = IgnorePulse;
378				break;
379			case FullSpace:
380				if (sz->buf_in[i] == STREAMZAP_TIMEOUT) {
381					sz->idle = 1;
382					streamzap_stop_timer(sz);
383					streamzap_flush_delay_buffer(sz);
384				} else
385					sz_push_full_space(sz, sz->buf_in[i]);
386				sz->decoder_state = PulseSpace;
387				break;
388			case IgnorePulse:
389				if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) ==
390				    STREAMZAP_SPACE_MASK) {
391					sz->decoder_state = FullSpace;
392					continue;
393				}
394				sz_push_half_space(sz, sz->buf_in[i]);
395				sz->decoder_state = PulseSpace;
396				break;
397			}
398		}
399	}
400
401	usb_submit_urb(urb, GFP_ATOMIC);
402
403	return;
404}
405
406static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz)
407{
408	struct input_dev *idev;
409	struct ir_dev_props *props;
410	struct device *dev = sz->dev;
411	int ret;
412
413	idev = input_allocate_device();
414	if (!idev) {
415		dev_err(dev, "remote input dev allocation failed\n");
416		goto idev_alloc_failed;
417	}
418
419	props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
420	if (!props) {
421		dev_err(dev, "remote ir dev props allocation failed\n");
422		goto props_alloc_failed;
423	}
424
425	snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared "
426		 "Receiver (%04x:%04x)",
427		 le16_to_cpu(sz->usbdev->descriptor.idVendor),
428		 le16_to_cpu(sz->usbdev->descriptor.idProduct));
429
430	idev->name = sz->name;
431	usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys));
432	strlcat(sz->phys, "/input0", sizeof(sz->phys));
433	idev->phys = sz->phys;
434
435	props->priv = sz;
436	props->driver_type = RC_DRIVER_IR_RAW;
437	props->allowed_protos = IR_TYPE_RC5 | IR_TYPE_RC6;
438
439	sz->props = props;
440
441	ret = ir_input_register(idev, RC_MAP_RC5_STREAMZAP, props, DRIVER_NAME);
442	if (ret < 0) {
443		dev_err(dev, "remote input device register failed\n");
444		goto irdev_failed;
445	}
446
447	return idev;
448
449irdev_failed:
450	kfree(props);
451props_alloc_failed:
452	input_free_device(idev);
453idev_alloc_failed:
454	return NULL;
455}
456
457static int streamzap_delay_buf_init(struct streamzap_ir *sz)
458{
459	int ret;
460
461	ret = kfifo_alloc(&sz->fifo, sizeof(int) * SZ_BUF_LEN,
462			  GFP_KERNEL);
463	if (ret == 0)
464		sz->fifo_initialized = 1;
465
466	return ret;
467}
468
469static void streamzap_start_flush_timer(struct streamzap_ir *sz)
470{
471	sz->flush_timer.expires = jiffies + HZ;
472	sz->flush = true;
473	add_timer(&sz->flush_timer);
474
475	sz->urb_in->dev = sz->usbdev;
476	if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
477		dev_err(sz->dev, "urb submit failed\n");
478}
479
480/**
481 *	streamzap_probe
482 *
483 *	Called by usb-core to associated with a candidate device
484 *	On any failure the return value is the ERROR
485 *	On success return 0
486 */
487static int __devinit streamzap_probe(struct usb_interface *intf,
488				     const struct usb_device_id *id)
489{
490	struct usb_device *usbdev = interface_to_usbdev(intf);
491	struct usb_host_interface *iface_host;
492	struct streamzap_ir *sz = NULL;
493	char buf[63], name[128] = "";
494	int retval = -ENOMEM;
495	int pipe, maxp;
496
497	/* Allocate space for device driver specific data */
498	sz = kzalloc(sizeof(struct streamzap_ir), GFP_KERNEL);
499	if (!sz)
500		return -ENOMEM;
501
502	sz->usbdev = usbdev;
503	sz->interface = intf;
504
505	/* Check to ensure endpoint information matches requirements */
506	iface_host = intf->cur_altsetting;
507
508	if (iface_host->desc.bNumEndpoints != 1) {
509		dev_err(&intf->dev, "%s: Unexpected desc.bNumEndpoints (%d)\n",
510			__func__, iface_host->desc.bNumEndpoints);
511		retval = -ENODEV;
512		goto free_sz;
513	}
514
515	sz->endpoint = &(iface_host->endpoint[0].desc);
516	if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
517	    != USB_DIR_IN) {
518		dev_err(&intf->dev, "%s: endpoint doesn't match input device "
519			"02%02x\n", __func__, sz->endpoint->bEndpointAddress);
520		retval = -ENODEV;
521		goto free_sz;
522	}
523
524	if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
525	    != USB_ENDPOINT_XFER_INT) {
526		dev_err(&intf->dev, "%s: endpoint attributes don't match xfer "
527			"02%02x\n", __func__, sz->endpoint->bmAttributes);
528		retval = -ENODEV;
529		goto free_sz;
530	}
531
532	pipe = usb_rcvintpipe(usbdev, sz->endpoint->bEndpointAddress);
533	maxp = usb_maxpacket(usbdev, pipe, usb_pipeout(pipe));
534
535	if (maxp == 0) {
536		dev_err(&intf->dev, "%s: endpoint Max Packet Size is 0!?!\n",
537			__func__);
538		retval = -ENODEV;
539		goto free_sz;
540	}
541
542	/* Allocate the USB buffer and IRQ URB */
543	sz->buf_in = usb_alloc_coherent(usbdev, maxp, GFP_ATOMIC, &sz->dma_in);
544	if (!sz->buf_in)
545		goto free_sz;
546
547	sz->urb_in = usb_alloc_urb(0, GFP_KERNEL);
548	if (!sz->urb_in)
549		goto free_buf_in;
550
551	sz->dev = &intf->dev;
552	sz->buf_in_len = maxp;
553
554	if (usbdev->descriptor.iManufacturer
555	    && usb_string(usbdev, usbdev->descriptor.iManufacturer,
556			  buf, sizeof(buf)) > 0)
557		strlcpy(name, buf, sizeof(name));
558
559	if (usbdev->descriptor.iProduct
560	    && usb_string(usbdev, usbdev->descriptor.iProduct,
561			  buf, sizeof(buf)) > 0)
562		snprintf(name + strlen(name), sizeof(name) - strlen(name),
563			 " %s", buf);
564
565	retval = streamzap_delay_buf_init(sz);
566	if (retval) {
567		dev_err(&intf->dev, "%s: delay buffer init failed\n", __func__);
568		goto free_urb_in;
569	}
570
571	sz->idev = streamzap_init_input_dev(sz);
572	if (!sz->idev)
573		goto input_dev_fail;
574
575	sz->idle = true;
576	sz->decoder_state = PulseSpace;
577
578	init_timer(&sz->delay_timer);
579	sz->delay_timer.function = streamzap_delay_timeout;
580	sz->delay_timer.data = (unsigned long)sz;
581	spin_lock_init(&sz->timer_lock);
582
583	init_timer(&sz->flush_timer);
584	sz->flush_timer.function = streamzap_flush_timeout;
585	sz->flush_timer.data = (unsigned long)sz;
586
587	do_gettimeofday(&sz->signal_start);
588
589	/* Complete final initialisations */
590	usb_fill_int_urb(sz->urb_in, usbdev, pipe, sz->buf_in,
591			 maxp, (usb_complete_t)streamzap_callback,
592			 sz, sz->endpoint->bInterval);
593	sz->urb_in->transfer_dma = sz->dma_in;
594	sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
595
596	usb_set_intfdata(intf, sz);
597
598	streamzap_start_flush_timer(sz);
599
600	dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
601		 usbdev->bus->busnum, usbdev->devnum);
602
603	return 0;
604
605input_dev_fail:
606	kfifo_free(&sz->fifo);
607free_urb_in:
608	usb_free_urb(sz->urb_in);
609free_buf_in:
610	usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in);
611free_sz:
612	kfree(sz);
613
614	return retval;
615}
616
617/**
618 * streamzap_disconnect
619 *
620 * Called by the usb core when the device is removed from the system.
621 *
622 * This routine guarantees that the driver will not submit any more urbs
623 * by clearing dev->usbdev.  It is also supposed to terminate any currently
624 * active urbs.  Unfortunately, usb_bulk_msg(), used in streamzap_read(),
625 * does not provide any way to do this.
626 */
627static void streamzap_disconnect(struct usb_interface *interface)
628{
629	struct streamzap_ir *sz = usb_get_intfdata(interface);
630	struct usb_device *usbdev = interface_to_usbdev(interface);
631
632	usb_set_intfdata(interface, NULL);
633
634	if (!sz)
635		return;
636
637	if (sz->flush) {
638		sz->flush = false;
639		del_timer_sync(&sz->flush_timer);
640	}
641
642	streamzap_stop_timer(sz);
643
644	sz->usbdev = NULL;
645	ir_input_unregister(sz->idev);
646	usb_kill_urb(sz->urb_in);
647	usb_free_urb(sz->urb_in);
648	usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
649
650	kfree(sz);
651}
652
653static int streamzap_suspend(struct usb_interface *intf, pm_message_t message)
654{
655	struct streamzap_ir *sz = usb_get_intfdata(intf);
656
657	if (sz->flush) {
658		sz->flush = false;
659		del_timer_sync(&sz->flush_timer);
660	}
661
662	streamzap_stop_timer(sz);
663
664	usb_kill_urb(sz->urb_in);
665
666	return 0;
667}
668
669static int streamzap_resume(struct usb_interface *intf)
670{
671	struct streamzap_ir *sz = usb_get_intfdata(intf);
672
673	if (sz->fifo_initialized)
674		kfifo_reset(&sz->fifo);
675
676	sz->flush_timer.expires = jiffies + HZ;
677	sz->flush = true;
678	add_timer(&sz->flush_timer);
679
680	if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
681		dev_err(sz->dev, "Error sumbiting urb\n");
682		return -EIO;
683	}
684
685	return 0;
686}
687
688/**
689 *	streamzap_init
690 */
691static int __init streamzap_init(void)
692{
693	int ret;
694
695	/* register this driver with the USB subsystem */
696	ret = usb_register(&streamzap_driver);
697	if (ret < 0)
698		printk(KERN_ERR DRIVER_NAME ": usb register failed, "
699		       "result = %d\n", ret);
700
701	return ret;
702}
703
704/**
705 *	streamzap_exit
706 */
707static void __exit streamzap_exit(void)
708{
709	usb_deregister(&streamzap_driver);
710}
711
712
713module_init(streamzap_init);
714module_exit(streamzap_exit);
715
716MODULE_AUTHOR("Jarod Wilson <jarod@wilsonet.com>");
717MODULE_DESCRIPTION(DRIVER_DESC);
718MODULE_LICENSE("GPL");
719
720module_param(debug, bool, S_IRUGO | S_IWUSR);
721MODULE_PARM_DESC(debug, "Enable debugging messages");
722