Advertisement
Guest User

Untitled

a guest
May 29th, 2014
293
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 31.12 KB | None | 0 0
  1. diff -uNr '--exclude=.git' a/configure.ac b/configure.ac
  2. --- a/configure.ac  2014-05-29 10:43:54.035853702 -0700
  3. +++ b/configure.ac  2014-05-29 10:44:17.687692495 -0700
  4. @@ -175,7 +175,8 @@
  5.          (lirc_dev lirc_sasem) \
  6.          (lirc_dev lirc_serial) \
  7.          (lirc_dev lirc_sir) \
  8. -        (lirc_dev lirc_wpc8769l)"
  9. +        (lirc_dev lirc_wpc8769l) \
  10. +        (lirc_dev lirc_xbox)"
  11.  fi
  12.  
  13.  AH_TEMPLATE([DAEMONIZE],
  14. @@ -458,7 +459,7 @@
  15.                            srm7500libusb, tekram,
  16.                            tekram_bt829, tira, tira_raw, ttusbir,
  17.                            tuxbox, tvbox, udp, uirt2, uirt2_raw,
  18. -                          usb_uirt_raw, usbx, wpc8769l],
  19. +                          usb_uirt_raw, usbx, wpc8769l, xbox],
  20.  driver=${withval},
  21.  driver="unset"
  22.  )
  23. @@ -623,6 +624,8 @@
  24.                  ;;
  25.          lirc_dev-lirc_wpc8769l)
  26.                  ;;
  27. +        lirc_dev-lirc_xbox)
  28. +                ;;
  29.          lirc_flyvideo)
  30.                  ;;
  31.          livedrive_midi)
  32. @@ -1420,6 +1423,10 @@
  33.    lircd_conf="acer/lircd.conf.Aspire_6530G"
  34.  fi
  35.  
  36. +if test "$driver" = "xbox"; then
  37. +  lirc_driver="lirc_dev lirc_xbox"
  38. +  lircd_conf="xbox/lircd.conf.xbox"
  39. +fi
  40.  
  41.  #END HARDWARE HEURISTIC
  42.  
  43. @@ -1526,7 +1533,8 @@
  44.          lirc_serial \
  45.          lirc_sir \
  46.          lirc_ttusbir \
  47. -        lirc_wpc8769l"
  48. +        lirc_wpc8769l \
  49. +        lirc_xbox"
  50.  fi
  51.  if kernel_module=$(expr "$lirc_driver" : 'lirc_dev \(.*\)'); then
  52.    :
  53. @@ -1815,6 +1823,7 @@
  54.    drivers/lirc_serial/Makefile
  55.    drivers/lirc_sir/Makefile
  56.    drivers/lirc_wpc8769l/Makefile
  57. +  drivers/lirc_xbox/Makefile
  58.    daemons/Makefile
  59.    tools/Makefile
  60.    doc/Makefile
  61. diff -uNr '--exclude=.git' a/drivers/lirc_xbox/lirc_xbox.c b/drivers/lirc_xbox/lirc_xbox.c
  62. --- a/drivers/lirc_xbox/lirc_xbox.c 1969-12-31 16:00:00.000000000 -0800
  63. +++ b/drivers/lirc_xbox/lirc_xbox.c 2014-05-29 10:55:21.474041862 -0700
  64. @@ -0,0 +1,992 @@
  65. +/*
  66. + * lirc_xbox - USB remote support for LIRC
  67. + * (supports Microsoft XBOX DVD Dongle)
  68. + *
  69. + * Copyright (C) 2003-2004 Paul Miller <pmiller9@users.sourceforge.net>
  70. + *
  71. + * This driver was derived from:
  72. + *   Vladimir Dergachev <volodya@minspring.com>'s 2002
  73. + *      "USB ATI Remote support" (input device)
  74. + *   Adrian Dewhurst <sailor-lk@sailorfrag.net>'s 2002
  75. + *      "USB StreamZap remote driver" (LIRC)
  76. + *   Artur Lipowski <alipowski@kki.net.pl>'s 2002
  77. + *      "lirc_dev" and "lirc_gpio" LIRC modules
  78. + *   Michael Wojciechowski
  79. + *      initial xbox support
  80. + *   Vassilis Virvilis <vasvir@iit.demokritos.gr> 2006
  81. + *      reworked the patch for lirc submission
  82. + *   Paul Miller's <pmiller9@users.sourceforge.net> 2004
  83. + *      lirc_atiusb - removed all ati remote support
  84. + * $Id: lirc_xbox.c,v 1.88 2011/06/03 11:11:11 jmartin Exp $
  85. + */
  86. +
  87. +/*
  88. + * This program is free software; you can redistribute it and/or modify
  89. + * it under the terms of the GNU General Public License as published by
  90. + * the Free Software Foundation; either version 2 of the License, or
  91. + * (at your option) any later version.
  92. + *
  93. + * This program is distributed in the hope that it will be useful,
  94. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  95. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  96. + * GNU General Public License for more details.
  97. + *
  98. + * You should have received a copy of the GNU General Public License
  99. + * along with this program; if not, write to the Free Software
  100. + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  101. + */
  102. +
  103. +#include <linux/version.h>
  104. +
  105. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
  106. +#include <linux/autoconf.h>
  107. +#endif
  108. +
  109. +#include <linux/kernel.h>
  110. +#include <linux/errno.h>
  111. +#include <linux/init.h>
  112. +#include <linux/slab.h>
  113. +#include <linux/module.h>
  114. +#include <linux/kmod.h>
  115. +#include <linux/completion.h>
  116. +#include <linux/uaccess.h>
  117. +#include <linux/usb.h>
  118. +#include <linux/poll.h>
  119. +#include <linux/wait.h>
  120. +#include <linux/list.h>
  121. +
  122. +#include "drivers/kcompat.h"
  123. +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35)
  124. +#include <media/lirc.h>
  125. +#include <media/lirc_dev.h>
  126. +#else
  127. +#include "drivers/lirc.h"
  128. +#include "drivers/lirc_dev/lirc_dev.h"
  129. +#endif
  130. +
  131. +#define DRIVER_VERSION     "$Revision: 0.01 $"
  132. +#define DRIVER_AUTHOR      "Jason Martin <austinspartan@users.sourceforge.net>"
  133. +#define DRIVER_DESC        "XBOX DVD Dongle USB remote driver for LIRC"
  134. +#define DRIVER_NAME        "lirc_xbox"
  135. +
  136. +#define CODE_LENGTH        6
  137. +#define CODE_MIN_LENGTH        6
  138. +#define DECODE_LENGTH      1
  139. +
  140. +/* module parameters */
  141. +#ifdef CONFIG_USB_DEBUG
  142. +static int debug = 1;
  143. +#else
  144. +static int debug;
  145. +#endif
  146. +
  147. +#define dprintk(fmt, args...)                  \
  148. +   do {                            \
  149. +       if (debug)                  \
  150. +           printk(KERN_DEBUG fmt, ## args);    \
  151. +   } while (0)
  152. +
  153. +/*
  154. + * USB_BUFF_LEN must be the maximum value of the code_length array.
  155. + * It is used for static arrays.
  156. + */
  157. +#define USB_BUFF_LEN 6
  158. +
  159. +static int mask = 0xFFFF;  /* channel acceptance bit mask */
  160. +static int unique;     /* enable channel-specific codes */
  161. +static int repeat = 10;        /* repeat time in 1/100 sec */
  162. +static unsigned long repeat_jiffies; /* repeat timeout */
  163. +
  164. +/* get hi and low bytes of a 16-bits int */
  165. +#define HI(a)          ((unsigned char)((a) >> 8))
  166. +#define LO(a)          ((unsigned char)((a) & 0xff))
  167. +
  168. +/* general constants */
  169. +#define SEND_FLAG_IN_PROGRESS  1
  170. +#define SEND_FLAG_COMPLETE 2
  171. +#define FREE_ALL       0xFF
  172. +
  173. +/* endpoints */
  174. +#define EP_KEYS            0
  175. +#define EP_MOUSE       1
  176. +#define EP_MOUSE_ADDR      0x81
  177. +#define EP_KEYS_ADDR       0x82
  178. +
  179. +/* USB vendor ids for XBOX DVD Dongles */
  180. +#define VENDOR_MS1     0x040b
  181. +#define VENDOR_MS2     0x045e
  182. +#define VENDOR_MS3     0xFFFF
  183. +
  184. +static struct usb_device_id usb_remote_table[] = {
  185. +   /* Gamester Xbox DVD Movie Playback Kit IR */
  186. +   { USB_DEVICE(VENDOR_MS1, 0x6521) },
  187. +
  188. +   /* Microsoft Xbox DVD Movie Playback Kit IR */
  189. +   { USB_DEVICE(VENDOR_MS2, 0x0284) },
  190. +
  191. +   /*
  192. +    * Some Chinese manufacturer -- conflicts with the joystick from the
  193. +    * same manufacturer
  194. +    */
  195. +   { USB_DEVICE(VENDOR_MS3, 0xFFFF) },
  196. +
  197. +   /* Terminating entry */
  198. +   { }
  199. +};
  200. +
  201. +/* init strings */
  202. +#define USB_OUTLEN     7
  203. +
  204. +static char init1[] = {0x01, 0x00, 0x20, 0x14};
  205. +static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20};
  206. +
  207. +struct in_endpt {
  208. +   /* inner link in list of endpoints for the remote specified by ir */
  209. +   struct list_head iep_list_link;
  210. +   struct xbox_dev *ir;
  211. +   struct urb *urb;
  212. +   struct usb_endpoint_descriptor *ep;
  213. +
  214. +   /* buffers and dma */
  215. +   unsigned char *buf;
  216. +   unsigned int len;
  217. +   dma_addr_t dma;
  218. +
  219. +   /* handle repeats */
  220. +   unsigned char old[USB_BUFF_LEN];
  221. +   unsigned long old_jiffies;
  222. +};
  223. +
  224. +struct out_endpt {
  225. +   struct xbox_dev *ir;
  226. +   struct urb *urb;
  227. +   struct usb_endpoint_descriptor *ep;
  228. +
  229. +   /* buffers and dma */
  230. +   unsigned char *buf;
  231. +   dma_addr_t dma;
  232. +
  233. +   /* handle sending (init strings) */
  234. +   int send_flags;
  235. +   wait_queue_head_t wait;
  236. +};
  237. +
  238. +
  239. +/* data structure for each usb remote */
  240. +struct xbox_dev {
  241. +   /* inner link in list of all remotes managed by this module */
  242. +   struct list_head remote_list_link;
  243. +   /* Number of usb interfaces associated with this device */
  244. +   int dev_refcount;
  245. +
  246. +   /* usb */
  247. +   struct usb_device *usbdev;
  248. +   /* Head link to list of all inbound endpoints in this remote */
  249. +   struct list_head iep_listhead;
  250. +   struct out_endpt *out_init;
  251. +   int devnum;
  252. +
  253. +   /* lirc */
  254. +   struct lirc_driver *d;
  255. +   int connected;
  256. +
  257. +   /* locking */
  258. +   struct mutex lock;
  259. +};
  260. +
  261. +/* list of all registered devices via the remote_list_link in xbox_dev */
  262. +static struct list_head remote_list;
  263. +
  264. +/*
  265. + * Convenience macros to retrieve a pointer to the surrounding struct from
  266. + * the given list_head reference within, pointed at by link.
  267. + */
  268. +#define get_iep_from_link(link) \
  269. +       list_entry((link), struct in_endpt, iep_list_link);
  270. +#define get_irctl_from_link(link) \
  271. +       list_entry((link), struct xbox_dev, remote_list_link);
  272. +
  273. +/* send packet - used to initialize remote */
  274. +static void send_packet(struct out_endpt *oep, u16 cmd, unsigned char *data)
  275. +{
  276. +   struct xbox_dev *ir = oep->ir;
  277. +   DECLARE_WAITQUEUE(wait, current);
  278. +   int timeout = HZ; /* 1 second */
  279. +   unsigned char buf[USB_OUTLEN];
  280. +
  281. +   dprintk(DRIVER_NAME "[%d]: send called (%#x)\n", ir->devnum, cmd);
  282. +
  283. +   mutex_lock(&ir->lock);
  284. +   oep->urb->transfer_buffer_length = LO(cmd) + 1;
  285. +   oep->urb->dev = oep->ir->usbdev;
  286. +   oep->send_flags = SEND_FLAG_IN_PROGRESS;
  287. +
  288. +   memcpy(buf+1, data, LO(cmd));
  289. +   buf[0] = HI(cmd);
  290. +   memcpy(oep->buf, buf, LO(cmd)+1);
  291. +
  292. +   set_current_state(TASK_INTERRUPTIBLE);
  293. +   add_wait_queue(&oep->wait, &wait);
  294. +
  295. +   if (usb_submit_urb(oep->urb, GFP_ATOMIC)) {
  296. +       set_current_state(TASK_RUNNING);
  297. +       remove_wait_queue(&oep->wait, &wait);
  298. +       mutex_unlock(&ir->lock);
  299. +       return;
  300. +   }
  301. +   mutex_unlock(&ir->lock);
  302. +
  303. +   while (timeout && (oep->urb->status == -EINPROGRESS)
  304. +          && !(oep->send_flags & SEND_FLAG_COMPLETE)) {
  305. +       timeout = schedule_timeout(timeout);
  306. +       rmb();
  307. +   }
  308. +
  309. +   dprintk(DRIVER_NAME "[%d]: send complete (%#x)\n", ir->devnum, cmd);
  310. +
  311. +   set_current_state(TASK_RUNNING);
  312. +   remove_wait_queue(&oep->wait, &wait);
  313. +   oep->urb->transfer_flags |= URB_ASYNC_UNLINK;
  314. +   usb_unlink_urb(oep->urb);
  315. +}
  316. +
  317. +static int unregister_from_lirc(struct xbox_dev *ir)
  318. +{
  319. +   struct lirc_driver *d = ir->d;
  320. +   int devnum;
  321. +
  322. +   devnum = ir->devnum;
  323. +   dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum);
  324. +
  325. +   lirc_unregister_driver(d->minor);
  326. +
  327. +   printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum);
  328. +   return 0;
  329. +}
  330. +
  331. +static int set_use_inc(void *data)
  332. +{
  333. +   struct xbox_dev *ir = data;
  334. +   struct list_head *pos, *n;
  335. +   struct in_endpt *iep;
  336. +   int rtn;
  337. +
  338. +   if (!ir) {
  339. +       printk(DRIVER_NAME "[?]: set_use_inc called with no context\n");
  340. +       return -EIO;
  341. +   }
  342. +   dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum);
  343. +
  344. +   mutex_lock(&ir->lock);
  345. +   if (!ir->connected) {
  346. +       if (!ir->usbdev) {
  347. +           mutex_unlock(&ir->lock);
  348. +           dprintk(DRIVER_NAME "[%d]: !ir->usbdev\n", ir->devnum);
  349. +           return -ENOENT;
  350. +       }
  351. +
  352. +       /* Iterate through the inbound endpoints */
  353. +       list_for_each_safe(pos, n, &ir->iep_listhead) {
  354. +           /* extract the current in_endpt */
  355. +           iep = get_iep_from_link(pos);
  356. +           iep->urb->dev = ir->usbdev;
  357. +           dprintk(DRIVER_NAME "[%d]: linking iep 0x%02x (%p)\n",
  358. +               ir->devnum, iep->ep->bEndpointAddress, iep);
  359. +           rtn = usb_submit_urb(iep->urb, GFP_ATOMIC);
  360. +           if (rtn) {
  361. +               printk(DRIVER_NAME "[%d]: open result = %d "
  362. +                      "error submitting urb\n",
  363. +                      ir->devnum, rtn);
  364. +               mutex_unlock(&ir->lock);
  365. +               return -EIO;
  366. +           }
  367. +       }
  368. +       ir->connected = 1;
  369. +   }
  370. +   mutex_unlock(&ir->lock);
  371. +
  372. +   return 0;
  373. +}
  374. +
  375. +static void set_use_dec(void *data)
  376. +{
  377. +   struct xbox_dev *ir = data;
  378. +   struct list_head *pos, *n;
  379. +   struct in_endpt *iep;
  380. +
  381. +   if (!ir) {
  382. +       printk(DRIVER_NAME "[?]: set_use_dec called with no context\n");
  383. +       return;
  384. +   }
  385. +   dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum);
  386. +
  387. +   mutex_lock(&ir->lock);
  388. +   if (ir->connected) {
  389. +       /* Free inbound usb urbs */
  390. +       list_for_each_safe(pos, n, &ir->iep_listhead) {
  391. +           iep = get_iep_from_link(pos);
  392. +           dprintk(DRIVER_NAME "[%d]: unlinking iep 0x%02x (%p)\n",
  393. +               ir->devnum, iep->ep->bEndpointAddress, iep);
  394. +           usb_kill_urb(iep->urb);
  395. +       }
  396. +       ir->connected = 0;
  397. +   }
  398. +   mutex_unlock(&ir->lock);
  399. +}
  400. +
  401. +static void print_data(struct in_endpt *iep, char *buf, int len)
  402. +{
  403. +        const int clen = CODE_LENGTH;
  404. +   char codes[clen * 3 + 1];
  405. +   int i;
  406. +
  407. +   if (len <= 0)
  408. +       return;
  409. +
  410. +   for (i = 0; i < len && i < clen; i++)
  411. +       snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF);
  412. +   printk(DRIVER_NAME "[%d]: data received %s (ep=0x%x length=%d)\n",
  413. +       iep->ir->devnum, codes, iep->ep->bEndpointAddress, len);
  414. +}
  415. +
  416. +static int code_check_xbox(struct in_endpt *iep, int len)
  417. +{
  418. +  //   struct xbox_dev *ir = iep->ir;
  419. +   const int clen = CODE_LENGTH;
  420. +
  421. +   if (len != clen) {
  422. +       dprintk(DRIVER_NAME ": We got %d instead of %d bytes from xbox "
  423. +           "ir.. ?\n", len, clen);
  424. +       return -1;
  425. +   }
  426. +
  427. +   /* check for repeats */
  428. +   if (memcmp(iep->old, iep->buf, len) == 0) {
  429. +       if (iep->old_jiffies + repeat_jiffies > jiffies)
  430. +           return -1;
  431. +   } else {
  432. +       /*
  433. +        * the third byte of xbox ir packet seems to contain key info
  434. +        * the last two bytes are.. some kind of clock?
  435. +        */
  436. +       iep->buf[0] = iep->buf[2];
  437. +       memset(iep->buf + 1, 0, len - 1);
  438. +       memcpy(iep->old, iep->buf, len);
  439. +   }
  440. +   iep->old_jiffies = jiffies;
  441. +
  442. +   return 0;
  443. +}
  444. +
  445. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
  446. +static void usb_remote_recv(struct urb *urb, struct pt_regs *regs)
  447. +#else
  448. +static void usb_remote_recv(struct urb *urb)
  449. +#endif
  450. +{
  451. +   struct in_endpt *iep;
  452. +   int len, result = -1;
  453. +
  454. +   if (!urb)
  455. +       return;
  456. +   iep = urb->context;
  457. +   if (!iep) {
  458. +       urb->transfer_flags |= URB_ASYNC_UNLINK;
  459. +       usb_unlink_urb(urb);
  460. +       return;
  461. +   }
  462. +   if (!iep->ir->usbdev)
  463. +       return;
  464. +
  465. +   len = urb->actual_length;
  466. +   if (debug)
  467. +       print_data(iep, urb->transfer_buffer, len);
  468. +
  469. +   switch (urb->status) {
  470. +
  471. +   case 0:
  472. +           result = code_check_xbox(iep, len);
  473. +    
  474. +           if (result < 0)
  475. +           break;
  476. +
  477. +       lirc_buffer_write(iep->ir->d->rbuf, iep->buf);
  478. +       wake_up(&iep->ir->d->rbuf->wait_poll);
  479. +       break;
  480. +
  481. +   case -ECONNRESET:
  482. +   case -ENOENT:
  483. +   case -ESHUTDOWN:
  484. +       urb->transfer_flags |= URB_ASYNC_UNLINK;
  485. +       usb_unlink_urb(urb);
  486. +       return;
  487. +
  488. +   case -EPIPE:
  489. +   default:
  490. +       break;
  491. +   }
  492. +
  493. +   usb_submit_urb(urb, GFP_ATOMIC);
  494. +}
  495. +
  496. +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
  497. +static void usb_remote_send(struct urb *urb, struct pt_regs *regs)
  498. +#else
  499. +static void usb_remote_send(struct urb *urb)
  500. +#endif
  501. +{
  502. +   struct out_endpt *oep;
  503. +
  504. +   if (!urb)
  505. +       return;
  506. +   oep = urb->context;
  507. +   if (!oep) {
  508. +       urb->transfer_flags |= URB_ASYNC_UNLINK;
  509. +       usb_unlink_urb(urb);
  510. +       return;
  511. +   }
  512. +   if (!oep->ir->usbdev)
  513. +       return;
  514. +
  515. +   dprintk(DRIVER_NAME "[%d]: usb out called\n", oep->ir->devnum);
  516. +
  517. +   if (urb->status)
  518. +       return;
  519. +
  520. +   oep->send_flags |= SEND_FLAG_COMPLETE;
  521. +   wmb();
  522. +   if (waitqueue_active(&oep->wait))
  523. +       wake_up(&oep->wait);
  524. +}
  525. +
  526. +
  527. +/*
  528. + * Initialization and removal
  529. + */
  530. +
  531. +/*
  532. + * Free iep according to mem_failure which specifies a checkpoint into the
  533. + * initialization sequence for rollback recovery.
  534. + */
  535. +static void free_in_endpt(struct in_endpt *iep, int mem_failure)
  536. +{
  537. +   struct xbox_dev *ir;
  538. +   dprintk(DRIVER_NAME ": free_in_endpt(%p, %d)\n", iep, mem_failure);
  539. +   if (!iep)
  540. +       return;
  541. +
  542. +   ir = iep->ir;
  543. +   if (!ir) {
  544. +       dprintk(DRIVER_NAME ": free_in_endpt: WARNING! null ir\n");
  545. +       return;
  546. +   }
  547. +   mutex_lock(&ir->lock);
  548. +   switch (mem_failure) {
  549. +   case FREE_ALL:
  550. +   case 5:
  551. +       list_del(&iep->iep_list_link);
  552. +       dprintk(DRIVER_NAME "[%d]: free_in_endpt removing ep=0x%0x "
  553. +           "from list\n", ir->devnum, iep->ep->bEndpointAddress);
  554. +   case 4:
  555. +       if (iep->urb) {
  556. +           iep->urb->transfer_flags |= URB_ASYNC_UNLINK;
  557. +           usb_unlink_urb(iep->urb);
  558. +           usb_free_urb(iep->urb);
  559. +           iep->urb = 0;
  560. +       } else
  561. +           dprintk(DRIVER_NAME "[%d]: free_in_endpt null urb!\n",
  562. +               ir->devnum);
  563. +   case 3:
  564. +       usb_free_coherent(iep->ir->usbdev, iep->len, iep->buf, iep->dma);
  565. +       iep->buf = 0;
  566. +   case 2:
  567. +       kfree(iep);
  568. +   }
  569. +   mutex_unlock(&ir->lock);
  570. +}
  571. +
  572. +/*
  573. + * Construct a new inbound endpoint for this remote, and add it to the list of
  574. + * in_epts in ir.
  575. + */
  576. +static struct in_endpt *new_in_endpt(struct xbox_dev *ir,
  577. +                    struct usb_endpoint_descriptor *ep)
  578. +{
  579. +   struct usb_device *dev = ir->usbdev;
  580. +   struct in_endpt *iep;
  581. +   int pipe, maxp, len, addr;
  582. +   int mem_failure;
  583. +
  584. +   addr = ep->bEndpointAddress;
  585. +   pipe = usb_rcvintpipe(dev, addr);
  586. +   maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
  587. +
  588. +/* len = (maxp > USB_BUFLEN) ? USB_BUFLEN : maxp;
  589. + * len -= (len % CODE_LENGTH); */
  590. +   len = CODE_LENGTH;
  591. +
  592. +   dprintk(DRIVER_NAME "[%d]: acceptable inbound endpoint (0x%x) found "
  593. +       "(maxp=%d len=%d)\n", ir->devnum, addr, maxp, len);
  594. +
  595. +   mem_failure = 0;
  596. +   iep = kzalloc(sizeof(*iep), GFP_KERNEL);
  597. +   if (!iep) {
  598. +       mem_failure = 1;
  599. +       goto new_in_endpt_failure_check;
  600. +   }
  601. +   iep->ir = ir;
  602. +   iep->ep = ep;
  603. +   iep->len = len;
  604. +
  605. +   iep->buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &iep->dma);
  606. +   if (!iep->buf) {
  607. +       mem_failure = 2;
  608. +       goto new_in_endpt_failure_check;
  609. +   }
  610. +
  611. +   iep->urb = usb_alloc_urb(0, GFP_KERNEL);
  612. +   if (!iep->urb)
  613. +       mem_failure = 3;
  614. +
  615. +new_in_endpt_failure_check:
  616. +
  617. +   if (mem_failure) {
  618. +       free_in_endpt(iep, mem_failure);
  619. +       printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n",
  620. +              ir->devnum, addr, mem_failure);
  621. +       return NULL;
  622. +   }
  623. +   list_add_tail(&iep->iep_list_link, &ir->iep_listhead);
  624. +   dprintk(DRIVER_NAME "[%d]: adding ep=0x%0x to list\n",
  625. +       ir->devnum, iep->ep->bEndpointAddress);
  626. +   return iep;
  627. +}
  628. +
  629. +static void free_out_endpt(struct out_endpt *oep, int mem_failure)
  630. +{
  631. +   struct xbox_dev *ir;
  632. +   dprintk(DRIVER_NAME ": free_out_endpt(%p, %d)\n", oep, mem_failure);
  633. +   if (!oep)
  634. +       return;
  635. +
  636. +   wake_up_all(&oep->wait);
  637. +
  638. +   ir = oep->ir;
  639. +   if (!ir) {
  640. +       dprintk(DRIVER_NAME ": free_out_endpt: WARNING! null ir\n");
  641. +       return;
  642. +   }
  643. +   mutex_lock(&ir->lock);
  644. +   switch (mem_failure) {
  645. +   case FREE_ALL:
  646. +   case 4:
  647. +       if (oep->urb) {
  648. +           oep->urb->transfer_flags |= URB_ASYNC_UNLINK;
  649. +           usb_unlink_urb(oep->urb);
  650. +           usb_free_urb(oep->urb);
  651. +           oep->urb = 0;
  652. +       } else {
  653. +           dprintk(DRIVER_NAME "[%d]: free_out_endpt: null urb!\n",
  654. +               ir->devnum);
  655. +       }
  656. +   case 3:
  657. +       usb_free_coherent(oep->ir->usbdev, USB_OUTLEN,
  658. +                 oep->buf, oep->dma);
  659. +       oep->buf = 0;
  660. +   case 2:
  661. +       kfree(oep);
  662. +   }
  663. +   mutex_unlock(&ir->lock);
  664. +}
  665. +
  666. +static struct out_endpt *new_out_endpt(struct xbox_dev *ir,
  667. +                      struct usb_endpoint_descriptor *ep)
  668. +{
  669. +   struct usb_device *dev = ir->usbdev;
  670. +   struct out_endpt *oep;
  671. +   int mem_failure;
  672. +
  673. +   dprintk(DRIVER_NAME "[%d]: acceptable outbound endpoint (0x%x) found\n",
  674. +       ir->devnum, ep->bEndpointAddress);
  675. +
  676. +   mem_failure = 0;
  677. +   oep = kzalloc(sizeof(*oep), GFP_KERNEL);
  678. +   if (!oep)
  679. +       mem_failure = 1;
  680. +   else {
  681. +       oep->ir = ir;
  682. +       oep->ep = ep;
  683. +       init_waitqueue_head(&oep->wait);
  684. +
  685. +       oep->buf = usb_alloc_coherent(dev, USB_OUTLEN,
  686. +                         GFP_ATOMIC, &oep->dma);
  687. +       if (!oep->buf)
  688. +           mem_failure = 2;
  689. +       else {
  690. +           oep->urb = usb_alloc_urb(0, GFP_KERNEL);
  691. +           if (!oep->urb)
  692. +               mem_failure = 3;
  693. +       }
  694. +   }
  695. +   if (mem_failure) {
  696. +       free_out_endpt(oep, mem_failure);
  697. +       printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n",
  698. +              ir->devnum, ep->bEndpointAddress, mem_failure);
  699. +       return NULL;
  700. +   }
  701. +   return oep;
  702. +}
  703. +
  704. +static void free_irctl(struct xbox_dev *ir, int mem_failure)
  705. +{
  706. +   struct list_head *pos, *n;
  707. +   struct in_endpt *in;
  708. +   dprintk(DRIVER_NAME ": free_irctl(%p, %d)\n", ir, mem_failure);
  709. +
  710. +   if (!ir)
  711. +       return;
  712. +
  713. +   list_for_each_safe(pos, n, &ir->iep_listhead) {
  714. +       in = get_iep_from_link(pos);
  715. +       free_in_endpt(in, FREE_ALL);
  716. +   }
  717. +   if (ir->out_init) {
  718. +       free_out_endpt(ir->out_init, FREE_ALL);
  719. +       ir->out_init = NULL;
  720. +   }
  721. +
  722. +   mutex_lock(&ir->lock);
  723. +   switch (mem_failure) {
  724. +   case FREE_ALL:
  725. +   case 6:
  726. +       if (!--ir->dev_refcount) {
  727. +           list_del(&ir->remote_list_link);
  728. +           dprintk(DRIVER_NAME "[%d]: free_irctl: removing "
  729. +               "remote from list\n", ir->devnum);
  730. +       } else {
  731. +           dprintk(DRIVER_NAME "[%d]: free_irctl: refcount at %d,"
  732. +               "aborting free_irctl\n",
  733. +               ir->devnum, ir->dev_refcount);
  734. +           mutex_unlock(&ir->lock);
  735. +           return;
  736. +       }
  737. +   case 5:
  738. +   case 4:
  739. +   case 3:
  740. +       if (ir->d) {
  741. +           switch (mem_failure) {
  742. +           case 5:
  743. +               lirc_buffer_free(ir->d->rbuf);
  744. +           case 4:
  745. +               kfree(ir->d->rbuf);
  746. +           case 3:
  747. +               kfree(ir->d);
  748. +           }
  749. +       } else
  750. +           printk(DRIVER_NAME "[%d]: ir->d is a null pointer!\n",
  751. +                  ir->devnum);
  752. +   case 2:
  753. +       mutex_unlock(&ir->lock);
  754. +       kfree(ir);
  755. +       return;
  756. +   }
  757. +   mutex_unlock(&ir->lock);
  758. +}
  759. +
  760. +static struct xbox_dev *new_irctl(struct usb_interface *intf)
  761. +{
  762. +   struct usb_device *dev = interface_to_usbdev(intf);
  763. +   struct xbox_dev *ir;
  764. +   struct lirc_driver *driver;
  765. +   int devnum, dclen;
  766. +   int mem_failure;
  767. +
  768. +   devnum = dev->devnum;
  769. +
  770. +   dprintk(DRIVER_NAME "[%d]: remote type = XBOX DVD Dongle\n", devnum);
  771. +
  772. +   mem_failure = 0;
  773. +   ir = kzalloc(sizeof(*ir), GFP_KERNEL);
  774. +   if (!ir) {
  775. +       mem_failure = 1;
  776. +       goto new_irctl_failure_check;
  777. +   }
  778. +
  779. +   dclen = DECODE_LENGTH;
  780. +
  781. +   /*
  782. +    * add this infrared remote struct to remote_list, keeping track
  783. +    * of the number of drivers registered.
  784. +    */
  785. +   dprintk(DRIVER_NAME "[%d]: adding remote to list\n", devnum);
  786. +   list_add_tail(&ir->remote_list_link, &remote_list);
  787. +   ir->dev_refcount = 1;
  788. +
  789. +   driver = kzalloc(sizeof(*driver), GFP_KERNEL);
  790. +   if (!driver) {
  791. +       mem_failure = 2;
  792. +       goto new_irctl_failure_check;
  793. +   }
  794. +
  795. +   ir->d = driver;
  796. +   driver->rbuf = kmalloc(sizeof(*(driver->rbuf)), GFP_KERNEL);
  797. +   if (!driver->rbuf) {
  798. +       mem_failure = 3;
  799. +       goto new_irctl_failure_check;
  800. +   }
  801. +
  802. +   if (lirc_buffer_init(driver->rbuf, dclen, 2)) {
  803. +       mem_failure = 4;
  804. +       goto new_irctl_failure_check;
  805. +   }
  806. +
  807. +   strcpy(driver->name, DRIVER_NAME " ");
  808. +   driver->minor = -1;
  809. +   driver->code_length = dclen * 8;
  810. +   driver->features = LIRC_CAN_REC_LIRCCODE;
  811. +   driver->data = ir;
  812. +   driver->set_use_inc = &set_use_inc;
  813. +   driver->set_use_dec = &set_use_dec;
  814. +   driver->dev = &intf->dev;
  815. +   driver->owner = THIS_MODULE;
  816. +   ir->usbdev = dev;
  817. +   ir->devnum = devnum;
  818. +
  819. +   mutex_init(&ir->lock);
  820. +   INIT_LIST_HEAD(&ir->iep_listhead);
  821. +
  822. +new_irctl_failure_check:
  823. +
  824. +   if (mem_failure) {
  825. +       free_irctl(ir, mem_failure);
  826. +       printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n",
  827. +              devnum, mem_failure);
  828. +       return NULL;
  829. +   }
  830. +   return ir;
  831. +}
  832. +
  833. +/*
  834. + * Scan the global list of remotes to see if the device listed is one of them.
  835. + * If it is, the corresponding xbox_dev is returned, with its dev_refcount
  836. + * incremented.  Otherwise, returns null.
  837. + */
  838. +static struct xbox_dev *get_prior_reg_ir(struct usb_device *dev)
  839. +{
  840. +   struct list_head *pos;
  841. +   struct xbox_dev *ir = NULL;
  842. +
  843. +   dprintk(DRIVER_NAME "[%d]: scanning remote_list...\n", dev->devnum);
  844. +   list_for_each(pos, &remote_list) {
  845. +       ir = get_irctl_from_link(pos);
  846. +       if (ir->usbdev != dev) {
  847. +           dprintk(DRIVER_NAME "[%d]: device %d isn't it...",
  848. +               dev->devnum, ir->devnum);
  849. +           ir = NULL;
  850. +       } else {
  851. +           dprintk(DRIVER_NAME "[%d]: prior instance found.\n",
  852. +               dev->devnum);
  853. +           ir->dev_refcount++;
  854. +           break;
  855. +       }
  856. +   }
  857. +   return ir;
  858. +}
  859. +
  860. +/*
  861. + * If the USB interface has an out endpoint for control.
  862. + */
  863. +static void send_outbound_init(struct xbox_dev *ir)
  864. +{
  865. +   if (ir->out_init) {
  866. +       struct out_endpt *oep = ir->out_init;
  867. +       dprintk(DRIVER_NAME "[%d]: usb_remote_probe: initializing "
  868. +           "outbound ep\n", ir->devnum);
  869. +       usb_fill_int_urb(oep->urb, ir->usbdev,
  870. +           usb_sndintpipe(ir->usbdev, oep->ep->bEndpointAddress),
  871. +           oep->buf, USB_OUTLEN, usb_remote_send,
  872. +           oep, oep->ep->bInterval);
  873. +       oep->urb->transfer_dma = oep->dma;
  874. +       oep->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
  875. +
  876. +       send_packet(oep, 0x8004, init1);
  877. +       send_packet(oep, 0x8007, init2);
  878. +   }
  879. +}
  880. +
  881. +/* Log driver and usb info */
  882. +static void log_usb_dev_info(struct usb_device *dev)
  883. +{
  884. +   char buf[63], name[128] = "";
  885. +
  886. +   if (dev->descriptor.iManufacturer
  887. +       && usb_string(dev, dev->descriptor.iManufacturer,
  888. +             buf, sizeof(buf)) > 0)
  889. +       strlcpy(name, buf, sizeof(name));
  890. +   if (dev->descriptor.iProduct
  891. +       && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0)
  892. +       snprintf(name + strlen(name), sizeof(name) - strlen(name),
  893. +            " %s", buf);
  894. +   printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", dev->devnum, name,
  895. +          dev->bus->busnum, dev->devnum);
  896. +}
  897. +
  898. +
  899. +static int usb_remote_probe(struct usb_interface *intf,
  900. +               const struct usb_device_id *id)
  901. +{
  902. +   struct usb_device *dev = interface_to_usbdev(intf);
  903. +   struct usb_host_interface *idesc;
  904. +   struct usb_endpoint_descriptor *ep;
  905. +   struct in_endpt *iep;
  906. +   struct xbox_dev *ir;
  907. +   int i;
  908. +
  909. +   dprintk(DRIVER_NAME "[%d]: usb_remote_probe: dev:%p, intf:%p, id:%p)\n",
  910. +       dev->devnum, dev, intf, id);
  911. +
  912. +   idesc = intf->cur_altsetting;
  913. +
  914. +   /* Check if a usb remote has already been registered for this device */
  915. +   ir = get_prior_reg_ir(dev);
  916. +
  917. +   if (!ir) {
  918. +       ir = new_irctl(intf);
  919. +       if (!ir)
  920. +           return -ENOMEM;
  921. +   }
  922. +
  923. +   /*
  924. +    * step through the endpoints to find first in and first out endpoint
  925. +    * of type interrupt transfer
  926. +    */
  927. +   for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
  928. +       ep = &idesc->endpoint[i].desc;
  929. +       dprintk(DRIVER_NAME "[%d]: processing endpoint %d\n",
  930. +           dev->devnum, i);
  931. +       if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
  932. +            USB_DIR_IN) &&
  933. +            ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
  934. +             USB_ENDPOINT_XFER_INT)) {
  935. +
  936. +           iep = new_in_endpt(ir, ep);
  937. +           if (iep)
  938. +           {
  939. +               usb_fill_int_urb(iep->urb, dev,
  940. +                   usb_rcvintpipe(dev,
  941. +                       iep->ep->bEndpointAddress),
  942. +                   iep->buf, iep->len, usb_remote_recv,
  943. +                   iep, iep->ep->bInterval);
  944. +               iep->urb->transfer_dma = iep->dma;
  945. +               iep->urb->transfer_flags |=
  946. +                   URB_NO_TRANSFER_DMA_MAP;
  947. +           }
  948. +       }
  949. +
  950. +       if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
  951. +            USB_DIR_OUT) &&
  952. +            ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
  953. +             USB_ENDPOINT_XFER_INT) &&
  954. +             (ir->out_init == NULL))
  955. +           ir->out_init = new_out_endpt(ir, ep);
  956. +   }
  957. +   if (list_empty(&ir->iep_listhead)) {
  958. +       printk(DRIVER_NAME "[%d]: inbound endpoint not found\n",
  959. +              ir->devnum);
  960. +       free_irctl(ir, FREE_ALL);
  961. +       return -ENODEV;
  962. +   }
  963. +   if (ir->dev_refcount == 1) {
  964. +       ir->d->minor = lirc_register_driver(ir->d);
  965. +       if (ir->d->minor < 0) {
  966. +           free_irctl(ir, FREE_ALL);
  967. +           return -ENODEV;
  968. +       }
  969. +
  970. +       /* Note new driver registration in kernel logs */
  971. +       log_usb_dev_info(dev);
  972. +
  973. +       /* outbound data (initialization) */
  974. +       send_outbound_init(ir);
  975. +   }
  976. +
  977. +   usb_set_intfdata(intf, ir);
  978. +   return 0;
  979. +}
  980. +
  981. +static void usb_remote_disconnect(struct usb_interface *intf)
  982. +{
  983. +   /* struct usb_device *dev = interface_to_usbdev(intf); */
  984. +   struct xbox_dev *ir = usb_get_intfdata(intf);
  985. +   usb_set_intfdata(intf, NULL);
  986. +
  987. +   dprintk(DRIVER_NAME ": disconnecting remote %d:\n",
  988. +       (ir ? ir->devnum : -1));
  989. +   if (!ir || !ir->d)
  990. +       return;
  991. +
  992. +   if (ir->usbdev) {
  993. +       /* Only unregister once */
  994. +       ir->usbdev = NULL;
  995. +       unregister_from_lirc(ir);
  996. +   }
  997. +
  998. +   /* This also removes the current remote from remote_list */
  999. +   free_irctl(ir, FREE_ALL);
  1000. +}
  1001. +
  1002. +static struct usb_driver usb_remote_driver = {
  1003. +   LIRC_THIS_MODULE(.owner = THIS_MODULE)
  1004. +   .name       = DRIVER_NAME,
  1005. +   .probe      = usb_remote_probe,
  1006. +   .disconnect = usb_remote_disconnect,
  1007. +   .id_table   = usb_remote_table
  1008. +};
  1009. +
  1010. +static int __init usb_remote_init(void)
  1011. +{
  1012. +   int i;
  1013. +
  1014. +   INIT_LIST_HEAD(&remote_list);
  1015. +
  1016. +   printk(KERN_INFO "\n" DRIVER_NAME ": " DRIVER_DESC " "
  1017. +          DRIVER_VERSION "\n");
  1018. +   printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n");
  1019. +   dprintk(DRIVER_NAME ": debug mode enabled: "
  1020. +       "$Id: lirc_xbox.c,v 1.88 2011/06/05 11:11:11 jmartin Exp $\n");
  1021. +
  1022. +   repeat_jiffies = repeat*HZ/100;
  1023. +
  1024. +   i = usb_register(&usb_remote_driver);
  1025. +   if (i) {
  1026. +       printk(DRIVER_NAME ": usb register failed, result = %d\n", i);
  1027. +       return -ENODEV;
  1028. +   }
  1029. +
  1030. +   return 0;
  1031. +}
  1032. +
  1033. +static void __exit usb_remote_exit(void)
  1034. +{
  1035. +   usb_deregister(&usb_remote_driver);
  1036. +}
  1037. +
  1038. +module_init(usb_remote_init);
  1039. +module_exit(usb_remote_exit);
  1040. +
  1041. +MODULE_DESCRIPTION(DRIVER_DESC);
  1042. +MODULE_AUTHOR(DRIVER_AUTHOR);
  1043. +MODULE_LICENSE("GPL");
  1044. +MODULE_DEVICE_TABLE(usb, usb_remote_table);
  1045. +
  1046. +module_param(debug, bool, S_IRUGO | S_IWUSR);
  1047. +MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)");
  1048. +
  1049. +module_param(mask, int, S_IRUGO | S_IWUSR);
  1050. +MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)");
  1051. +
  1052. +module_param(unique, bool, S_IRUGO | S_IWUSR);
  1053. +MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)");
  1054. +
  1055. +module_param(repeat, int, S_IRUGO | S_IWUSR);
  1056. +MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)");
  1057. diff -uNr '--exclude=.git' a/drivers/lirc_xbox/Makefile.am b/drivers/lirc_xbox/Makefile.am
  1058. --- a/drivers/lirc_xbox/Makefile.am 1969-12-31 16:00:00.000000000 -0800
  1059. +++ b/drivers/lirc_xbox/Makefile.am 2014-05-29 10:43:01.608195797 -0700
  1060. @@ -0,0 +1,13 @@
  1061. +## $Id: Makefile.am,v 1.3 2004/04/25 16:29:24 lirc Exp $
  1062. +
  1063. +## Process this file with automake to produce Makefile.in
  1064. +
  1065. +## this is so that Automake includes the C compiling definitions, and
  1066. +## includes the source files in the distribution.
  1067. +EXTRA_PROGRAMS = automake_dummy
  1068. +automake_dummy_SOURCES = lirc_xbox.c
  1069. +
  1070. +## there is no *just* object file support in automake.  This is close enough
  1071. +module_DATA = lirc_xbox.o
  1072. +
  1073. +include ../Makefile.common
  1074. \ No newline at end of file
  1075. diff -uNr '--exclude=.git' a/remotes/xbox/lircd.conf.xbox b/remotes/xbox/lircd.conf.xbox
  1076. --- a/remotes/xbox/lircd.conf.xbox  1969-12-31 16:00:00.000000000 -0800
  1077. +++ b/remotes/xbox/lircd.conf.xbox  2014-05-29 10:43:21.564068151 -0700
  1078. @@ -0,0 +1,58 @@
  1079. +#lirc.conf.xbox
  1080. +# Please make this file available to others
  1081. +# by sending it to <lirc@bartelmus.de>
  1082. +#
  1083. +# this config file was automatically generated
  1084. +# using lirc-0.8.2-CVS(default) on Mon Aug 25 09:04:22 2008
  1085. +#
  1086. +# contributed by
  1087. +#
  1088. +# brand:                       xbox.conf
  1089. +# model no. of remote control:
  1090. +# devices being controlled by this remote:
  1091. +#
  1092. +
  1093. +begin remote
  1094. +
  1095. +  name  xbox.conf
  1096. +  bits            8
  1097. +  eps            30
  1098. +  aeps          100
  1099. +
  1100. +  one             0     0
  1101. +  zero            0     0
  1102. +  gap          163983
  1103. +  min_repeat      15
  1104. +  toggle_bit_mask 0x0
  1105. +
  1106. +      begin codes
  1107. +          MENU                     0xF7
  1108. +          DISPLAY                  0xD5
  1109. +          TITLE                    0xE5
  1110. +          INFO                     0xC3
  1111. +          EXIT                     0xD8
  1112. +          UP                       0xA6
  1113. +          DOWN                     0xA7
  1114. +          LEFT                     0xA9
  1115. +          RIGHT                    0xA8
  1116. +          SELECT                   0x0B
  1117. +          SKIP-                    0xDD
  1118. +          SKIP+                    0xDF
  1119. +          REW                      0xE2
  1120. +          FF                       0xE3
  1121. +          STOP                     0xE0
  1122. +          1                        0xCE
  1123. +          2                        0xCD
  1124. +          PAUSE                    0xE6
  1125. +          PLAY                     0xEA
  1126. +          3                        0xCC
  1127. +          4                        0xCB
  1128. +          5                        0xCA
  1129. +          6                        0xC9
  1130. +          7                        0xC8
  1131. +          8                        0xC7
  1132. +          9                        0xC6
  1133. +          0                        0xCF
  1134. +      end codes
  1135. +
  1136. +end remote
  1137. diff -uNr '--exclude=.git' a/setup.data b/setup.data
  1138. --- a/setup.data    2014-05-29 10:43:54.071853460 -0700
  1139. +++ b/setup.data    2014-05-29 10:50:20.324812924 -0700
  1140. @@ -146,6 +146,7 @@
  1141.          usb_uirt_raw: "USB-UIRT"
  1142.          mplay: "VLSystem MPlay Blast"
  1143.          mplay: "VLSystem MPlay Mini"
  1144. +        xbox: "XBOX DVD Dongle"
  1145.  
  1146.  param_type: \
  1147.          act200l \
  1148. @@ -260,7 +261,8 @@
  1149.          ttusbir \
  1150.          tvbox \
  1151.          udp \
  1152. -        wpc8769l
  1153. +        wpc8769l \
  1154. +        xbox
  1155.          none:
  1156.  
  1157.  default_param: \
  1158. @@ -331,7 +333,8 @@
  1159.          ttusbir \
  1160.          tvbox \
  1161.          udp \
  1162. -        wpc8769l
  1163. +        wpc8769l \
  1164. +        xbox
  1165.          none:
  1166.  
  1167.  default_param: \
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement