From 9cc44f3437a256661044bd2f91460dfeefad90a1 Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Wed, 19 Jul 2017 11:58:28 +0200 Subject: [PATCH 1/2] linux: remove lirc-xbox patch Signed-off-by: Matthias Reichl --- .../linux-052-XBOX_remote_support.patch | 1024 ----------------- 1 file changed, 1024 deletions(-) delete mode 100644 packages/linux/patches/default/linux-052-XBOX_remote_support.patch diff --git a/packages/linux/patches/default/linux-052-XBOX_remote_support.patch b/packages/linux/patches/default/linux-052-XBOX_remote_support.patch deleted file mode 100644 index 799da23140..0000000000 --- a/packages/linux/patches/default/linux-052-XBOX_remote_support.patch +++ /dev/null @@ -1,1024 +0,0 @@ -diff --git a/drivers/staging/media/lirc/Kconfig b/drivers/staging/media/lirc/Kconfig -index 3e350a9..935dcc2 100644 ---- a/drivers/staging/media/lirc/Kconfig -+++ b/drivers/staging/media/lirc/Kconfig -@@ -19,3 +19,10 @@ - Driver for the Zilog/Hauppauge IR Transmitter, found on - PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards -+ -+config LIRC_XBOX -+ tristate "XBOX USB IR Remote" -+ depends on LIRC && USB -+ help -+ Driver for the Microsoft XBOX USB IR Remote -+ - endif - -diff --git a/drivers/staging/media/lirc/lirc_xbox.c b/drivers/staging/media/lirc/lirc_xbox.c -new file mode 100644 -index 0000000..c269d5d ---- /dev/null -+++ b/drivers/staging/media/lirc/lirc_xbox.c -@@ -0,0 +1,995 @@ -+/* -+ * lirc_xbox - USB remote support for LIRC -+ * (supports Microsoft XBOX DVD Dongle) -+ * -+ * Copyright (C) 2003-2004 Paul Miller -+ * -+ * This driver was derived from: -+ * Vladimir Dergachev 's 2002 -+ * "USB ATI Remote support" (input device) -+ * Adrian Dewhurst 's 2002 -+ * "USB StreamZap remote driver" (LIRC) -+ * Artur Lipowski 's 2002 -+ * "lirc_dev" and "lirc_gpio" LIRC modules -+ * Michael Wojciechowski -+ * initial xbox support -+ * Vassilis Virvilis 2006 -+ * reworked the patch for lirc submission -+ * Paul Miller's 2004 -+ * lirc_atiusb - removed all ati remote support -+ * $Id: lirc_xbox.c,v 1.88 2011/06/03 11:11:11 jmartin Exp $ -+ */ -+ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+ -+//#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) -+//#include -+//#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+//#include "drivers/kcompat.h" -+//#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) -+#include -+#include -+//#else -+//#include "drivers/lirc.h" -+//#include "drivers/lirc_dev/lirc_dev.h" -+//#endif -+ -+#define DRIVER_VERSION "$Revision: 0.01 $" -+#define DRIVER_AUTHOR "Jason Martin " -+#define DRIVER_DESC "XBOX DVD Dongle USB remote driver for LIRC" -+#define DRIVER_NAME "lirc_xbox" -+ -+#define CODE_LENGTH 6 -+#define CODE_MIN_LENGTH 6 -+#define DECODE_LENGTH 1 -+ -+#ifndef URB_ASYNC_UNLINK -+#define URB_ASYNC_UNLINK 0 -+#endif -+ -+/* module parameters */ -+#ifdef CONFIG_USB_DEBUG -+static int debug = 1; -+#else -+static int debug; -+#endif -+ -+#define dprintk(fmt, args...) \ -+ do { \ -+ if (debug) \ -+ printk(KERN_DEBUG fmt, ## args); \ -+ } while (0) -+ -+/* -+ * USB_BUFF_LEN must be the maximum value of the code_length array. -+ * It is used for static arrays. -+ */ -+#define USB_BUFF_LEN 6 -+ -+static int mask = 0xFFFF; /* channel acceptance bit mask */ -+static int unique; /* enable channel-specific codes */ -+static int repeat = 10; /* repeat time in 1/100 sec */ -+static unsigned long repeat_jiffies; /* repeat timeout */ -+ -+/* get hi and low bytes of a 16-bits int */ -+#define HI(a) ((unsigned char)((a) >> 8)) -+#define LO(a) ((unsigned char)((a) & 0xff)) -+ -+/* general constants */ -+#define SEND_FLAG_IN_PROGRESS 1 -+#define SEND_FLAG_COMPLETE 2 -+#define FREE_ALL 0xFF -+ -+/* endpoints */ -+#define EP_KEYS 0 -+#define EP_MOUSE 1 -+#define EP_MOUSE_ADDR 0x81 -+#define EP_KEYS_ADDR 0x82 -+ -+/* USB vendor ids for XBOX DVD Dongles */ -+#define VENDOR_MS1 0x040b -+#define VENDOR_MS2 0x045e -+#define VENDOR_MS3 0xFFFF -+ -+static struct usb_device_id usb_remote_table[] = { -+ /* Gamester Xbox DVD Movie Playback Kit IR */ -+ { USB_DEVICE(VENDOR_MS1, 0x6521) }, -+ -+ /* Microsoft Xbox DVD Movie Playback Kit IR */ -+ { USB_DEVICE(VENDOR_MS2, 0x0284) }, -+ -+ /* -+ * Some Chinese manufacturer -- conflicts with the joystick from the -+ * same manufacturer -+ */ -+ { USB_DEVICE(VENDOR_MS3, 0xFFFF) }, -+ -+ /* Terminating entry */ -+ { } -+}; -+ -+/* init strings */ -+#define USB_OUTLEN 7 -+ -+static char init1[] = {0x01, 0x00, 0x20, 0x14}; -+static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20}; -+ -+struct in_endpt { -+ /* inner link in list of endpoints for the remote specified by ir */ -+ struct list_head iep_list_link; -+ struct xbox_dev *ir; -+ struct urb *urb; -+ struct usb_endpoint_descriptor *ep; -+ -+ /* buffers and dma */ -+ unsigned char *buf; -+ unsigned int len; -+ dma_addr_t dma; -+ -+ /* handle repeats */ -+ unsigned char old[USB_BUFF_LEN]; -+ unsigned long old_jiffies; -+}; -+ -+struct out_endpt { -+ struct xbox_dev *ir; -+ struct urb *urb; -+ struct usb_endpoint_descriptor *ep; -+ -+ /* buffers and dma */ -+ unsigned char *buf; -+ dma_addr_t dma; -+ -+ /* handle sending (init strings) */ -+ int send_flags; -+ wait_queue_head_t wait; -+}; -+ -+ -+/* data structure for each usb remote */ -+struct xbox_dev { -+ /* inner link in list of all remotes managed by this module */ -+ struct list_head remote_list_link; -+ /* Number of usb interfaces associated with this device */ -+ int dev_refcount; -+ -+ /* usb */ -+ struct usb_device *usbdev; -+ /* Head link to list of all inbound endpoints in this remote */ -+ struct list_head iep_listhead; -+ struct out_endpt *out_init; -+ int devnum; -+ -+ /* lirc */ -+ struct lirc_driver *d; -+ int connected; -+ -+ /* locking */ -+ struct mutex lock; -+}; -+ -+/* list of all registered devices via the remote_list_link in xbox_dev */ -+static struct list_head remote_list; -+ -+/* -+ * Convenience macros to retrieve a pointer to the surrounding struct from -+ * the given list_head reference within, pointed at by link. -+ */ -+#define get_iep_from_link(link) \ -+ list_entry((link), struct in_endpt, iep_list_link); -+#define get_irctl_from_link(link) \ -+ list_entry((link), struct xbox_dev, remote_list_link); -+ -+/* send packet - used to initialize remote */ -+static void send_packet(struct out_endpt *oep, u16 cmd, unsigned char *data) -+{ -+ struct xbox_dev *ir = oep->ir; -+ DECLARE_WAITQUEUE(wait, current); -+ int timeout = HZ; /* 1 second */ -+ unsigned char buf[USB_OUTLEN]; -+ -+ dprintk(DRIVER_NAME "[%d]: send called (%#x)\n", ir->devnum, cmd); -+ -+ mutex_lock(&ir->lock); -+ oep->urb->transfer_buffer_length = LO(cmd) + 1; -+ oep->urb->dev = oep->ir->usbdev; -+ oep->send_flags = SEND_FLAG_IN_PROGRESS; -+ -+ memcpy(buf+1, data, LO(cmd)); -+ buf[0] = HI(cmd); -+ memcpy(oep->buf, buf, LO(cmd)+1); -+ -+ set_current_state(TASK_INTERRUPTIBLE); -+ add_wait_queue(&oep->wait, &wait); -+ -+ if (usb_submit_urb(oep->urb, GFP_ATOMIC)) { -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&oep->wait, &wait); -+ mutex_unlock(&ir->lock); -+ return; -+ } -+ mutex_unlock(&ir->lock); -+ -+ while (timeout && (oep->urb->status == -EINPROGRESS) -+ && !(oep->send_flags & SEND_FLAG_COMPLETE)) { -+ timeout = schedule_timeout(timeout); -+ rmb(); -+ } -+ -+ dprintk(DRIVER_NAME "[%d]: send complete (%#x)\n", ir->devnum, cmd); -+ -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&oep->wait, &wait); -+ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(oep->urb); -+} -+ -+static int unregister_from_lirc(struct xbox_dev *ir) -+{ -+ struct lirc_driver *d = ir->d; -+ int devnum; -+ -+ devnum = ir->devnum; -+ dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); -+ -+ lirc_unregister_driver(d->minor); -+ -+ printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); -+ return 0; -+} -+ -+static int set_use_inc(void *data) -+{ -+ struct xbox_dev *ir = data; -+ struct list_head *pos, *n; -+ struct in_endpt *iep; -+ int rtn; -+ -+ if (!ir) { -+ printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); -+ return -EIO; -+ } -+ dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); -+ -+ mutex_lock(&ir->lock); -+ if (!ir->connected) { -+ if (!ir->usbdev) { -+ mutex_unlock(&ir->lock); -+ dprintk(DRIVER_NAME "[%d]: !ir->usbdev\n", ir->devnum); -+ return -ENOENT; -+ } -+ -+ /* Iterate through the inbound endpoints */ -+ list_for_each_safe(pos, n, &ir->iep_listhead) { -+ /* extract the current in_endpt */ -+ iep = get_iep_from_link(pos); -+ iep->urb->dev = ir->usbdev; -+ dprintk(DRIVER_NAME "[%d]: linking iep 0x%02x (%p)\n", -+ ir->devnum, iep->ep->bEndpointAddress, iep); -+ rtn = usb_submit_urb(iep->urb, GFP_ATOMIC); -+ if (rtn) { -+ printk(DRIVER_NAME "[%d]: open result = %d " -+ "error submitting urb\n", -+ ir->devnum, rtn); -+ mutex_unlock(&ir->lock); -+ return -EIO; -+ } -+ } -+ ir->connected = 1; -+ } -+ mutex_unlock(&ir->lock); -+ -+ return 0; -+} -+ -+static void set_use_dec(void *data) -+{ -+ struct xbox_dev *ir = data; -+ struct list_head *pos, *n; -+ struct in_endpt *iep; -+ -+ if (!ir) { -+ printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); -+ return; -+ } -+ dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); -+ -+ mutex_lock(&ir->lock); -+ if (ir->connected) { -+ /* Free inbound usb urbs */ -+ list_for_each_safe(pos, n, &ir->iep_listhead) { -+ iep = get_iep_from_link(pos); -+ dprintk(DRIVER_NAME "[%d]: unlinking iep 0x%02x (%p)\n", -+ ir->devnum, iep->ep->bEndpointAddress, iep); -+ usb_kill_urb(iep->urb); -+ } -+ ir->connected = 0; -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+static void print_data(struct in_endpt *iep, char *buf, int len) -+{ -+ const int clen = CODE_LENGTH; -+ char codes[clen * 3 + 1]; -+ int i; -+ -+ if (len <= 0) -+ return; -+ -+ for (i = 0; i < len && i < clen; i++) -+ snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF); -+ printk(DRIVER_NAME "[%d]: data received %s (ep=0x%x length=%d)\n", -+ iep->ir->devnum, codes, iep->ep->bEndpointAddress, len); -+} -+ -+static int code_check_xbox(struct in_endpt *iep, int len) -+{ -+ // struct xbox_dev *ir = iep->ir; -+ const int clen = CODE_LENGTH; -+ -+ if (len != clen) { -+ dprintk(DRIVER_NAME ": We got %d instead of %d bytes from xbox " -+ "ir.. ?\n", len, clen); -+ return -1; -+ } -+ -+ /* check for repeats */ -+ if (memcmp(iep->old, iep->buf, len) == 0) { -+ if (iep->old_jiffies + repeat_jiffies > jiffies) -+ return -1; -+ } else { -+ /* -+ * the third byte of xbox ir packet seems to contain key info -+ * the last two bytes are.. some kind of clock? -+ */ -+ iep->buf[0] = iep->buf[2]; -+ memset(iep->buf + 1, 0, len - 1); -+ memcpy(iep->old, iep->buf, len); -+ } -+ iep->old_jiffies = jiffies; -+ -+ return 0; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+static void usb_remote_recv(struct urb *urb, struct pt_regs *regs) -+#else -+static void usb_remote_recv(struct urb *urb) -+#endif -+{ -+ struct in_endpt *iep; -+ int len, result = -1; -+ -+ if (!urb) -+ return; -+ iep = urb->context; -+ if (!iep) { -+ urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(urb); -+ return; -+ } -+ if (!iep->ir->usbdev) -+ return; -+ -+ len = urb->actual_length; -+ if (debug) -+ print_data(iep, urb->transfer_buffer, len); -+ -+ switch (urb->status) { -+ -+ case 0: -+ result = code_check_xbox(iep, len); -+ -+ if (result < 0) -+ break; -+ -+ lirc_buffer_write(iep->ir->d->rbuf, iep->buf); -+ wake_up(&iep->ir->d->rbuf->wait_poll); -+ break; -+ -+ case -ECONNRESET: -+ case -ENOENT: -+ case -ESHUTDOWN: -+ urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(urb); -+ return; -+ -+ case -EPIPE: -+ default: -+ break; -+ } -+ -+ usb_submit_urb(urb, GFP_ATOMIC); -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+static void usb_remote_send(struct urb *urb, struct pt_regs *regs) -+#else -+static void usb_remote_send(struct urb *urb) -+#endif -+{ -+ struct out_endpt *oep; -+ -+ if (!urb) -+ return; -+ oep = urb->context; -+ if (!oep) { -+ urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(urb); -+ return; -+ } -+ if (!oep->ir->usbdev) -+ return; -+ -+ dprintk(DRIVER_NAME "[%d]: usb out called\n", oep->ir->devnum); -+ -+ if (urb->status) -+ return; -+ -+ oep->send_flags |= SEND_FLAG_COMPLETE; -+ wmb(); -+ if (waitqueue_active(&oep->wait)) -+ wake_up(&oep->wait); -+} -+ -+ -+/* -+ * Initialization and removal -+ */ -+ -+/* -+ * Free iep according to mem_failure which specifies a checkpoint into the -+ * initialization sequence for rollback recovery. -+ */ -+static void free_in_endpt(struct in_endpt *iep, int mem_failure) -+{ -+ struct xbox_dev *ir; -+ dprintk(DRIVER_NAME ": free_in_endpt(%p, %d)\n", iep, mem_failure); -+ if (!iep) -+ return; -+ -+ ir = iep->ir; -+ if (!ir) { -+ dprintk(DRIVER_NAME ": free_in_endpt: WARNING! null ir\n"); -+ return; -+ } -+ mutex_lock(&ir->lock); -+ switch (mem_failure) { -+ case FREE_ALL: -+ case 5: -+ list_del(&iep->iep_list_link); -+ dprintk(DRIVER_NAME "[%d]: free_in_endpt removing ep=0x%0x " -+ "from list\n", ir->devnum, iep->ep->bEndpointAddress); -+ case 4: -+ if (iep->urb) { -+ iep->urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(iep->urb); -+ usb_free_urb(iep->urb); -+ iep->urb = 0; -+ } else -+ dprintk(DRIVER_NAME "[%d]: free_in_endpt null urb!\n", -+ ir->devnum); -+ case 3: -+ usb_free_coherent(iep->ir->usbdev, iep->len, iep->buf, iep->dma); -+ iep->buf = 0; -+ case 2: -+ kfree(iep); -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+/* -+ * Construct a new inbound endpoint for this remote, and add it to the list of -+ * in_epts in ir. -+ */ -+static struct in_endpt *new_in_endpt(struct xbox_dev *ir, -+ struct usb_endpoint_descriptor *ep) -+{ -+ struct usb_device *dev = ir->usbdev; -+ struct in_endpt *iep; -+ int pipe, maxp, len, addr; -+ int mem_failure; -+ -+ addr = ep->bEndpointAddress; -+ pipe = usb_rcvintpipe(dev, addr); -+ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); -+ -+/* len = (maxp > USB_BUFLEN) ? USB_BUFLEN : maxp; -+ * len -= (len % CODE_LENGTH); */ -+ len = CODE_LENGTH; -+ -+ dprintk(DRIVER_NAME "[%d]: acceptable inbound endpoint (0x%x) found " -+ "(maxp=%d len=%d)\n", ir->devnum, addr, maxp, len); -+ -+ mem_failure = 0; -+ iep = kzalloc(sizeof(*iep), GFP_KERNEL); -+ if (!iep) { -+ mem_failure = 1; -+ goto new_in_endpt_failure_check; -+ } -+ iep->ir = ir; -+ iep->ep = ep; -+ iep->len = len; -+ -+ iep->buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &iep->dma); -+ if (!iep->buf) { -+ mem_failure = 2; -+ goto new_in_endpt_failure_check; -+ } -+ -+ iep->urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (!iep->urb) -+ mem_failure = 3; -+ -+new_in_endpt_failure_check: -+ -+ if (mem_failure) { -+ free_in_endpt(iep, mem_failure); -+ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", -+ ir->devnum, addr, mem_failure); -+ return NULL; -+ } -+ list_add_tail(&iep->iep_list_link, &ir->iep_listhead); -+ dprintk(DRIVER_NAME "[%d]: adding ep=0x%0x to list\n", -+ ir->devnum, iep->ep->bEndpointAddress); -+ return iep; -+} -+ -+static void free_out_endpt(struct out_endpt *oep, int mem_failure) -+{ -+ struct xbox_dev *ir; -+ dprintk(DRIVER_NAME ": free_out_endpt(%p, %d)\n", oep, mem_failure); -+ if (!oep) -+ return; -+ -+ wake_up_all(&oep->wait); -+ -+ ir = oep->ir; -+ if (!ir) { -+ dprintk(DRIVER_NAME ": free_out_endpt: WARNING! null ir\n"); -+ return; -+ } -+ mutex_lock(&ir->lock); -+ switch (mem_failure) { -+ case FREE_ALL: -+ case 4: -+ if (oep->urb) { -+ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(oep->urb); -+ usb_free_urb(oep->urb); -+ oep->urb = 0; -+ } else { -+ dprintk(DRIVER_NAME "[%d]: free_out_endpt: null urb!\n", -+ ir->devnum); -+ } -+ case 3: -+ usb_free_coherent(oep->ir->usbdev, USB_OUTLEN, -+ oep->buf, oep->dma); -+ oep->buf = 0; -+ case 2: -+ kfree(oep); -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+static struct out_endpt *new_out_endpt(struct xbox_dev *ir, -+ struct usb_endpoint_descriptor *ep) -+{ -+ struct usb_device *dev = ir->usbdev; -+ struct out_endpt *oep; -+ int mem_failure; -+ -+ dprintk(DRIVER_NAME "[%d]: acceptable outbound endpoint (0x%x) found\n", -+ ir->devnum, ep->bEndpointAddress); -+ -+ mem_failure = 0; -+ oep = kzalloc(sizeof(*oep), GFP_KERNEL); -+ if (!oep) -+ mem_failure = 1; -+ else { -+ oep->ir = ir; -+ oep->ep = ep; -+ init_waitqueue_head(&oep->wait); -+ -+ oep->buf = usb_alloc_coherent(dev, USB_OUTLEN, -+ GFP_ATOMIC, &oep->dma); -+ if (!oep->buf) -+ mem_failure = 2; -+ else { -+ oep->urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (!oep->urb) -+ mem_failure = 3; -+ } -+ } -+ if (mem_failure) { -+ free_out_endpt(oep, mem_failure); -+ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", -+ ir->devnum, ep->bEndpointAddress, mem_failure); -+ return NULL; -+ } -+ return oep; -+} -+ -+static void free_irctl(struct xbox_dev *ir, int mem_failure) -+{ -+ struct list_head *pos, *n; -+ struct in_endpt *in; -+ dprintk(DRIVER_NAME ": free_irctl(%p, %d)\n", ir, mem_failure); -+ -+ if (!ir) -+ return; -+ -+ list_for_each_safe(pos, n, &ir->iep_listhead) { -+ in = get_iep_from_link(pos); -+ free_in_endpt(in, FREE_ALL); -+ } -+ if (ir->out_init) { -+ free_out_endpt(ir->out_init, FREE_ALL); -+ ir->out_init = NULL; -+ } -+ -+ mutex_lock(&ir->lock); -+ switch (mem_failure) { -+ case FREE_ALL: -+ case 6: -+ if (!--ir->dev_refcount) { -+ list_del(&ir->remote_list_link); -+ dprintk(DRIVER_NAME "[%d]: free_irctl: removing " -+ "remote from list\n", ir->devnum); -+ } else { -+ dprintk(DRIVER_NAME "[%d]: free_irctl: refcount at %d," -+ "aborting free_irctl\n", -+ ir->devnum, ir->dev_refcount); -+ mutex_unlock(&ir->lock); -+ return; -+ } -+ case 5: -+ case 4: -+ case 3: -+ if (ir->d) { -+ switch (mem_failure) { -+ case 5: -+ lirc_buffer_free(ir->d->rbuf); -+ case 4: -+ kfree(ir->d->rbuf); -+ case 3: -+ kfree(ir->d); -+ } -+ } else -+ printk(DRIVER_NAME "[%d]: ir->d is a null pointer!\n", -+ ir->devnum); -+ case 2: -+ mutex_unlock(&ir->lock); -+ kfree(ir); -+ return; -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+static struct xbox_dev *new_irctl(struct usb_interface *intf) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct xbox_dev *ir; -+ struct lirc_driver *driver; -+ int devnum, dclen; -+ int mem_failure; -+ -+ devnum = dev->devnum; -+ -+ dprintk(DRIVER_NAME "[%d]: remote type = XBOX DVD Dongle\n", devnum); -+ -+ mem_failure = 0; -+ ir = kzalloc(sizeof(*ir), GFP_KERNEL); -+ if (!ir) { -+ mem_failure = 1; -+ goto new_irctl_failure_check; -+ } -+ -+ dclen = DECODE_LENGTH; -+ -+ /* -+ * add this infrared remote struct to remote_list, keeping track -+ * of the number of drivers registered. -+ */ -+ dprintk(DRIVER_NAME "[%d]: adding remote to list\n", devnum); -+ list_add_tail(&ir->remote_list_link, &remote_list); -+ ir->dev_refcount = 1; -+ -+ driver = kzalloc(sizeof(*driver), GFP_KERNEL); -+ if (!driver) { -+ mem_failure = 2; -+ goto new_irctl_failure_check; -+ } -+ -+ ir->d = driver; -+ driver->rbuf = kmalloc(sizeof(*(driver->rbuf)), GFP_KERNEL); -+ if (!driver->rbuf) { -+ mem_failure = 3; -+ goto new_irctl_failure_check; -+ } -+ -+ if (lirc_buffer_init(driver->rbuf, dclen, 2)) { -+ mem_failure = 4; -+ goto new_irctl_failure_check; -+ } -+ -+ strcpy(driver->name, DRIVER_NAME " "); -+ driver->minor = -1; -+ driver->code_length = dclen * 8; -+ driver->features = LIRC_CAN_REC_LIRCCODE; -+ driver->data = ir; -+ driver->set_use_inc = &set_use_inc; -+ driver->set_use_dec = &set_use_dec; -+ driver->dev = &intf->dev; -+ driver->owner = THIS_MODULE; -+ ir->usbdev = dev; -+ ir->devnum = devnum; -+ -+ mutex_init(&ir->lock); -+ INIT_LIST_HEAD(&ir->iep_listhead); -+ -+new_irctl_failure_check: -+ -+ if (mem_failure) { -+ free_irctl(ir, mem_failure); -+ printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", -+ devnum, mem_failure); -+ return NULL; -+ } -+ return ir; -+} -+ -+/* -+ * Scan the global list of remotes to see if the device listed is one of them. -+ * If it is, the corresponding xbox_dev is returned, with its dev_refcount -+ * incremented. Otherwise, returns null. -+ */ -+static struct xbox_dev *get_prior_reg_ir(struct usb_device *dev) -+{ -+ struct list_head *pos; -+ struct xbox_dev *ir = NULL; -+ -+ dprintk(DRIVER_NAME "[%d]: scanning remote_list...\n", dev->devnum); -+ list_for_each(pos, &remote_list) { -+ ir = get_irctl_from_link(pos); -+ if (ir->usbdev != dev) { -+ dprintk(DRIVER_NAME "[%d]: device %d isn't it...", -+ dev->devnum, ir->devnum); -+ ir = NULL; -+ } else { -+ dprintk(DRIVER_NAME "[%d]: prior instance found.\n", -+ dev->devnum); -+ ir->dev_refcount++; -+ break; -+ } -+ } -+ return ir; -+} -+ -+/* -+ * If the USB interface has an out endpoint for control. -+ */ -+static void send_outbound_init(struct xbox_dev *ir) -+{ -+ if (ir->out_init) { -+ struct out_endpt *oep = ir->out_init; -+ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: initializing " -+ "outbound ep\n", ir->devnum); -+ usb_fill_int_urb(oep->urb, ir->usbdev, -+ usb_sndintpipe(ir->usbdev, oep->ep->bEndpointAddress), -+ oep->buf, USB_OUTLEN, usb_remote_send, -+ oep, oep->ep->bInterval); -+ oep->urb->transfer_dma = oep->dma; -+ oep->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -+ -+ send_packet(oep, 0x8004, init1); -+ send_packet(oep, 0x8007, init2); -+ } -+} -+ -+/* Log driver and usb info */ -+static void log_usb_dev_info(struct usb_device *dev) -+{ -+ char buf[63], name[128] = ""; -+ -+ if (dev->descriptor.iManufacturer -+ && usb_string(dev, dev->descriptor.iManufacturer, -+ buf, sizeof(buf)) > 0) -+ strlcpy(name, buf, sizeof(name)); -+ if (dev->descriptor.iProduct -+ && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) -+ snprintf(name + strlen(name), sizeof(name) - strlen(name), -+ " %s", buf); -+ printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", dev->devnum, name, -+ dev->bus->busnum, dev->devnum); -+} -+ -+ -+static int usb_remote_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct usb_host_interface *idesc; -+ struct usb_endpoint_descriptor *ep; -+ struct in_endpt *iep; -+ struct xbox_dev *ir; -+ int i; -+ -+ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: dev:%p, intf:%p, id:%p)\n", -+ dev->devnum, dev, intf, id); -+ -+ idesc = intf->cur_altsetting; -+ -+ /* Check if a usb remote has already been registered for this device */ -+ ir = get_prior_reg_ir(dev); -+ -+ if (!ir) { -+ ir = new_irctl(intf); -+ if (!ir) -+ return -ENOMEM; -+ } -+ -+ /* -+ * step through the endpoints to find first in and first out endpoint -+ * of type interrupt transfer -+ */ -+ for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { -+ ep = &idesc->endpoint[i].desc; -+ dprintk(DRIVER_NAME "[%d]: processing endpoint %d\n", -+ dev->devnum, i); -+ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == -+ USB_DIR_IN) && -+ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == -+ USB_ENDPOINT_XFER_INT)) { -+ -+ iep = new_in_endpt(ir, ep); -+ if (iep) -+ { -+ usb_fill_int_urb(iep->urb, dev, -+ usb_rcvintpipe(dev, -+ iep->ep->bEndpointAddress), -+ iep->buf, iep->len, usb_remote_recv, -+ iep, iep->ep->bInterval); -+ iep->urb->transfer_dma = iep->dma; -+ iep->urb->transfer_flags |= -+ URB_NO_TRANSFER_DMA_MAP; -+ } -+ } -+ -+ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == -+ USB_DIR_OUT) && -+ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == -+ USB_ENDPOINT_XFER_INT) && -+ (ir->out_init == NULL)) -+ ir->out_init = new_out_endpt(ir, ep); -+ } -+ if (list_empty(&ir->iep_listhead)) { -+ printk(DRIVER_NAME "[%d]: inbound endpoint not found\n", -+ ir->devnum); -+ free_irctl(ir, FREE_ALL); -+ return -ENODEV; -+ } -+ if (ir->dev_refcount == 1) { -+ ir->d->minor = lirc_register_driver(ir->d); -+ if (ir->d->minor < 0) { -+ free_irctl(ir, FREE_ALL); -+ return -ENODEV; -+ } -+ -+ /* Note new driver registration in kernel logs */ -+ log_usb_dev_info(dev); -+ -+ /* outbound data (initialization) */ -+ send_outbound_init(ir); -+ } -+ -+ usb_set_intfdata(intf, ir); -+ return 0; -+} -+ -+static void usb_remote_disconnect(struct usb_interface *intf) -+{ -+ /* struct usb_device *dev = interface_to_usbdev(intf); */ -+ struct xbox_dev *ir = usb_get_intfdata(intf); -+ usb_set_intfdata(intf, NULL); -+ -+ dprintk(DRIVER_NAME ": disconnecting remote %d:\n", -+ (ir ? ir->devnum : -1)); -+ if (!ir || !ir->d) -+ return; -+ -+ if (ir->usbdev) { -+ /* Only unregister once */ -+ ir->usbdev = NULL; -+ unregister_from_lirc(ir); -+ } -+ -+ /* This also removes the current remote from remote_list */ -+ free_irctl(ir, FREE_ALL); -+} -+ -+static struct usb_driver usb_remote_driver = { -+ .name = DRIVER_NAME, -+ .probe = usb_remote_probe, -+ .disconnect = usb_remote_disconnect, -+ .id_table = usb_remote_table -+}; -+ -+static int __init usb_remote_init(void) -+{ -+ int i; -+ -+ INIT_LIST_HEAD(&remote_list); -+ -+ printk(KERN_INFO "\n" DRIVER_NAME ": " DRIVER_DESC " " -+ DRIVER_VERSION "\n"); -+ printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); -+ dprintk(DRIVER_NAME ": debug mode enabled: " -+ "$Id: lirc_xbox.c,v 1.88 2011/06/05 11:11:11 jmartin Exp $\n"); -+ -+ repeat_jiffies = repeat*HZ/100; -+ -+ i = usb_register(&usb_remote_driver); -+ if (i) { -+ printk(DRIVER_NAME ": usb register failed, result = %d\n", i); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static void __exit usb_remote_exit(void) -+{ -+ usb_deregister(&usb_remote_driver); -+} -+ -+module_init(usb_remote_init); -+module_exit(usb_remote_exit); -+ -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_AUTHOR(DRIVER_AUTHOR); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(usb, usb_remote_table); -+ -+module_param(debug, uint, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)"); -+ -+module_param(mask, uint, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)"); -+ -+module_param(unique, uint, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)"); -+ -+module_param(repeat, uint, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)"); -diff --git a/drivers/staging/media/lirc/Makefile b/drivers/staging/media/lirc/Makefile -index 6655624..9e9fc05 100644 ---- a/drivers/staging/media/lirc/Makefile -+++ b/drivers/staging/media/lirc/Makefile -@@ -6 +6,2 @@ - obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o -+obj-$(CONFIG_LIRC_XBOX) += lirc_xbox.o From 585ccc8f0f431e6cb4dc78ae35366cce04c318a8 Mon Sep 17 00:00:00 2001 From: Matthias Reichl Date: Wed, 19 Jul 2017 11:59:34 +0200 Subject: [PATCH 2/2] media_build: remove lirc-xbox patch Signed-off-by: Matthias Reichl --- .../media_build-02-add-to-backports.patch | 3 +- .../linux-052-XBOX_remote_support.patch | 1039 ----------------- 2 files changed, 1 insertion(+), 1041 deletions(-) delete mode 100644 packages/linux-drivers/media_build/sources/backports/linux-052-XBOX_remote_support.patch diff --git a/packages/linux-drivers/media_build/patches/media_build-02-add-to-backports.patch b/packages/linux-drivers/media_build/patches/media_build-02-add-to-backports.patch index 58be53948f..dfd0a88c2b 100644 --- a/packages/linux-drivers/media_build/patches/media_build-02-add-to-backports.patch +++ b/packages/linux-drivers/media_build/patches/media_build-02-add-to-backports.patch @@ -1,10 +1,9 @@ --- a/backports/backports.txt +++ b/backports/backports.txt -@@ -25,6 +25,15 @@ add api_version.patch +@@ -25,6 +25,14 @@ add api_version.patch add pr_fmt.patch add debug.patch add drx39xxj.patch -+add linux-052-XBOX_remote_support.patch +add linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch +add linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch +add linux-062-imon_pad_ignore_diagonal.patch diff --git a/packages/linux-drivers/media_build/sources/backports/linux-052-XBOX_remote_support.patch b/packages/linux-drivers/media_build/sources/backports/linux-052-XBOX_remote_support.patch deleted file mode 100644 index 3521d9e86f..0000000000 --- a/packages/linux-drivers/media_build/sources/backports/linux-052-XBOX_remote_support.patch +++ /dev/null @@ -1,1039 +0,0 @@ -Subject: linux-052-XBOX_remote_support updated for kernel 4.11 - -diff --git a/drivers/staging/media/lirc/Kconfig b/drivers/staging/media/lirc/Kconfig -index bc67da2..87d894e 100644 ---- a/drivers/staging/media/lirc/Kconfig -+++ b/drivers/staging/media/lirc/Kconfig -@@ -24,10 +24,17 @@ config LIRC_SIR - help - Driver for the SIR IrDA port - -+config LIRC_XBOX -+ tristate "XBOX USB IR Remote" -+ depends on LIRC && USB -+ help -+ Driver for the Microsoft XBOX USB IR Remote -+ - config LIRC_ZILOG - tristate "Zilog/Hauppauge IR Transmitter" - depends on LIRC && I2C - help - Driver for the Zilog/Hauppauge IR Transmitter, found on - PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards -+ - endif -diff --git a/drivers/staging/media/lirc/Makefile b/drivers/staging/media/lirc/Makefile -index 28740c9..b3e331e4 100644 ---- a/drivers/staging/media/lirc/Makefile -+++ b/drivers/staging/media/lirc/Makefile -@@ -3,4 +3,5 @@ - - # Each configuration option enables a list of files. - -+obj-$(CONFIG_LIRC_XBOX) += lirc_xbox.o - obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o - -diff --git a/drivers/staging/media/lirc/lirc_xbox.c b/drivers/staging/media/lirc/lirc_xbox.c -new file mode 100644 -index 0000000..c269d5d ---- /dev/null -+++ b/drivers/staging/media/lirc/lirc_xbox.c -@@ -0,0 +1,995 @@ -+/* -+ * lirc_xbox - USB remote support for LIRC -+ * (supports Microsoft XBOX DVD Dongle) -+ * -+ * Copyright (C) 2003-2004 Paul Miller -+ * -+ * This driver was derived from: -+ * Vladimir Dergachev 's 2002 -+ * "USB ATI Remote support" (input device) -+ * Adrian Dewhurst 's 2002 -+ * "USB StreamZap remote driver" (LIRC) -+ * Artur Lipowski 's 2002 -+ * "lirc_dev" and "lirc_gpio" LIRC modules -+ * Michael Wojciechowski -+ * initial xbox support -+ * Vassilis Virvilis 2006 -+ * reworked the patch for lirc submission -+ * Paul Miller's 2004 -+ * lirc_atiusb - removed all ati remote support -+ * $Id: lirc_xbox.c,v 1.88 2011/06/03 11:11:11 jmartin Exp $ -+ */ -+ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+ -+//#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) -+//#include -+//#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+//#include "drivers/kcompat.h" -+//#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) -+#include -+#include -+//#else -+//#include "drivers/lirc.h" -+//#include "drivers/lirc_dev/lirc_dev.h" -+//#endif -+ -+#define DRIVER_VERSION "$Revision: 0.01 $" -+#define DRIVER_AUTHOR "Jason Martin " -+#define DRIVER_DESC "XBOX DVD Dongle USB remote driver for LIRC" -+#define DRIVER_NAME "lirc_xbox" -+ -+#define CODE_LENGTH 6 -+#define CODE_MIN_LENGTH 6 -+#define DECODE_LENGTH 1 -+ -+#ifndef URB_ASYNC_UNLINK -+#define URB_ASYNC_UNLINK 0 -+#endif -+ -+/* module parameters */ -+#ifdef CONFIG_USB_DEBUG -+static int debug = 1; -+#else -+static int debug; -+#endif -+ -+#define dprintk(fmt, args...) \ -+ do { \ -+ if (debug) \ -+ printk(KERN_DEBUG fmt, ## args); \ -+ } while (0) -+ -+/* -+ * USB_BUFF_LEN must be the maximum value of the code_length array. -+ * It is used for static arrays. -+ */ -+#define USB_BUFF_LEN 6 -+ -+static int mask = 0xFFFF; /* channel acceptance bit mask */ -+static int unique; /* enable channel-specific codes */ -+static int repeat = 10; /* repeat time in 1/100 sec */ -+static unsigned long repeat_jiffies; /* repeat timeout */ -+ -+/* get hi and low bytes of a 16-bits int */ -+#define HI(a) ((unsigned char)((a) >> 8)) -+#define LO(a) ((unsigned char)((a) & 0xff)) -+ -+/* general constants */ -+#define SEND_FLAG_IN_PROGRESS 1 -+#define SEND_FLAG_COMPLETE 2 -+#define FREE_ALL 0xFF -+ -+/* endpoints */ -+#define EP_KEYS 0 -+#define EP_MOUSE 1 -+#define EP_MOUSE_ADDR 0x81 -+#define EP_KEYS_ADDR 0x82 -+ -+/* USB vendor ids for XBOX DVD Dongles */ -+#define VENDOR_MS1 0x040b -+#define VENDOR_MS2 0x045e -+#define VENDOR_MS3 0xFFFF -+ -+static struct usb_device_id usb_remote_table[] = { -+ /* Gamester Xbox DVD Movie Playback Kit IR */ -+ { USB_DEVICE(VENDOR_MS1, 0x6521) }, -+ -+ /* Microsoft Xbox DVD Movie Playback Kit IR */ -+ { USB_DEVICE(VENDOR_MS2, 0x0284) }, -+ -+ /* -+ * Some Chinese manufacturer -- conflicts with the joystick from the -+ * same manufacturer -+ */ -+ { USB_DEVICE(VENDOR_MS3, 0xFFFF) }, -+ -+ /* Terminating entry */ -+ { } -+}; -+ -+/* init strings */ -+#define USB_OUTLEN 7 -+ -+static char init1[] = {0x01, 0x00, 0x20, 0x14}; -+static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20}; -+ -+struct in_endpt { -+ /* inner link in list of endpoints for the remote specified by ir */ -+ struct list_head iep_list_link; -+ struct xbox_dev *ir; -+ struct urb *urb; -+ struct usb_endpoint_descriptor *ep; -+ -+ /* buffers and dma */ -+ unsigned char *buf; -+ unsigned int len; -+ dma_addr_t dma; -+ -+ /* handle repeats */ -+ unsigned char old[USB_BUFF_LEN]; -+ unsigned long old_jiffies; -+}; -+ -+struct out_endpt { -+ struct xbox_dev *ir; -+ struct urb *urb; -+ struct usb_endpoint_descriptor *ep; -+ -+ /* buffers and dma */ -+ unsigned char *buf; -+ dma_addr_t dma; -+ -+ /* handle sending (init strings) */ -+ int send_flags; -+ wait_queue_head_t wait; -+}; -+ -+ -+/* data structure for each usb remote */ -+struct xbox_dev { -+ /* inner link in list of all remotes managed by this module */ -+ struct list_head remote_list_link; -+ /* Number of usb interfaces associated with this device */ -+ int dev_refcount; -+ -+ /* usb */ -+ struct usb_device *usbdev; -+ /* Head link to list of all inbound endpoints in this remote */ -+ struct list_head iep_listhead; -+ struct out_endpt *out_init; -+ int devnum; -+ -+ /* lirc */ -+ struct lirc_driver *d; -+ int connected; -+ -+ /* locking */ -+ struct mutex lock; -+}; -+ -+/* list of all registered devices via the remote_list_link in xbox_dev */ -+static struct list_head remote_list; -+ -+/* -+ * Convenience macros to retrieve a pointer to the surrounding struct from -+ * the given list_head reference within, pointed at by link. -+ */ -+#define get_iep_from_link(link) \ -+ list_entry((link), struct in_endpt, iep_list_link); -+#define get_irctl_from_link(link) \ -+ list_entry((link), struct xbox_dev, remote_list_link); -+ -+/* send packet - used to initialize remote */ -+static void send_packet(struct out_endpt *oep, u16 cmd, unsigned char *data) -+{ -+ struct xbox_dev *ir = oep->ir; -+ DECLARE_WAITQUEUE(wait, current); -+ int timeout = HZ; /* 1 second */ -+ unsigned char buf[USB_OUTLEN]; -+ -+ dprintk(DRIVER_NAME "[%d]: send called (%#x)\n", ir->devnum, cmd); -+ -+ mutex_lock(&ir->lock); -+ oep->urb->transfer_buffer_length = LO(cmd) + 1; -+ oep->urb->dev = oep->ir->usbdev; -+ oep->send_flags = SEND_FLAG_IN_PROGRESS; -+ -+ memcpy(buf+1, data, LO(cmd)); -+ buf[0] = HI(cmd); -+ memcpy(oep->buf, buf, LO(cmd)+1); -+ -+ set_current_state(TASK_INTERRUPTIBLE); -+ add_wait_queue(&oep->wait, &wait); -+ -+ if (usb_submit_urb(oep->urb, GFP_ATOMIC)) { -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&oep->wait, &wait); -+ mutex_unlock(&ir->lock); -+ return; -+ } -+ mutex_unlock(&ir->lock); -+ -+ while (timeout && (oep->urb->status == -EINPROGRESS) -+ && !(oep->send_flags & SEND_FLAG_COMPLETE)) { -+ timeout = schedule_timeout(timeout); -+ rmb(); -+ } -+ -+ dprintk(DRIVER_NAME "[%d]: send complete (%#x)\n", ir->devnum, cmd); -+ -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&oep->wait, &wait); -+ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(oep->urb); -+} -+ -+static int unregister_from_lirc(struct xbox_dev *ir) -+{ -+ struct lirc_driver *d = ir->d; -+ int devnum; -+ -+ devnum = ir->devnum; -+ dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); -+ -+ lirc_unregister_driver(d->minor); -+ -+ printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); -+ return 0; -+} -+ -+static int set_use_inc(void *data) -+{ -+ struct xbox_dev *ir = data; -+ struct list_head *pos, *n; -+ struct in_endpt *iep; -+ int rtn; -+ -+ if (!ir) { -+ printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); -+ return -EIO; -+ } -+ dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); -+ -+ mutex_lock(&ir->lock); -+ if (!ir->connected) { -+ if (!ir->usbdev) { -+ mutex_unlock(&ir->lock); -+ dprintk(DRIVER_NAME "[%d]: !ir->usbdev\n", ir->devnum); -+ return -ENOENT; -+ } -+ -+ /* Iterate through the inbound endpoints */ -+ list_for_each_safe(pos, n, &ir->iep_listhead) { -+ /* extract the current in_endpt */ -+ iep = get_iep_from_link(pos); -+ iep->urb->dev = ir->usbdev; -+ dprintk(DRIVER_NAME "[%d]: linking iep 0x%02x (%p)\n", -+ ir->devnum, iep->ep->bEndpointAddress, iep); -+ rtn = usb_submit_urb(iep->urb, GFP_ATOMIC); -+ if (rtn) { -+ printk(DRIVER_NAME "[%d]: open result = %d " -+ "error submitting urb\n", -+ ir->devnum, rtn); -+ mutex_unlock(&ir->lock); -+ return -EIO; -+ } -+ } -+ ir->connected = 1; -+ } -+ mutex_unlock(&ir->lock); -+ -+ return 0; -+} -+ -+static void set_use_dec(void *data) -+{ -+ struct xbox_dev *ir = data; -+ struct list_head *pos, *n; -+ struct in_endpt *iep; -+ -+ if (!ir) { -+ printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); -+ return; -+ } -+ dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); -+ -+ mutex_lock(&ir->lock); -+ if (ir->connected) { -+ /* Free inbound usb urbs */ -+ list_for_each_safe(pos, n, &ir->iep_listhead) { -+ iep = get_iep_from_link(pos); -+ dprintk(DRIVER_NAME "[%d]: unlinking iep 0x%02x (%p)\n", -+ ir->devnum, iep->ep->bEndpointAddress, iep); -+ usb_kill_urb(iep->urb); -+ } -+ ir->connected = 0; -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+static void print_data(struct in_endpt *iep, char *buf, int len) -+{ -+ const int clen = CODE_LENGTH; -+ char codes[clen * 3 + 1]; -+ int i; -+ -+ if (len <= 0) -+ return; -+ -+ for (i = 0; i < len && i < clen; i++) -+ snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF); -+ printk(DRIVER_NAME "[%d]: data received %s (ep=0x%x length=%d)\n", -+ iep->ir->devnum, codes, iep->ep->bEndpointAddress, len); -+} -+ -+static int code_check_xbox(struct in_endpt *iep, int len) -+{ -+ // struct xbox_dev *ir = iep->ir; -+ const int clen = CODE_LENGTH; -+ -+ if (len != clen) { -+ dprintk(DRIVER_NAME ": We got %d instead of %d bytes from xbox " -+ "ir.. ?\n", len, clen); -+ return -1; -+ } -+ -+ /* check for repeats */ -+ if (memcmp(iep->old, iep->buf, len) == 0) { -+ if (iep->old_jiffies + repeat_jiffies > jiffies) -+ return -1; -+ } else { -+ /* -+ * the third byte of xbox ir packet seems to contain key info -+ * the last two bytes are.. some kind of clock? -+ */ -+ iep->buf[0] = iep->buf[2]; -+ memset(iep->buf + 1, 0, len - 1); -+ memcpy(iep->old, iep->buf, len); -+ } -+ iep->old_jiffies = jiffies; -+ -+ return 0; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+static void usb_remote_recv(struct urb *urb, struct pt_regs *regs) -+#else -+static void usb_remote_recv(struct urb *urb) -+#endif -+{ -+ struct in_endpt *iep; -+ int len, result = -1; -+ -+ if (!urb) -+ return; -+ iep = urb->context; -+ if (!iep) { -+ urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(urb); -+ return; -+ } -+ if (!iep->ir->usbdev) -+ return; -+ -+ len = urb->actual_length; -+ if (debug) -+ print_data(iep, urb->transfer_buffer, len); -+ -+ switch (urb->status) { -+ -+ case 0: -+ result = code_check_xbox(iep, len); -+ -+ if (result < 0) -+ break; -+ -+ lirc_buffer_write(iep->ir->d->rbuf, iep->buf); -+ wake_up(&iep->ir->d->rbuf->wait_poll); -+ break; -+ -+ case -ECONNRESET: -+ case -ENOENT: -+ case -ESHUTDOWN: -+ urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(urb); -+ return; -+ -+ case -EPIPE: -+ default: -+ break; -+ } -+ -+ usb_submit_urb(urb, GFP_ATOMIC); -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+static void usb_remote_send(struct urb *urb, struct pt_regs *regs) -+#else -+static void usb_remote_send(struct urb *urb) -+#endif -+{ -+ struct out_endpt *oep; -+ -+ if (!urb) -+ return; -+ oep = urb->context; -+ if (!oep) { -+ urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(urb); -+ return; -+ } -+ if (!oep->ir->usbdev) -+ return; -+ -+ dprintk(DRIVER_NAME "[%d]: usb out called\n", oep->ir->devnum); -+ -+ if (urb->status) -+ return; -+ -+ oep->send_flags |= SEND_FLAG_COMPLETE; -+ wmb(); -+ if (waitqueue_active(&oep->wait)) -+ wake_up(&oep->wait); -+} -+ -+ -+/* -+ * Initialization and removal -+ */ -+ -+/* -+ * Free iep according to mem_failure which specifies a checkpoint into the -+ * initialization sequence for rollback recovery. -+ */ -+static void free_in_endpt(struct in_endpt *iep, int mem_failure) -+{ -+ struct xbox_dev *ir; -+ dprintk(DRIVER_NAME ": free_in_endpt(%p, %d)\n", iep, mem_failure); -+ if (!iep) -+ return; -+ -+ ir = iep->ir; -+ if (!ir) { -+ dprintk(DRIVER_NAME ": free_in_endpt: WARNING! null ir\n"); -+ return; -+ } -+ mutex_lock(&ir->lock); -+ switch (mem_failure) { -+ case FREE_ALL: -+ case 5: -+ list_del(&iep->iep_list_link); -+ dprintk(DRIVER_NAME "[%d]: free_in_endpt removing ep=0x%0x " -+ "from list\n", ir->devnum, iep->ep->bEndpointAddress); -+ case 4: -+ if (iep->urb) { -+ iep->urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(iep->urb); -+ usb_free_urb(iep->urb); -+ iep->urb = 0; -+ } else -+ dprintk(DRIVER_NAME "[%d]: free_in_endpt null urb!\n", -+ ir->devnum); -+ case 3: -+ usb_free_coherent(iep->ir->usbdev, iep->len, iep->buf, iep->dma); -+ iep->buf = 0; -+ case 2: -+ kfree(iep); -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+/* -+ * Construct a new inbound endpoint for this remote, and add it to the list of -+ * in_epts in ir. -+ */ -+static struct in_endpt *new_in_endpt(struct xbox_dev *ir, -+ struct usb_endpoint_descriptor *ep) -+{ -+ struct usb_device *dev = ir->usbdev; -+ struct in_endpt *iep; -+ int pipe, maxp, len, addr; -+ int mem_failure; -+ -+ addr = ep->bEndpointAddress; -+ pipe = usb_rcvintpipe(dev, addr); -+ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); -+ -+/* len = (maxp > USB_BUFLEN) ? USB_BUFLEN : maxp; -+ * len -= (len % CODE_LENGTH); */ -+ len = CODE_LENGTH; -+ -+ dprintk(DRIVER_NAME "[%d]: acceptable inbound endpoint (0x%x) found " -+ "(maxp=%d len=%d)\n", ir->devnum, addr, maxp, len); -+ -+ mem_failure = 0; -+ iep = kzalloc(sizeof(*iep), GFP_KERNEL); -+ if (!iep) { -+ mem_failure = 1; -+ goto new_in_endpt_failure_check; -+ } -+ iep->ir = ir; -+ iep->ep = ep; -+ iep->len = len; -+ -+ iep->buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &iep->dma); -+ if (!iep->buf) { -+ mem_failure = 2; -+ goto new_in_endpt_failure_check; -+ } -+ -+ iep->urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (!iep->urb) -+ mem_failure = 3; -+ -+new_in_endpt_failure_check: -+ -+ if (mem_failure) { -+ free_in_endpt(iep, mem_failure); -+ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", -+ ir->devnum, addr, mem_failure); -+ return NULL; -+ } -+ list_add_tail(&iep->iep_list_link, &ir->iep_listhead); -+ dprintk(DRIVER_NAME "[%d]: adding ep=0x%0x to list\n", -+ ir->devnum, iep->ep->bEndpointAddress); -+ return iep; -+} -+ -+static void free_out_endpt(struct out_endpt *oep, int mem_failure) -+{ -+ struct xbox_dev *ir; -+ dprintk(DRIVER_NAME ": free_out_endpt(%p, %d)\n", oep, mem_failure); -+ if (!oep) -+ return; -+ -+ wake_up_all(&oep->wait); -+ -+ ir = oep->ir; -+ if (!ir) { -+ dprintk(DRIVER_NAME ": free_out_endpt: WARNING! null ir\n"); -+ return; -+ } -+ mutex_lock(&ir->lock); -+ switch (mem_failure) { -+ case FREE_ALL: -+ case 4: -+ if (oep->urb) { -+ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(oep->urb); -+ usb_free_urb(oep->urb); -+ oep->urb = 0; -+ } else { -+ dprintk(DRIVER_NAME "[%d]: free_out_endpt: null urb!\n", -+ ir->devnum); -+ } -+ case 3: -+ usb_free_coherent(oep->ir->usbdev, USB_OUTLEN, -+ oep->buf, oep->dma); -+ oep->buf = 0; -+ case 2: -+ kfree(oep); -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+static struct out_endpt *new_out_endpt(struct xbox_dev *ir, -+ struct usb_endpoint_descriptor *ep) -+{ -+ struct usb_device *dev = ir->usbdev; -+ struct out_endpt *oep; -+ int mem_failure; -+ -+ dprintk(DRIVER_NAME "[%d]: acceptable outbound endpoint (0x%x) found\n", -+ ir->devnum, ep->bEndpointAddress); -+ -+ mem_failure = 0; -+ oep = kzalloc(sizeof(*oep), GFP_KERNEL); -+ if (!oep) -+ mem_failure = 1; -+ else { -+ oep->ir = ir; -+ oep->ep = ep; -+ init_waitqueue_head(&oep->wait); -+ -+ oep->buf = usb_alloc_coherent(dev, USB_OUTLEN, -+ GFP_ATOMIC, &oep->dma); -+ if (!oep->buf) -+ mem_failure = 2; -+ else { -+ oep->urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (!oep->urb) -+ mem_failure = 3; -+ } -+ } -+ if (mem_failure) { -+ free_out_endpt(oep, mem_failure); -+ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", -+ ir->devnum, ep->bEndpointAddress, mem_failure); -+ return NULL; -+ } -+ return oep; -+} -+ -+static void free_irctl(struct xbox_dev *ir, int mem_failure) -+{ -+ struct list_head *pos, *n; -+ struct in_endpt *in; -+ dprintk(DRIVER_NAME ": free_irctl(%p, %d)\n", ir, mem_failure); -+ -+ if (!ir) -+ return; -+ -+ list_for_each_safe(pos, n, &ir->iep_listhead) { -+ in = get_iep_from_link(pos); -+ free_in_endpt(in, FREE_ALL); -+ } -+ if (ir->out_init) { -+ free_out_endpt(ir->out_init, FREE_ALL); -+ ir->out_init = NULL; -+ } -+ -+ mutex_lock(&ir->lock); -+ switch (mem_failure) { -+ case FREE_ALL: -+ case 6: -+ if (!--ir->dev_refcount) { -+ list_del(&ir->remote_list_link); -+ dprintk(DRIVER_NAME "[%d]: free_irctl: removing " -+ "remote from list\n", ir->devnum); -+ } else { -+ dprintk(DRIVER_NAME "[%d]: free_irctl: refcount at %d," -+ "aborting free_irctl\n", -+ ir->devnum, ir->dev_refcount); -+ mutex_unlock(&ir->lock); -+ return; -+ } -+ case 5: -+ case 4: -+ case 3: -+ if (ir->d) { -+ switch (mem_failure) { -+ case 5: -+ lirc_buffer_free(ir->d->rbuf); -+ case 4: -+ kfree(ir->d->rbuf); -+ case 3: -+ kfree(ir->d); -+ } -+ } else -+ printk(DRIVER_NAME "[%d]: ir->d is a null pointer!\n", -+ ir->devnum); -+ case 2: -+ mutex_unlock(&ir->lock); -+ kfree(ir); -+ return; -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+static struct xbox_dev *new_irctl(struct usb_interface *intf) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct xbox_dev *ir; -+ struct lirc_driver *driver; -+ int devnum, dclen; -+ int mem_failure; -+ -+ devnum = dev->devnum; -+ -+ dprintk(DRIVER_NAME "[%d]: remote type = XBOX DVD Dongle\n", devnum); -+ -+ mem_failure = 0; -+ ir = kzalloc(sizeof(*ir), GFP_KERNEL); -+ if (!ir) { -+ mem_failure = 1; -+ goto new_irctl_failure_check; -+ } -+ -+ dclen = DECODE_LENGTH; -+ -+ /* -+ * add this infrared remote struct to remote_list, keeping track -+ * of the number of drivers registered. -+ */ -+ dprintk(DRIVER_NAME "[%d]: adding remote to list\n", devnum); -+ list_add_tail(&ir->remote_list_link, &remote_list); -+ ir->dev_refcount = 1; -+ -+ driver = kzalloc(sizeof(*driver), GFP_KERNEL); -+ if (!driver) { -+ mem_failure = 2; -+ goto new_irctl_failure_check; -+ } -+ -+ ir->d = driver; -+ driver->rbuf = kmalloc(sizeof(*(driver->rbuf)), GFP_KERNEL); -+ if (!driver->rbuf) { -+ mem_failure = 3; -+ goto new_irctl_failure_check; -+ } -+ -+ if (lirc_buffer_init(driver->rbuf, dclen, 2)) { -+ mem_failure = 4; -+ goto new_irctl_failure_check; -+ } -+ -+ strcpy(driver->name, DRIVER_NAME " "); -+ driver->minor = -1; -+ driver->code_length = dclen * 8; -+ driver->features = LIRC_CAN_REC_LIRCCODE; -+ driver->data = ir; -+ driver->set_use_inc = &set_use_inc; -+ driver->set_use_dec = &set_use_dec; -+ driver->dev = &intf->dev; -+ driver->owner = THIS_MODULE; -+ ir->usbdev = dev; -+ ir->devnum = devnum; -+ -+ mutex_init(&ir->lock); -+ INIT_LIST_HEAD(&ir->iep_listhead); -+ -+new_irctl_failure_check: -+ -+ if (mem_failure) { -+ free_irctl(ir, mem_failure); -+ printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", -+ devnum, mem_failure); -+ return NULL; -+ } -+ return ir; -+} -+ -+/* -+ * Scan the global list of remotes to see if the device listed is one of them. -+ * If it is, the corresponding xbox_dev is returned, with its dev_refcount -+ * incremented. Otherwise, returns null. -+ */ -+static struct xbox_dev *get_prior_reg_ir(struct usb_device *dev) -+{ -+ struct list_head *pos; -+ struct xbox_dev *ir = NULL; -+ -+ dprintk(DRIVER_NAME "[%d]: scanning remote_list...\n", dev->devnum); -+ list_for_each(pos, &remote_list) { -+ ir = get_irctl_from_link(pos); -+ if (ir->usbdev != dev) { -+ dprintk(DRIVER_NAME "[%d]: device %d isn't it...", -+ dev->devnum, ir->devnum); -+ ir = NULL; -+ } else { -+ dprintk(DRIVER_NAME "[%d]: prior instance found.\n", -+ dev->devnum); -+ ir->dev_refcount++; -+ break; -+ } -+ } -+ return ir; -+} -+ -+/* -+ * If the USB interface has an out endpoint for control. -+ */ -+static void send_outbound_init(struct xbox_dev *ir) -+{ -+ if (ir->out_init) { -+ struct out_endpt *oep = ir->out_init; -+ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: initializing " -+ "outbound ep\n", ir->devnum); -+ usb_fill_int_urb(oep->urb, ir->usbdev, -+ usb_sndintpipe(ir->usbdev, oep->ep->bEndpointAddress), -+ oep->buf, USB_OUTLEN, usb_remote_send, -+ oep, oep->ep->bInterval); -+ oep->urb->transfer_dma = oep->dma; -+ oep->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -+ -+ send_packet(oep, 0x8004, init1); -+ send_packet(oep, 0x8007, init2); -+ } -+} -+ -+/* Log driver and usb info */ -+static void log_usb_dev_info(struct usb_device *dev) -+{ -+ char buf[63], name[128] = ""; -+ -+ if (dev->descriptor.iManufacturer -+ && usb_string(dev, dev->descriptor.iManufacturer, -+ buf, sizeof(buf)) > 0) -+ strlcpy(name, buf, sizeof(name)); -+ if (dev->descriptor.iProduct -+ && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) -+ snprintf(name + strlen(name), sizeof(name) - strlen(name), -+ " %s", buf); -+ printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", dev->devnum, name, -+ dev->bus->busnum, dev->devnum); -+} -+ -+ -+static int usb_remote_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct usb_host_interface *idesc; -+ struct usb_endpoint_descriptor *ep; -+ struct in_endpt *iep; -+ struct xbox_dev *ir; -+ int i; -+ -+ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: dev:%p, intf:%p, id:%p)\n", -+ dev->devnum, dev, intf, id); -+ -+ idesc = intf->cur_altsetting; -+ -+ /* Check if a usb remote has already been registered for this device */ -+ ir = get_prior_reg_ir(dev); -+ -+ if (!ir) { -+ ir = new_irctl(intf); -+ if (!ir) -+ return -ENOMEM; -+ } -+ -+ /* -+ * step through the endpoints to find first in and first out endpoint -+ * of type interrupt transfer -+ */ -+ for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { -+ ep = &idesc->endpoint[i].desc; -+ dprintk(DRIVER_NAME "[%d]: processing endpoint %d\n", -+ dev->devnum, i); -+ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == -+ USB_DIR_IN) && -+ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == -+ USB_ENDPOINT_XFER_INT)) { -+ -+ iep = new_in_endpt(ir, ep); -+ if (iep) -+ { -+ usb_fill_int_urb(iep->urb, dev, -+ usb_rcvintpipe(dev, -+ iep->ep->bEndpointAddress), -+ iep->buf, iep->len, usb_remote_recv, -+ iep, iep->ep->bInterval); -+ iep->urb->transfer_dma = iep->dma; -+ iep->urb->transfer_flags |= -+ URB_NO_TRANSFER_DMA_MAP; -+ } -+ } -+ -+ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == -+ USB_DIR_OUT) && -+ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == -+ USB_ENDPOINT_XFER_INT) && -+ (ir->out_init == NULL)) -+ ir->out_init = new_out_endpt(ir, ep); -+ } -+ if (list_empty(&ir->iep_listhead)) { -+ printk(DRIVER_NAME "[%d]: inbound endpoint not found\n", -+ ir->devnum); -+ free_irctl(ir, FREE_ALL); -+ return -ENODEV; -+ } -+ if (ir->dev_refcount == 1) { -+ ir->d->minor = lirc_register_driver(ir->d); -+ if (ir->d->minor < 0) { -+ free_irctl(ir, FREE_ALL); -+ return -ENODEV; -+ } -+ -+ /* Note new driver registration in kernel logs */ -+ log_usb_dev_info(dev); -+ -+ /* outbound data (initialization) */ -+ send_outbound_init(ir); -+ } -+ -+ usb_set_intfdata(intf, ir); -+ return 0; -+} -+ -+static void usb_remote_disconnect(struct usb_interface *intf) -+{ -+ /* struct usb_device *dev = interface_to_usbdev(intf); */ -+ struct xbox_dev *ir = usb_get_intfdata(intf); -+ usb_set_intfdata(intf, NULL); -+ -+ dprintk(DRIVER_NAME ": disconnecting remote %d:\n", -+ (ir ? ir->devnum : -1)); -+ if (!ir || !ir->d) -+ return; -+ -+ if (ir->usbdev) { -+ /* Only unregister once */ -+ ir->usbdev = NULL; -+ unregister_from_lirc(ir); -+ } -+ -+ /* This also removes the current remote from remote_list */ -+ free_irctl(ir, FREE_ALL); -+} -+ -+static struct usb_driver usb_remote_driver = { -+ .name = DRIVER_NAME, -+ .probe = usb_remote_probe, -+ .disconnect = usb_remote_disconnect, -+ .id_table = usb_remote_table -+}; -+ -+static int __init usb_remote_init(void) -+{ -+ int i; -+ -+ INIT_LIST_HEAD(&remote_list); -+ -+ printk(KERN_INFO "\n" DRIVER_NAME ": " DRIVER_DESC " " -+ DRIVER_VERSION "\n"); -+ printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); -+ dprintk(DRIVER_NAME ": debug mode enabled: " -+ "$Id: lirc_xbox.c,v 1.88 2011/06/05 11:11:11 jmartin Exp $\n"); -+ -+ repeat_jiffies = repeat*HZ/100; -+ -+ i = usb_register(&usb_remote_driver); -+ if (i) { -+ printk(DRIVER_NAME ": usb register failed, result = %d\n", i); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static void __exit usb_remote_exit(void) -+{ -+ usb_deregister(&usb_remote_driver); -+} -+ -+module_init(usb_remote_init); -+module_exit(usb_remote_exit); -+ -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_AUTHOR(DRIVER_AUTHOR); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(usb, usb_remote_table); -+ -+module_param(debug, uint, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)"); -+ -+module_param(mask, uint, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)"); -+ -+module_param(unique, uint, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)"); -+ -+module_param(repeat, uint, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)"); --- -2.7.4 -