Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff -uNr '--exclude=.git' a/configure.ac b/configure.ac
- --- a/configure.ac 2014-05-29 10:43:54.035853702 -0700
- +++ b/configure.ac 2014-05-29 10:44:17.687692495 -0700
- @@ -175,7 +175,8 @@
- (lirc_dev lirc_sasem) \
- (lirc_dev lirc_serial) \
- (lirc_dev lirc_sir) \
- - (lirc_dev lirc_wpc8769l)"
- + (lirc_dev lirc_wpc8769l) \
- + (lirc_dev lirc_xbox)"
- fi
- AH_TEMPLATE([DAEMONIZE],
- @@ -458,7 +459,7 @@
- srm7500libusb, tekram,
- tekram_bt829, tira, tira_raw, ttusbir,
- tuxbox, tvbox, udp, uirt2, uirt2_raw,
- - usb_uirt_raw, usbx, wpc8769l],
- + usb_uirt_raw, usbx, wpc8769l, xbox],
- driver=${withval},
- driver="unset"
- )
- @@ -623,6 +624,8 @@
- ;;
- lirc_dev-lirc_wpc8769l)
- ;;
- + lirc_dev-lirc_xbox)
- + ;;
- lirc_flyvideo)
- ;;
- livedrive_midi)
- @@ -1420,6 +1423,10 @@
- lircd_conf="acer/lircd.conf.Aspire_6530G"
- fi
- +if test "$driver" = "xbox"; then
- + lirc_driver="lirc_dev lirc_xbox"
- + lircd_conf="xbox/lircd.conf.xbox"
- +fi
- #END HARDWARE HEURISTIC
- @@ -1526,7 +1533,8 @@
- lirc_serial \
- lirc_sir \
- lirc_ttusbir \
- - lirc_wpc8769l"
- + lirc_wpc8769l \
- + lirc_xbox"
- fi
- if kernel_module=$(expr "$lirc_driver" : 'lirc_dev \(.*\)'); then
- :
- @@ -1815,6 +1823,7 @@
- drivers/lirc_serial/Makefile
- drivers/lirc_sir/Makefile
- drivers/lirc_wpc8769l/Makefile
- + drivers/lirc_xbox/Makefile
- daemons/Makefile
- tools/Makefile
- doc/Makefile
- diff -uNr '--exclude=.git' a/drivers/lirc_xbox/lirc_xbox.c b/drivers/lirc_xbox/lirc_xbox.c
- --- a/drivers/lirc_xbox/lirc_xbox.c 1969-12-31 16:00:00.000000000 -0800
- +++ b/drivers/lirc_xbox/lirc_xbox.c 2014-05-29 10:55:21.474041862 -0700
- @@ -0,0 +1,992 @@
- +/*
- + * lirc_xbox - USB remote support for LIRC
- + * (supports Microsoft XBOX DVD Dongle)
- + *
- + * Copyright (C) 2003-2004 Paul Miller <pmiller9@users.sourceforge.net>
- + *
- + * This driver was derived from:
- + * Vladimir Dergachev <volodya@minspring.com>'s 2002
- + * "USB ATI Remote support" (input device)
- + * Adrian Dewhurst <sailor-lk@sailorfrag.net>'s 2002
- + * "USB StreamZap remote driver" (LIRC)
- + * Artur Lipowski <alipowski@kki.net.pl>'s 2002
- + * "lirc_dev" and "lirc_gpio" LIRC modules
- + * Michael Wojciechowski
- + * initial xbox support
- + * Vassilis Virvilis <vasvir@iit.demokritos.gr> 2006
- + * reworked the patch for lirc submission
- + * Paul Miller's <pmiller9@users.sourceforge.net> 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 <linux/version.h>
- +
- +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
- +#include <linux/autoconf.h>
- +#endif
- +
- +#include <linux/kernel.h>
- +#include <linux/errno.h>
- +#include <linux/init.h>
- +#include <linux/slab.h>
- +#include <linux/module.h>
- +#include <linux/kmod.h>
- +#include <linux/completion.h>
- +#include <linux/uaccess.h>
- +#include <linux/usb.h>
- +#include <linux/poll.h>
- +#include <linux/wait.h>
- +#include <linux/list.h>
- +
- +#include "drivers/kcompat.h"
- +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
- +#include <media/lirc.h>
- +#include <media/lirc_dev.h>
- +#else
- +#include "drivers/lirc.h"
- +#include "drivers/lirc_dev/lirc_dev.h"
- +#endif
- +
- +#define DRIVER_VERSION "$Revision: 0.01 $"
- +#define DRIVER_AUTHOR "Jason Martin <austinspartan@users.sourceforge.net>"
- +#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
- +
- +/* 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 = {
- + LIRC_THIS_MODULE(.owner = THIS_MODULE)
- + .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, bool, S_IRUGO | S_IWUSR);
- +MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)");
- +
- +module_param(mask, int, S_IRUGO | S_IWUSR);
- +MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)");
- +
- +module_param(unique, bool, S_IRUGO | S_IWUSR);
- +MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)");
- +
- +module_param(repeat, int, S_IRUGO | S_IWUSR);
- +MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)");
- diff -uNr '--exclude=.git' a/drivers/lirc_xbox/Makefile.am b/drivers/lirc_xbox/Makefile.am
- --- a/drivers/lirc_xbox/Makefile.am 1969-12-31 16:00:00.000000000 -0800
- +++ b/drivers/lirc_xbox/Makefile.am 2014-05-29 10:43:01.608195797 -0700
- @@ -0,0 +1,13 @@
- +## $Id: Makefile.am,v 1.3 2004/04/25 16:29:24 lirc Exp $
- +
- +## Process this file with automake to produce Makefile.in
- +
- +## this is so that Automake includes the C compiling definitions, and
- +## includes the source files in the distribution.
- +EXTRA_PROGRAMS = automake_dummy
- +automake_dummy_SOURCES = lirc_xbox.c
- +
- +## there is no *just* object file support in automake. This is close enough
- +module_DATA = lirc_xbox.o
- +
- +include ../Makefile.common
- \ No newline at end of file
- diff -uNr '--exclude=.git' a/remotes/xbox/lircd.conf.xbox b/remotes/xbox/lircd.conf.xbox
- --- a/remotes/xbox/lircd.conf.xbox 1969-12-31 16:00:00.000000000 -0800
- +++ b/remotes/xbox/lircd.conf.xbox 2014-05-29 10:43:21.564068151 -0700
- @@ -0,0 +1,58 @@
- +#lirc.conf.xbox
- +# Please make this file available to others
- +# by sending it to <lirc@bartelmus.de>
- +#
- +# this config file was automatically generated
- +# using lirc-0.8.2-CVS(default) on Mon Aug 25 09:04:22 2008
- +#
- +# contributed by
- +#
- +# brand: xbox.conf
- +# model no. of remote control:
- +# devices being controlled by this remote:
- +#
- +
- +begin remote
- +
- + name xbox.conf
- + bits 8
- + eps 30
- + aeps 100
- +
- + one 0 0
- + zero 0 0
- + gap 163983
- + min_repeat 15
- + toggle_bit_mask 0x0
- +
- + begin codes
- + MENU 0xF7
- + DISPLAY 0xD5
- + TITLE 0xE5
- + INFO 0xC3
- + EXIT 0xD8
- + UP 0xA6
- + DOWN 0xA7
- + LEFT 0xA9
- + RIGHT 0xA8
- + SELECT 0x0B
- + SKIP- 0xDD
- + SKIP+ 0xDF
- + REW 0xE2
- + FF 0xE3
- + STOP 0xE0
- + 1 0xCE
- + 2 0xCD
- + PAUSE 0xE6
- + PLAY 0xEA
- + 3 0xCC
- + 4 0xCB
- + 5 0xCA
- + 6 0xC9
- + 7 0xC8
- + 8 0xC7
- + 9 0xC6
- + 0 0xCF
- + end codes
- +
- +end remote
- diff -uNr '--exclude=.git' a/setup.data b/setup.data
- --- a/setup.data 2014-05-29 10:43:54.071853460 -0700
- +++ b/setup.data 2014-05-29 10:50:20.324812924 -0700
- @@ -146,6 +146,7 @@
- usb_uirt_raw: "USB-UIRT"
- mplay: "VLSystem MPlay Blast"
- mplay: "VLSystem MPlay Mini"
- + xbox: "XBOX DVD Dongle"
- param_type: \
- act200l \
- @@ -260,7 +261,8 @@
- ttusbir \
- tvbox \
- udp \
- - wpc8769l
- + wpc8769l \
- + xbox
- none:
- default_param: \
- @@ -331,7 +333,8 @@
- ttusbir \
- tvbox \
- udp \
- - wpc8769l
- + wpc8769l \
- + xbox
- none:
- default_param: \
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement