mceusb.c revision 5ae8f9a3757e4010c7ea9c07c047088fb812335e
166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* 266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * Driver for USB Windows Media Center Ed. eHome Infrared Transceivers 366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * 466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com> 566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * 666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * Based on the original lirc_mceusb and lirc_mceusb2 drivers, by Dan 766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * Conti, Martin Blatter and Daniel Melander, the latter of which was 866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * in turn also based on the lirc_atiusb driver by Paul Miller. The 966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * two mce drivers were merged into one by Jarod Wilson, with transmit 1066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * support for the 1st-gen device added primarily by Patrick Calhoun, 1166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * with a bit of tweaks by Jarod. Debugging improvements and proper 1266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * support for what appears to be 3rd-gen hardware added by Jarod. 1366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * Initial port from lirc driver to ir-core drivery by Jarod, based 1466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * partially on a port to an earlier proposed IR infrastructure by 1566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * Jon Smirl, which included enhancements and simplifications to the 1666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * incoming IR buffer parsing routines. 1766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * 1866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * 1966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * This program is free software; you can redistribute it and/or modify 2066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * it under the terms of the GNU General Public License as published by 2166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * the Free Software Foundation; either version 2 of the License, or 2266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * (at your option) any later version. 2366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * 2466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * This program is distributed in the hope that it will be useful, 2566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * but WITHOUT ANY WARRANTY; without even the implied warranty of 2666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * GNU General Public License for more details. 2866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * 2966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * You should have received a copy of the GNU General Public License 3066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * along with this program; if not, write to the Free Software 3166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 3266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * 3366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson */ 3466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 3566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#include <linux/device.h> 3666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#include <linux/module.h> 3766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#include <linux/slab.h> 38635f76b2aa8ef3e8436dedddc8baa6f7f438dc40Paul Bender#include <linux/usb.h> 39635f76b2aa8ef3e8436dedddc8baa6f7f438dc40Paul Bender#include <linux/usb/input.h> 406bda96447cef24fbf97a798b1ea664224d5fdc25Mauro Carvalho Chehab#include <media/rc-core.h> 4166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 4266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define DRIVER_VERSION "1.91" 4366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define DRIVER_AUTHOR "Jarod Wilson <jarod@wilsonet.com>" 4466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define DRIVER_DESC "Windows Media Center Ed. eHome Infrared Transceiver " \ 4566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson "device driver" 4666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define DRIVER_NAME "mceusb" 4766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 484a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define USB_BUFLEN 32 /* USB reception buffer length */ 494a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */ 504a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */ 5166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 5266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* MCE constants */ 534a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */ 544a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_TIME_UNIT 50 /* Approx 50us resolution */ 554a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */ 564a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */ 574a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_IRDATA_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */ 584a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_IRDATA_TRAILER 0x80 /* End of IR data */ 594a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */ 604a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */ 614a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_DEFAULT_TX_MASK 0x03 /* Vals: TX1=0x01, TX2=0x02, ALL=0x03 */ 624a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_PULSE_BIT 0x80 /* Pulse bit, MSB set == PULSE else SPACE */ 634a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_PULSE_MASK 0x7f /* Pulse mask */ 644a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_MAX_PULSE_LENGTH 0x7f /* Longest transmittable pulse symbol */ 654a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson 664a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_HW_CMD_HEADER 0xff /* MCE hardware command header */ 674a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_COMMAND_HEADER 0x9f /* MCE command header */ 684a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_COMMAND_MASK 0xe0 /* Mask out command bits */ 694a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_COMMAND_NULL 0x00 /* These show up various places... */ 704a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson/* if buf[i] & MCE_COMMAND_MASK == 0x80 and buf[i] != MCE_COMMAND_HEADER, 714a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson * then we're looking at a raw IR data sample */ 724a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_COMMAND_IRDATA 0x80 734a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_PACKET_LENGTH_MASK 0x1f /* Packet length mask */ 744a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson 754a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson/* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */ 761cd50f25614226e99ac7a1518311e8474ea024e3Jarod Wilson#define MCE_CMD_SIG_END 0x01 /* End of signal */ 774a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_PING 0x03 /* Ping device */ 784a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_UNKNOWN 0x04 /* Unknown */ 794a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_UNKNOWN2 0x05 /* Unknown */ 804a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_S_CARRIER 0x06 /* Set TX carrier frequency */ 814a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_G_CARRIER 0x07 /* Get TX carrier frequency */ 824a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_S_TXMASK 0x08 /* Set TX port bitmask */ 834a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_UNKNOWN3 0x09 /* Unknown */ 844a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_UNKNOWN4 0x0a /* Unknown */ 854a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_G_REVISION 0x0b /* Get hw/sw revision */ 864a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_S_TIMEOUT 0x0c /* Set RX timeout value */ 874a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_G_TIMEOUT 0x0d /* Get RX timeout value */ 884a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_UNKNOWN5 0x0e /* Unknown */ 894a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_UNKNOWN6 0x0f /* Unknown */ 904a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_G_RXPORTSTS 0x11 /* Get RX port status */ 914a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_G_TXMASK 0x13 /* Set TX port bitmask */ 924a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_S_RXSENSOR 0x14 /* Set RX sensor (std/learning) */ 934a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_G_RXSENSOR 0x15 /* Get RX sensor (std/learning) */ 942ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson#define MCE_RSP_PULSE_COUNT 0x15 /* RX pulse count (only if learning) */ 954a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_TX_PORTS 0x16 /* Get number of TX ports */ 964a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_G_WAKESRC 0x17 /* Get wake source */ 974a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_UNKNOWN7 0x18 /* Unknown */ 984a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_UNKNOWN8 0x19 /* Unknown */ 994a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_UNKNOWN9 0x1b /* Unknown */ 1004a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_CMD_DEVICE_RESET 0xaa /* Reset the hardware */ 1014a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson#define MCE_RSP_CMD_INVALID 0xfe /* Invalid command issued */ 10266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 10366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 10466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* module parameters */ 10566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#ifdef CONFIG_USB_DEBUG 10666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic int debug = 1; 10766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#else 10866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic int debug; 10966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#endif 11066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 1115ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson#define mce_dbg(dev, fmt, ...) \ 1125ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson do { \ 1135ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson if (debug) \ 1145ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson dev_info(dev, fmt, ## __VA_ARGS__); \ 1155ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson } while (0) 1165ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson 11766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* general constants */ 11866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define SEND_FLAG_IN_PROGRESS 1 11966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define SEND_FLAG_COMPLETE 2 12066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define RECV_FLAG_IN_PROGRESS 3 12166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define RECV_FLAG_COMPLETE 4 12266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 12366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCEUSB_RX 1 12466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCEUSB_TX 2 12566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 12666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_PHILIPS 0x0471 12766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_SMK 0x0609 12866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_TATUNG 0x1460 12966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_GATEWAY 0x107b 13066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_SHUTTLE 0x1308 13166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_SHUTTLE2 0x051c 13266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_MITSUMI 0x03ee 13366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_TOPSEED 0x1784 13466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_RICAVISION 0x179d 13566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_ITRON 0x195d 13666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_FIC 0x1509 13766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_LG 0x043e 13866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_MICROSOFT 0x045e 13966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_FORMOSA 0x147a 14066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_FINTEK 0x1934 14166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_PINNACLE 0x2304 14266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_ECS 0x1019 14366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_WISTRON 0x0fb8 14466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_COMPRO 0x185b 14566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_NORTHSTAR 0x04eb 14666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_REALTEK 0x0bda 14766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_TIVO 0x105a 14856e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab#define VENDOR_CONEXANT 0x0572 14966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 15037dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehabenum mceusb_model_type { 15137dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab MCE_GEN2 = 0, /* Most boards */ 15237dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab MCE_GEN1, 15337dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab MCE_GEN3, 15437dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab MCE_GEN2_TX_INV, 15537dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab POLARIS_EVK, 1566f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson CX_HYBRID_TV, 157a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson MULTIFUNCTION, 158d8ee99e79994f916bc5b81990f861ea923e7f332Jarod Wilson TIVO_KIT, 1592faa0ca82c7180f58a4b3bb3c460e5bdcdcf04c6Jarod Wilson MCE_GEN2_NO_TX, 16037dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab}; 16137dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab 16237dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehabstruct mceusb_model { 16337dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab u32 mce_gen1:1; 16437dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab u32 mce_gen2:1; 16537dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab u32 mce_gen3:1; 166d8cc7fd7e6371026c15254a35e618d2e5c5bf562Jarod Wilson u32 tx_mask_normal:1; 1676f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson u32 no_tx:1; 16837dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab 169a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson int ir_intfnum; 170a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson 17117c2b1fd71f75a50284a33af9bc0d98ed1cbcd30Mauro Carvalho Chehab const char *rc_map; /* Allow specify a per-board map */ 1723459d4553b95084a6390e9b62687488538f33c57Mauro Carvalho Chehab const char *name; /* per-board name */ 17337dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab}; 17437dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab 17537dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehabstatic const struct mceusb_model mceusb_model[] = { 17637dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab [MCE_GEN1] = { 17737dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .mce_gen1 = 1, 178d8cc7fd7e6371026c15254a35e618d2e5c5bf562Jarod Wilson .tx_mask_normal = 1, 17937dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab }, 18037dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab [MCE_GEN2] = { 18137dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .mce_gen2 = 1, 18237dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab }, 1832faa0ca82c7180f58a4b3bb3c460e5bdcdcf04c6Jarod Wilson [MCE_GEN2_NO_TX] = { 1842faa0ca82c7180f58a4b3bb3c460e5bdcdcf04c6Jarod Wilson .mce_gen2 = 1, 1852faa0ca82c7180f58a4b3bb3c460e5bdcdcf04c6Jarod Wilson .no_tx = 1, 1862faa0ca82c7180f58a4b3bb3c460e5bdcdcf04c6Jarod Wilson }, 18737dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab [MCE_GEN2_TX_INV] = { 18837dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .mce_gen2 = 1, 189d8cc7fd7e6371026c15254a35e618d2e5c5bf562Jarod Wilson .tx_mask_normal = 1, 19037dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab }, 19137dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab [MCE_GEN3] = { 19237dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .mce_gen3 = 1, 193d8cc7fd7e6371026c15254a35e618d2e5c5bf562Jarod Wilson .tx_mask_normal = 1, 19437dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab }, 19537dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab [POLARIS_EVK] = { 19617c2b1fd71f75a50284a33af9bc0d98ed1cbcd30Mauro Carvalho Chehab /* 19717c2b1fd71f75a50284a33af9bc0d98ed1cbcd30Mauro Carvalho Chehab * In fact, the EVK is shipped without 19817c2b1fd71f75a50284a33af9bc0d98ed1cbcd30Mauro Carvalho Chehab * remotes, but we should have something handy, 19917c2b1fd71f75a50284a33af9bc0d98ed1cbcd30Mauro Carvalho Chehab * to allow testing it 20017c2b1fd71f75a50284a33af9bc0d98ed1cbcd30Mauro Carvalho Chehab */ 20115195d3a83b59f0ca3bed52cbe5524042ce13fd6Mauro Carvalho Chehab .rc_map = RC_MAP_HAUPPAUGE, 2026f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson .name = "Conexant Hybrid TV (cx231xx) MCE IR", 2036f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson }, 2046f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson [CX_HYBRID_TV] = { 2056f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson .no_tx = 1, /* tx isn't wired up at all */ 2066f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson .name = "Conexant Hybrid TV (cx231xx) MCE IR", 20737dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab }, 208a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson [MULTIFUNCTION] = { 209a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson .mce_gen2 = 1, 210a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson .ir_intfnum = 2, 211a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson }, 212d8ee99e79994f916bc5b81990f861ea923e7f332Jarod Wilson [TIVO_KIT] = { 213d8ee99e79994f916bc5b81990f861ea923e7f332Jarod Wilson .mce_gen2 = 1, 214d8ee99e79994f916bc5b81990f861ea923e7f332Jarod Wilson .rc_map = RC_MAP_TIVO, 215d8ee99e79994f916bc5b81990f861ea923e7f332Jarod Wilson }, 21637dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab}; 21737dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab 21866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic struct usb_device_id mceusb_dev_table[] = { 21966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Original Microsoft MCE IR Transceiver (often HP-branded) */ 22037dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_MICROSOFT, 0x006d), 22137dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .driver_info = MCE_GEN1 }, 22266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Philips Infrared Transceiver - Sahara branded */ 22366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x0608) }, 22466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Philips Infrared Transceiver - HP branded */ 22537dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_PHILIPS, 0x060c), 22637dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .driver_info = MCE_GEN2_TX_INV }, 22766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Philips SRM5100 */ 22866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x060d) }, 22966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Philips Infrared Transceiver - Omaura */ 23066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x060f) }, 23166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Philips Infrared Transceiver - Spinel plus */ 23266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x0613) }, 23366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Philips eHome Infrared Transceiver */ 23466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x0815) }, 235c13df9cf6b1cad7fd088c9acceb98b6bffd9ca31Jarod Wilson /* Philips/Spinel plus IR transceiver for ASUS */ 236c13df9cf6b1cad7fd088c9acceb98b6bffd9ca31Jarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x206c) }, 237c13df9cf6b1cad7fd088c9acceb98b6bffd9ca31Jarod Wilson /* Philips/Spinel plus IR transceiver for ASUS */ 238c13df9cf6b1cad7fd088c9acceb98b6bffd9ca31Jarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x2088) }, 239e296e1276ca389156d7f06eed668dac30141c37dJarod Wilson /* Philips IR transceiver (Dell branded) */ 240e296e1276ca389156d7f06eed668dac30141c37dJarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x2093) }, 241a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson /* Realtek MCE IR Receiver and card reader */ 242a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson { USB_DEVICE(VENDOR_REALTEK, 0x0161), 243a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson .driver_info = MULTIFUNCTION }, 24466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* SMK/Toshiba G83C0004D410 */ 24537dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_SMK, 0x031d), 24637dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .driver_info = MCE_GEN2_TX_INV }, 24766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* SMK eHome Infrared Transceiver (Sony VAIO) */ 24837dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_SMK, 0x0322), 24937dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .driver_info = MCE_GEN2_TX_INV }, 25066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* bundled with Hauppauge PVR-150 */ 25137dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_SMK, 0x0334), 25237dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .driver_info = MCE_GEN2_TX_INV }, 25366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* SMK eHome Infrared Transceiver */ 25466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_SMK, 0x0338) }, 25566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Tatung eHome Infrared Transceiver */ 25666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, 25766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Shuttle eHome Infrared Transceiver */ 25866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_SHUTTLE, 0xc001) }, 25966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Shuttle eHome Infrared Transceiver */ 26066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) }, 26166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Gateway eHome Infrared Transceiver */ 26266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_GATEWAY, 0x3009) }, 26366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Mitsumi */ 26466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_MITSUMI, 0x2501) }, 26566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Topseed eHome Infrared Transceiver */ 26637dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_TOPSEED, 0x0001), 26737dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .driver_info = MCE_GEN2_TX_INV }, 26866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Topseed HP eHome Infrared Transceiver */ 26937dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_TOPSEED, 0x0006), 27037dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .driver_info = MCE_GEN2_TX_INV }, 27166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Topseed eHome Infrared Transceiver */ 27237dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_TOPSEED, 0x0007), 27337dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .driver_info = MCE_GEN2_TX_INV }, 27466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Topseed eHome Infrared Transceiver */ 27537dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_TOPSEED, 0x0008), 27637dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .driver_info = MCE_GEN3 }, 27766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Topseed eHome Infrared Transceiver */ 27837dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_TOPSEED, 0x000a), 27937dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .driver_info = MCE_GEN2_TX_INV }, 28066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Topseed eHome Infrared Transceiver */ 28137dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_TOPSEED, 0x0011), 2827d9a46f9d5e0bea8e862143be73df2bbc9acb2a3Jarod Wilson .driver_info = MCE_GEN3 }, 28366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Ricavision internal Infrared Transceiver */ 28466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_RICAVISION, 0x0010) }, 28566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Itron ione Libra Q-11 */ 28666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_ITRON, 0x7002) }, 28766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* FIC eHome Infrared Transceiver */ 28866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FIC, 0x9242) }, 28966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* LG eHome Infrared Transceiver */ 29066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_LG, 0x9803) }, 29166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Microsoft MCE Infrared Transceiver */ 29266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) }, 29366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa eHome Infrared Transceiver */ 29466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe015) }, 29566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa21 / eHome Infrared Receiver */ 29666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, 29766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa aim / Trust MCE Infrared Receiver */ 2982faa0ca82c7180f58a4b3bb3c460e5bdcdcf04c6Jarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe017), 2992faa0ca82c7180f58a4b3bb3c460e5bdcdcf04c6Jarod Wilson .driver_info = MCE_GEN2_NO_TX }, 30066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa Industrial Computing / Beanbag Emulation Device */ 30166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, 30266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa21 / eHome Infrared Receiver */ 30366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe03a) }, 30466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa Industrial Computing AIM IR605/A */ 30566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) }, 30666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa Industrial Computing */ 30766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe03e) }, 308fbb1f1b0db9b196928157f97515a7ea537310ebcJarod Wilson /* Fintek eHome Infrared Transceiver (HP branded) */ 309fbb1f1b0db9b196928157f97515a7ea537310ebcJarod Wilson { USB_DEVICE(VENDOR_FINTEK, 0x5168) }, 31066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Fintek eHome Infrared Transceiver */ 31166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FINTEK, 0x0602) }, 31266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Fintek eHome Infrared Transceiver (in the AOpen MP45) */ 31366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FINTEK, 0x0702) }, 31466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Pinnacle Remote Kit */ 31537dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_PINNACLE, 0x0225), 31637dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .driver_info = MCE_GEN3 }, 31766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Elitegroup Computer Systems IR */ 31866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_ECS, 0x0f38) }, 31966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Wistron Corp. eHome Infrared Receiver */ 32066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_WISTRON, 0x0002) }, 32166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Compro K100 */ 32266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_COMPRO, 0x3020) }, 32366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Compro K100 v2 */ 32466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_COMPRO, 0x3082) }, 32566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Northstar Systems, Inc. eHome Infrared Transceiver */ 32666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) }, 32766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* TiVo PC IR Receiver */ 328d8ee99e79994f916bc5b81990f861ea923e7f332Jarod Wilson { USB_DEVICE(VENDOR_TIVO, 0x2000), 329d8ee99e79994f916bc5b81990f861ea923e7f332Jarod Wilson .driver_info = TIVO_KIT }, 3306f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson /* Conexant Hybrid TV "Shelby" Polaris SDK */ 33137dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab { USB_DEVICE(VENDOR_CONEXANT, 0x58a1), 33237dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab .driver_info = POLARIS_EVK }, 3336f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson /* Conexant Hybrid TV RDU253S Polaris */ 3346f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson { USB_DEVICE(VENDOR_CONEXANT, 0x58a5), 3356f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson .driver_info = CX_HYBRID_TV }, 33666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Terminating entry */ 33766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { } 33866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson}; 33966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 34066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* data structure for each usb transceiver */ 34166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstruct mceusb_dev { 34266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* ir-core bits */ 343d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman struct rc_dev *rc; 3442ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson 3452ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson /* optional features we can enable */ 3462ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson bool carrier_report_enabled; 3472ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson bool learning_enabled; 34866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 34966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* core device bits */ 35066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct device *dev; 35166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 35266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* usb */ 35366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_device *usbdev; 35466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct urb *urb_in; 35566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_endpoint_descriptor *usb_ep_in; 35666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_endpoint_descriptor *usb_ep_out; 35766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 35866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* buffers and dma */ 35966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson unsigned char *buf_in; 36066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson unsigned int len_in; 3612ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson dma_addr_t dma_in; 3622ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson dma_addr_t dma_out; 36339dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab 36439dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab enum { 36539dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab CMD_HEADER = 0, 36639dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab SUBCMD, 36739dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab CMD_DATA, 36839dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab PARSE_IRDATA, 36939dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab } parser_state; 37039dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab 3712ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson u8 cmd, rem; /* Remaining IR data bytes in packet */ 37266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 37366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct { 37466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson u32 connected:1; 375d8cc7fd7e6371026c15254a35e618d2e5c5bf562Jarod Wilson u32 tx_mask_normal:1; 37666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson u32 microsoft_gen1:1; 3776f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson u32 no_tx:1; 37866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } flags; 37966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 380e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* transmit support */ 38166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int send_flags; 382e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson u32 carrier; 383e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson unsigned char tx_mask; 38466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 38566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson char name[128]; 38666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson char phys[64]; 38737dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab enum mceusb_model_type model; 38866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson}; 38966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 39066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* 39166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * MCE Device Command Strings 39266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * Device command responses vary from device to device... 39366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - DEVICE_RESET resets the hardware to its default state 39466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - GET_REVISION fetches the hardware/software revision, common 39566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * replies are ff 0b 45 ff 1b 08 and ff 0b 50 ff 1b 42 39666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - GET_CARRIER_FREQ gets the carrier mode and frequency of the 39766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * device, with replies in the form of 9f 06 MM FF, where MM is 0-3, 39866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * meaning clk of 10000000, 2500000, 625000 or 156250, and FF is 39966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * ((clk / frequency) - 1) 40066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - GET_RX_TIMEOUT fetches the receiver timeout in units of 50us, 40166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * response in the form of 9f 0c msb lsb 40266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - GET_TX_BITMASK fetches the transmitter bitmask, replies in 40366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * the form of 9f 08 bm, where bm is the bitmask 40466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - GET_RX_SENSOR fetches the RX sensor setting -- long-range 40566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * general use one or short-range learning one, in the form of 40666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * 9f 14 ss, where ss is either 01 for long-range or 02 for short 40766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - SET_CARRIER_FREQ sets a new carrier mode and frequency 40866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - SET_TX_BITMASK sets the transmitter bitmask 40966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - SET_RX_TIMEOUT sets the receiver timeout 41066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - SET_RX_SENSOR sets which receiver sensor to use 41166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson */ 4124a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilsonstatic char DEVICE_RESET[] = {MCE_COMMAND_NULL, MCE_HW_CMD_HEADER, 4134a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson MCE_CMD_DEVICE_RESET}; 4144a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilsonstatic char GET_REVISION[] = {MCE_HW_CMD_HEADER, MCE_CMD_G_REVISION}; 4154a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilsonstatic char GET_UNKNOWN[] = {MCE_HW_CMD_HEADER, MCE_CMD_UNKNOWN7}; 4164a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilsonstatic char GET_UNKNOWN2[] = {MCE_COMMAND_HEADER, MCE_CMD_UNKNOWN2}; 4174a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilsonstatic char GET_CARRIER_FREQ[] = {MCE_COMMAND_HEADER, MCE_CMD_G_CARRIER}; 4184a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilsonstatic char GET_RX_TIMEOUT[] = {MCE_COMMAND_HEADER, MCE_CMD_G_TIMEOUT}; 4194a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilsonstatic char GET_TX_BITMASK[] = {MCE_COMMAND_HEADER, MCE_CMD_G_TXMASK}; 4204a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilsonstatic char GET_RX_SENSOR[] = {MCE_COMMAND_HEADER, MCE_CMD_G_RXSENSOR}; 42166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* sub in desired values in lower byte or bytes for full command */ 42266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* FIXME: make use of these for transmit. 4234a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilsonstatic char SET_CARRIER_FREQ[] = {MCE_COMMAND_HEADER, 4244a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson MCE_CMD_S_CARRIER, 0x00, 0x00}; 4254a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilsonstatic char SET_TX_BITMASK[] = {MCE_COMMAND_HEADER, MCE_CMD_S_TXMASK, 0x00}; 4264a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilsonstatic char SET_RX_TIMEOUT[] = {MCE_COMMAND_HEADER, 4274a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson MCE_CMD_S_TIMEOUT, 0x00, 0x00}; 4284a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilsonstatic char SET_RX_SENSOR[] = {MCE_COMMAND_HEADER, 4294a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson MCE_CMD_S_RXSENSOR, 0x00}; 43066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson*/ 43166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 43239dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehabstatic int mceusb_cmdsize(u8 cmd, u8 subcmd) 43339dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab{ 43439dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab int datasize = 0; 43539dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab 43639dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab switch (cmd) { 4374a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_COMMAND_NULL: 4384a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson if (subcmd == MCE_HW_CMD_HEADER) 43939dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab datasize = 1; 44039dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab break; 4414a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_HW_CMD_HEADER: 44239dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab switch (subcmd) { 4434a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_G_REVISION: 44439dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab datasize = 2; 44539dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab break; 44639dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab } 4474a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_COMMAND_HEADER: 44839dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab switch (subcmd) { 4494a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_UNKNOWN: 4504a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_S_CARRIER: 4514a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_S_TIMEOUT: 4522ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson case MCE_RSP_PULSE_COUNT: 45339dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab datasize = 2; 45439dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab break; 4551cd50f25614226e99ac7a1518311e8474ea024e3Jarod Wilson case MCE_CMD_SIG_END: 4564a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_S_TXMASK: 4574a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_S_RXSENSOR: 45839dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab datasize = 1; 45939dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab break; 46039dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab } 46139dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab } 46239dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab return datasize; 46339dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab} 46439dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab 46566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, 46636e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson int offset, int len, bool out) 46766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 46866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson char codes[USB_BUFLEN * 3 + 1]; 46966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson char inout[9]; 47066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson u8 cmd, subcmd, data1, data2; 47166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct device *dev = ir->dev; 47236e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson int i, start, skip = 0; 47336e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson 47436e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson if (!debug) 47536e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson return; 47666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 477657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ 47829b4494b1ff0157c1816ce8e2aea2abfdeb7f763Jarod Wilson if (ir->flags.microsoft_gen1 && !out && !offset) 47936e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson skip = 2; 48066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 48136e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson if (len <= skip) 48266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 48366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 48466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson for (i = 0; i < len && i < USB_BUFLEN; i++) 48536e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson snprintf(codes + i * 3, 4, "%02x ", buf[i + offset] & 0xff); 48666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 48736e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson dev_info(dev, "%sx data: %s(length=%d)\n", 48866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson (out ? "t" : "r"), codes, len); 48966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 49066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (out) 49166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson strcpy(inout, "Request\0"); 49266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson else 49366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson strcpy(inout, "Got\0"); 49466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 49536e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson start = offset + skip; 49636e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson cmd = buf[start] & 0xff; 49736e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson subcmd = buf[start + 1] & 0xff; 49836e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson data1 = buf[start + 2] & 0xff; 49936e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson data2 = buf[start + 3] & 0xff; 50066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 50166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson switch (cmd) { 5024a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_COMMAND_NULL: 5034a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson if ((subcmd == MCE_HW_CMD_HEADER) && 5044a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson (data1 == MCE_CMD_DEVICE_RESET)) 50566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Device reset requested\n"); 50666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson else 50766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Unknown command 0x%02x 0x%02x\n", 50866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson cmd, subcmd); 50966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5104a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_HW_CMD_HEADER: 51166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson switch (subcmd) { 5124a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_G_REVISION: 51366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (len == 2) 51466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Get hw/sw rev?\n"); 51566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson else 51666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "hw/sw rev 0x%02x 0x%02x " 51766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson "0x%02x 0x%02x\n", data1, data2, 51836e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson buf[start + 4], buf[start + 5]); 51966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5204a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_DEVICE_RESET: 52166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Device reset requested\n"); 52266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5234a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_RSP_CMD_INVALID: 52466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Previous command not supported\n"); 52566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5264a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_UNKNOWN7: 5274a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_UNKNOWN9: 52866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson default: 52966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Unknown command 0x%02x 0x%02x\n", 53066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson cmd, subcmd); 53166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 53266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 53366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5344a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_COMMAND_HEADER: 53566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson switch (subcmd) { 5361cd50f25614226e99ac7a1518311e8474ea024e3Jarod Wilson case MCE_CMD_SIG_END: 5371cd50f25614226e99ac7a1518311e8474ea024e3Jarod Wilson dev_info(dev, "End of signal\n"); 5381cd50f25614226e99ac7a1518311e8474ea024e3Jarod Wilson break; 5394a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_PING: 54066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Ping\n"); 54166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5424a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_UNKNOWN: 54366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n", 54466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson data1, data2); 54566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5464a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_S_CARRIER: 54766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "%s carrier mode and freq of " 54866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson "0x%02x 0x%02x\n", inout, data1, data2); 54966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5504a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_G_CARRIER: 55166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Get carrier mode and freq\n"); 55266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5534a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_S_TXMASK: 55466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "%s transmit blaster mask of 0x%02x\n", 55566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson inout, data1); 55666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5574a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_S_TIMEOUT: 55866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* value is in units of 50us, so x*50/100 or x/2 ms */ 55966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "%s receive timeout of %d ms\n", 56066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson inout, ((data1 << 8) | data2) / 2); 56166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5624a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_G_TIMEOUT: 56366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Get receive timeout\n"); 56466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5654a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_G_TXMASK: 56666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Get transmit blaster mask\n"); 56766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5684a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_S_RXSENSOR: 56966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "%s %s-range receive sensor in use\n", 57066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson inout, data1 == 0x02 ? "short" : "long"); 57166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5724a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_G_RXSENSOR: 5732ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson /* aka MCE_RSP_PULSE_COUNT */ 5742ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson if (out) 57566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Get receive sensor\n"); 5762ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson else if (ir->learning_enabled) 5772ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson dev_info(dev, "RX pulse count: %d\n", 57866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ((data1 << 8) | data2)); 57966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5804a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_RSP_CMD_INVALID: 58166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Error! Hardware is likely wedged...\n"); 58266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 5834a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_UNKNOWN2: 5844a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_UNKNOWN3: 5854a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson case MCE_CMD_UNKNOWN5: 58666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson default: 58766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Unknown command 0x%02x 0x%02x\n", 58866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson cmd, subcmd); 58966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 59066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 59166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 59266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson default: 59366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 59466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 59536e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson 59636e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson if (cmd == MCE_IRDATA_TRAILER) 59736e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson dev_info(dev, "End of raw IR data\n"); 59836e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson else if ((cmd != MCE_COMMAND_HEADER) && 59936e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson ((cmd & MCE_COMMAND_MASK) == MCE_COMMAND_IRDATA)) 60036e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson dev_info(dev, "Raw IR data, %d pulse/space samples\n", ir->rem); 60166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 60266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 6037c294402d58e22bb760c0e1a825eea5d582a8f2dJarod Wilsonstatic void mce_async_callback(struct urb *urb, struct pt_regs *regs) 60466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 60566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct mceusb_dev *ir; 60666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int len; 60766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 60866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!urb) 60966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 61066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 61166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir = urb->context; 61266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ir) { 61366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson len = urb->actual_length; 61466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 6155ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(ir->dev, "callback called (status=%d len=%d)\n", 61666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson urb->status, len); 61766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 61836e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true); 61966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 62066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 62166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 62266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 62366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* request incoming or send outgoing usb packet - used to initialize remote */ 62451ea62927e5bbb577360dd92c3f282edbf4cd3f8Jarod Wilsonstatic void mce_request_packet(struct mceusb_dev *ir, unsigned char *data, 62551ea62927e5bbb577360dd92c3f282edbf4cd3f8Jarod Wilson int size, int urb_type) 62666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 62751ea62927e5bbb577360dd92c3f282edbf4cd3f8Jarod Wilson int res, pipe; 62866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct urb *async_urb; 62966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct device *dev = ir->dev; 63066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson unsigned char *async_buf; 63166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 63266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (urb_type == MCEUSB_TX) { 63366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson async_urb = usb_alloc_urb(0, GFP_KERNEL); 63466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (unlikely(!async_urb)) { 63566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_err(dev, "Error, couldn't allocate urb!\n"); 63666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 63766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 63866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 63966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson async_buf = kzalloc(size, GFP_KERNEL); 64066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!async_buf) { 64166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_err(dev, "Error, couldn't allocate buf!\n"); 64266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_free_urb(async_urb); 64366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 64466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 64566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 64666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* outbound data */ 64751ea62927e5bbb577360dd92c3f282edbf4cd3f8Jarod Wilson pipe = usb_sndintpipe(ir->usbdev, 64851ea62927e5bbb577360dd92c3f282edbf4cd3f8Jarod Wilson ir->usb_ep_out->bEndpointAddress); 64951ea62927e5bbb577360dd92c3f282edbf4cd3f8Jarod Wilson usb_fill_int_urb(async_urb, ir->usbdev, pipe, 6507c294402d58e22bb760c0e1a825eea5d582a8f2dJarod Wilson async_buf, size, (usb_complete_t)mce_async_callback, 65151ea62927e5bbb577360dd92c3f282edbf4cd3f8Jarod Wilson ir, ir->usb_ep_out->bInterval); 65266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson memcpy(async_buf, data, size); 65366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 65466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } else if (urb_type == MCEUSB_RX) { 65566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* standard request */ 65666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson async_urb = ir->urb_in; 65766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->send_flags = RECV_FLAG_IN_PROGRESS; 65866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 65966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } else { 66066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_err(dev, "Error! Unknown urb type %d\n", urb_type); 66166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 66266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 66366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 6645ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(dev, "receive request called (size=%#x)\n", size); 66566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 66666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson async_urb->transfer_buffer_length = size; 66766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson async_urb->dev = ir->usbdev; 66866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 66966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson res = usb_submit_urb(async_urb, GFP_ATOMIC); 67066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (res) { 6715ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(dev, "receive request FAILED! (res=%d)\n", res); 67266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 67366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 6745ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(dev, "receive request complete (res=%d)\n", res); 67566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 67666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 67766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) 67866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 67951ea62927e5bbb577360dd92c3f282edbf4cd3f8Jarod Wilson mce_request_packet(ir, data, size, MCEUSB_TX); 68066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 68166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 68266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size) 68366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 68451ea62927e5bbb577360dd92c3f282edbf4cd3f8Jarod Wilson mce_request_packet(ir, data, size, MCEUSB_RX); 68566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 68666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 687e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson/* Send data out the IR blaster port(s) */ 688d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdemanstatic int mceusb_tx_ir(struct rc_dev *dev, int *txbuf, u32 n) 689e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson{ 690d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman struct mceusb_dev *ir = dev->priv; 691e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson int i, ret = 0; 692e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson int count, cmdcount = 0; 693e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson unsigned char *cmdbuf; /* MCE command buffer */ 694e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson long signal_duration = 0; /* Singnal length in us */ 695e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson struct timeval start_time, end_time; 696e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 697e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson do_gettimeofday(&start_time); 698e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 699e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson count = n / sizeof(int); 700e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 701e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL); 702e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if (!cmdbuf) 703e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson return -ENOMEM; 704e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 705e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* MCE tx init header */ 7064a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson cmdbuf[cmdcount++] = MCE_COMMAND_HEADER; 7074a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson cmdbuf[cmdcount++] = MCE_CMD_S_TXMASK; 708e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[cmdcount++] = ir->tx_mask; 709e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 710e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Generate mce packet data */ 711e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) { 712e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson signal_duration += txbuf[i]; 713e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson txbuf[i] = txbuf[i] / MCE_TIME_UNIT; 714e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 715e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson do { /* loop to support long pulses/spaces > 127*50us=6.35ms */ 716e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 717e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Insert mce packet header every 4th entry */ 718e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if ((cmdcount < MCE_CMDBUF_SIZE) && 719e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson (cmdcount - MCE_TX_HEADER_LENGTH) % 720e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson MCE_CODE_LENGTH == 0) 7214a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson cmdbuf[cmdcount++] = MCE_IRDATA_HEADER; 722e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 723e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Insert mce packet data */ 724e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if (cmdcount < MCE_CMDBUF_SIZE) 725e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[cmdcount++] = 726e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson (txbuf[i] < MCE_PULSE_BIT ? 727e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson txbuf[i] : MCE_MAX_PULSE_LENGTH) | 728e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson (i & 1 ? 0x00 : MCE_PULSE_BIT); 729e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson else { 730e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson ret = -EINVAL; 731e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson goto out; 732e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 733e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 734e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) && 735e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson (txbuf[i] -= MCE_MAX_PULSE_LENGTH)); 736e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 737e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 738e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Fix packet length in last header */ 739e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] = 7404a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson MCE_COMMAND_IRDATA + (cmdcount - MCE_TX_HEADER_LENGTH) % 7414a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson MCE_CODE_LENGTH - 1; 742e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 743e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Check if we have room for the empty packet at the end */ 744e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if (cmdcount >= MCE_CMDBUF_SIZE) { 745e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson ret = -EINVAL; 746e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson goto out; 747e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 748e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 749e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* All mce commands end with an empty packet (0x80) */ 7504a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson cmdbuf[cmdcount++] = MCE_IRDATA_TRAILER; 751e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 752e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Transmit the command to the mce device */ 753e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson mce_async_out(ir, cmdbuf, cmdcount); 754e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 755e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* 756e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson * The lircd gap calculation expects the write function to 757e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson * wait the time it takes for the ircommand to be sent before 758e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson * it returns. 759e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson */ 760e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson do_gettimeofday(&end_time); 761e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson signal_duration -= (end_time.tv_usec - start_time.tv_usec) + 762e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson (end_time.tv_sec - start_time.tv_sec) * 1000000; 763e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 764e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* delay with the closest number of ticks */ 765e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson set_current_state(TASK_INTERRUPTIBLE); 766e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson schedule_timeout(usecs_to_jiffies(signal_duration)); 767e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 768e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilsonout: 769e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson kfree(cmdbuf); 770e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson return ret ? ret : n; 771e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson} 772e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 7736f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson/* Sets active IR outputs -- mce devices typically have two */ 774d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdemanstatic int mceusb_set_tx_mask(struct rc_dev *dev, u32 mask) 775657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson{ 776d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman struct mceusb_dev *ir = dev->priv; 777657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson 778d8cc7fd7e6371026c15254a35e618d2e5c5bf562Jarod Wilson if (ir->flags.tx_mask_normal) 779d8cc7fd7e6371026c15254a35e618d2e5c5bf562Jarod Wilson ir->tx_mask = mask; 780d8cc7fd7e6371026c15254a35e618d2e5c5bf562Jarod Wilson else 7814a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson ir->tx_mask = (mask != MCE_DEFAULT_TX_MASK ? 7824a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson mask ^ MCE_DEFAULT_TX_MASK : mask) << 1; 783657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson 784657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson return 0; 785657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson} 786657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson 787e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson/* Sets the send carrier frequency and mode */ 788d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdemanstatic int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier) 789e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson{ 790d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman struct mceusb_dev *ir = dev->priv; 791e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson int clk = 10000000; 792e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson int prescaler = 0, divisor = 0; 7934a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson unsigned char cmdbuf[4] = { MCE_COMMAND_HEADER, 7944a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson MCE_CMD_S_CARRIER, 0x00, 0x00 }; 795e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 796e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Carrier has changed */ 797e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if (ir->carrier != carrier) { 798e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 799e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if (carrier == 0) { 800e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson ir->carrier = carrier; 8011cd50f25614226e99ac7a1518311e8474ea024e3Jarod Wilson cmdbuf[2] = MCE_CMD_SIG_END; 8024a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson cmdbuf[3] = MCE_IRDATA_TRAILER; 8035ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(ir->dev, "%s: disabling carrier " 804e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson "modulation\n", __func__); 805e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); 806e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson return carrier; 807e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 808e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 809e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson for (prescaler = 0; prescaler < 4; ++prescaler) { 810e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson divisor = (clk >> (2 * prescaler)) / carrier; 8114a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson if (divisor <= 0xff) { 812e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson ir->carrier = carrier; 813e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[2] = prescaler; 814e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[3] = divisor; 8155ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(ir->dev, "%s: requesting %u HZ " 816e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson "carrier\n", __func__, carrier); 817e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 818e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Transmit new carrier to mce device */ 819e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); 820e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson return carrier; 821e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 822e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 823e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 824e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson return -EINVAL; 825e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 826e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 827e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 828e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson return carrier; 829e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson} 830e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 8312ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson/* 8322ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson * We don't do anything but print debug spew for many of the command bits 8332ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson * we receive from the hardware, but some of them are useful information 8342ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson * we want to store so that we can use them. 8352ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson */ 8362ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilsonstatic void mceusb_handle_command(struct mceusb_dev *ir, int index) 8372ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson{ 8382ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson u8 hi = ir->buf_in[index + 1] & 0xff; 8392ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson u8 lo = ir->buf_in[index + 2] & 0xff; 8402ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson 8412ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson switch (ir->buf_in[index]) { 8422ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson /* 2-byte return value commands */ 8432ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson case MCE_CMD_S_TIMEOUT: 844b4608faee04047ecb15d2acf276d12e21b170b0dJarod Wilson ir->rc->timeout = US_TO_NS((hi << 8 | lo) / 2); 8452ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson break; 8462ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson 8472ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson /* 1-byte return value commands */ 8482ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson case MCE_CMD_S_TXMASK: 8492ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson ir->tx_mask = hi; 8502ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson break; 8512ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson case MCE_CMD_S_RXSENSOR: 8522ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson ir->learning_enabled = (hi == 0x02); 8532ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson break; 8542ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson default: 8552ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson break; 8562ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson } 8572ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson} 8582ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson 85966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) 86066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 8614651918a4afdd49bdea21d2f919b189ef17a6399Maxim Levitsky DEFINE_IR_RAW_EVENT(rawir); 86239dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab int i = 0; 86366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 86466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ 86566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ir->flags.microsoft_gen1) 86639dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab i = 2; 86766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 86829b4494b1ff0157c1816ce8e2aea2abfdeb7f763Jarod Wilson /* if there's no data, just return now */ 86929b4494b1ff0157c1816ce8e2aea2abfdeb7f763Jarod Wilson if (buf_len <= i) 87029b4494b1ff0157c1816ce8e2aea2abfdeb7f763Jarod Wilson return; 87129b4494b1ff0157c1816ce8e2aea2abfdeb7f763Jarod Wilson 87239dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab for (; i < buf_len; i++) { 87339dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab switch (ir->parser_state) { 87439dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab case SUBCMD: 87539dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]); 87636e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson mceusb_dev_printdata(ir, ir->buf_in, i - 1, 87736e9d2605d430d94c60e4b449c737da1798de3b5Jarod Wilson ir->rem + 2, false); 8782ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson mceusb_handle_command(ir, i); 87939dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab ir->parser_state = CMD_DATA; 88039dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab break; 88139dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab case PARSE_IRDATA: 88266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->rem--; 8835bd9d73c84a519b828f95ce295587b83eab3329eJarod Wilson init_ir_raw_event(&rawir); 88466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0); 88566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK) 886b4608faee04047ecb15d2acf276d12e21b170b0dJarod Wilson * US_TO_NS(MCE_TIME_UNIT); 88766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 8885ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(ir->dev, "Storing %s with duration %d\n", 88966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson rawir.pulse ? "pulse" : "space", 89066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson rawir.duration); 89166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 892d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman ir_raw_event_store_with_filter(ir->rc, &rawir); 89339dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab break; 89439dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab case CMD_DATA: 89539dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab ir->rem--; 89639dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab break; 89739dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab case CMD_HEADER: 89839dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab /* decode mce packets of the form (84),AA,BB,CC,DD */ 89939dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab /* IR data packets can span USB messages - rem */ 90039dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab ir->cmd = ir->buf_in[i]; 9014a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson if ((ir->cmd == MCE_COMMAND_HEADER) || 9024a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson ((ir->cmd & MCE_COMMAND_MASK) != 9034a8839187a613cbc34cf21f4f58ae5d5176ec26dJarod Wilson MCE_COMMAND_IRDATA)) { 90439dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab ir->parser_state = SUBCMD; 90539dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab continue; 90639dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab } 90739dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK); 9082ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson mceusb_dev_printdata(ir, ir->buf_in, 9092ee95db222137429407dfcd6801b0f1a8c689771Jarod Wilson i, ir->rem + 1, false); 9101cd50f25614226e99ac7a1518311e8474ea024e3Jarod Wilson if (ir->rem) 91139dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab ir->parser_state = PARSE_IRDATA; 9125bd9d73c84a519b828f95ce295587b83eab3329eJarod Wilson else 9135bd9d73c84a519b828f95ce295587b83eab3329eJarod Wilson ir_raw_event_reset(ir->rc); 91439dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab break; 91566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 91666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 91739dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab if (ir->parser_state != CMD_HEADER && !ir->rem) 91839dc5c3adf65bf86115aeccd740993256e6a22d4Mauro Carvalho Chehab ir->parser_state = CMD_HEADER; 91966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 9205ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n"); 921d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman ir_raw_event_handle(ir->rc); 92266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 92366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 92466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) 92566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 92666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct mceusb_dev *ir; 92766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int buf_len; 92866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 92966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!urb) 93066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 93166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 93266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir = urb->context; 93366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!ir) { 93466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_unlink_urb(urb); 93566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 93666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 93766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 93866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson buf_len = urb->actual_length; 93966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 94066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { 94166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->send_flags = SEND_FLAG_COMPLETE; 9425ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(ir->dev, "setup answer received %d bytes\n", 94366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson buf_len); 94466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 94566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 94666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson switch (urb->status) { 94766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* success */ 94866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0: 94966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mceusb_process_ir_data(ir, buf_len); 95066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 95166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 95266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case -ECONNRESET: 95366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case -ENOENT: 95466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case -ESHUTDOWN: 95566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_unlink_urb(urb); 95666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 95766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 95866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case -EPIPE: 95966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson default: 9605ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(ir->dev, "Error: urb status = %d\n", urb->status); 96166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 96266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 96366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 96466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_submit_urb(urb, GFP_ATOMIC); 96566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 96666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 96766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mceusb_gen1_init(struct mceusb_dev *ir) 96866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 969ca17a4f0bfc48feb3b4eb3f671a82adfe89530fbMauro Carvalho Chehab int ret; 97022b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson int maxp = ir->len_in; 97166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct device *dev = ir->dev; 972b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson char *data; 973657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson 974657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL); 975657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson if (!data) { 976657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson dev_err(dev, "%s: memory allocation failed!\n", __func__); 977657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson return; 978657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson } 97966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 98066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* 981b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson * This is a strange one. Windows issues a set address to the device 98266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * on the receive control pipe and expect a certain value pair back 98366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson */ 98466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), 98566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0, 986657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson data, USB_CTRL_MSG_SZ, HZ * 3); 9875ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(dev, "%s - ret = %d\n", __func__, ret); 9885ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(dev, "%s - data[0] = %d, data[1] = %d\n", 98966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson __func__, data[0], data[1]); 99066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 99166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* set feature: bit rate 38400 bps */ 99266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), 99366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson USB_REQ_SET_FEATURE, USB_TYPE_VENDOR, 99466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 0xc04e, 0x0000, NULL, 0, HZ * 3); 99566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 9965ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(dev, "%s - ret = %d\n", __func__, ret); 99766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 99866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* bRequest 4: set char length to 8 bits */ 99966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), 100066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 4, USB_TYPE_VENDOR, 100166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 0x0808, 0x0000, NULL, 0, HZ * 3); 10025ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(dev, "%s - retB = %d\n", __func__, ret); 100366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 100466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* bRequest 2: set handshaking to use DTR/DSR */ 100566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), 100666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 2, USB_TYPE_VENDOR, 100766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 0x0000, 0x0100, NULL, 0, HZ * 3); 10085ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(dev, "%s - retC = %d\n", __func__, ret); 1009657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson 101022b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson /* device reset */ 101122b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); 101222b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mce_sync_in(ir, NULL, maxp); 101322b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson 101422b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson /* get hw/sw revision? */ 101522b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); 101622b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mce_sync_in(ir, NULL, maxp); 101722b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson 1018657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson kfree(data); 101966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson}; 102066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 102166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mceusb_gen2_init(struct mceusb_dev *ir) 102266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 102366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int maxp = ir->len_in; 102466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 102566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* device reset */ 102666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); 102766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 102866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 102966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* get hw/sw revision? */ 103066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); 103166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 103266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 103322b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson /* unknown what the next two actually return... */ 103466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN)); 103566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 103622b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2)); 103722b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mce_sync_in(ir, NULL, maxp); 103866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 103966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 104022b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilsonstatic void mceusb_get_parameters(struct mceusb_dev *ir) 104166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 104266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int maxp = ir->len_in; 104366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 104466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* get the carrier and frequency */ 104566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ)); 104666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 104766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 10486f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson if (!ir->flags.no_tx) { 10496f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson /* get the transmitter bitmask */ 10506f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); 10516f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson mce_sync_in(ir, NULL, maxp); 10526f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson } 105366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 105466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* get receiver timeout value */ 105566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); 105666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 105766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 105866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* get receiver sensor setting */ 105966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR)); 106066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 106166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 106266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 1063d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdemanstatic struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir) 106466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 106566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct device *dev = ir->dev; 1066d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman struct rc_dev *rc; 1067d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman int ret; 106866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 1069d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc = rc_allocate_device(); 1070d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman if (!rc) { 1071d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman dev_err(dev, "remote dev allocation failed\n"); 1072d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman goto out; 107366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 107466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 10753459d4553b95084a6390e9b62687488538f33c57Mauro Carvalho Chehab snprintf(ir->name, sizeof(ir->name), "%s (%04x:%04x)", 1076d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman mceusb_model[ir->model].name ? 10775ad1a55542dd69d2c6aa7db5ca79073d693bbfedPaul Bender mceusb_model[ir->model].name : 1078d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman "Media Center Ed. eHome Infrared Remote Transceiver", 107966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson le16_to_cpu(ir->usbdev->descriptor.idVendor), 108066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson le16_to_cpu(ir->usbdev->descriptor.idProduct)); 108166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 108266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_make_path(ir->usbdev, ir->phys, sizeof(ir->phys)); 108366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 1084d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc->input_name = ir->name; 1085d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc->input_phys = ir->phys; 1086d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman usb_to_input_id(ir->usbdev, &rc->input_id); 1087d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc->dev.parent = dev; 1088d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc->priv = ir; 1089d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc->driver_type = RC_DRIVER_IR_RAW; 109052b661449aecc47e652a164c0d8078b31e10aca0Mauro Carvalho Chehab rc->allowed_protos = RC_TYPE_ALL; 1091b4608faee04047ecb15d2acf276d12e21b170b0dJarod Wilson rc->timeout = US_TO_NS(1000); 10926f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson if (!ir->flags.no_tx) { 1093d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc->s_tx_mask = mceusb_set_tx_mask; 1094d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc->s_tx_carrier = mceusb_set_tx_carrier; 1095d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc->tx_ir = mceusb_tx_ir; 10966f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson } 1097d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc->driver_name = DRIVER_NAME; 1098d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc->map_name = mceusb_model[ir->model].rc_map ? 1099d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman mceusb_model[ir->model].rc_map : RC_MAP_RC6_MCE; 110066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 1101d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman ret = rc_register_device(rc); 110266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ret < 0) { 1103d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman dev_err(dev, "remote dev registration failed\n"); 1104d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman goto out; 110566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 110666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 1107d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman return rc; 110866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 1109d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdemanout: 1110d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc_free_device(rc); 111166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return NULL; 111266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 111366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 111466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic int __devinit mceusb_dev_probe(struct usb_interface *intf, 111566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson const struct usb_device_id *id) 111666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 111766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_device *dev = interface_to_usbdev(intf); 111866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_host_interface *idesc; 111966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_endpoint_descriptor *ep = NULL; 112066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_endpoint_descriptor *ep_in = NULL; 112166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_endpoint_descriptor *ep_out = NULL; 112266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct mceusb_dev *ir = NULL; 1123d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson int pipe, maxp, i; 112466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson char buf[63], name[128] = ""; 112537dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab enum mceusb_model_type model = id->driver_info; 112666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson bool is_gen3; 112766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson bool is_microsoft_gen1; 1128d8cc7fd7e6371026c15254a35e618d2e5c5bf562Jarod Wilson bool tx_mask_normal; 1129a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson int ir_intfnum; 113066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 11315ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(&intf->dev, "%s called\n", __func__); 113266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 113366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson idesc = intf->cur_altsetting; 113466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 113537dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab is_gen3 = mceusb_model[model].mce_gen3; 113637dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab is_microsoft_gen1 = mceusb_model[model].mce_gen1; 1137d8cc7fd7e6371026c15254a35e618d2e5c5bf562Jarod Wilson tx_mask_normal = mceusb_model[model].tx_mask_normal; 1138a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson ir_intfnum = mceusb_model[model].ir_intfnum; 113956e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab 1140a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson /* There are multi-function devices with non-IR interfaces */ 1141a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson if (idesc->desc.bInterfaceNumber != ir_intfnum) 1142a6994eb0a706bf36bcb3b5f7e439c5b76c31cfe5Jarod Wilson return -ENODEV; 114366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 114466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* step through the endpoints to find first bulk in and out endpoint */ 114566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { 114666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ep = &idesc->endpoint[i].desc; 114766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 114866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if ((ep_in == NULL) 114966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) 115066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson == USB_DIR_IN) 115166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 115266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson == USB_ENDPOINT_XFER_BULK) 115366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 115466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson == USB_ENDPOINT_XFER_INT))) { 115566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 115666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ep_in = ep; 115766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ep_in->bmAttributes = USB_ENDPOINT_XFER_INT; 1158d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson ep_in->bInterval = 1; 11595ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(&intf->dev, "acceptable inbound endpoint " 1160d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson "found\n"); 116166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 116266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 116366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if ((ep_out == NULL) 116466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) 116566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson == USB_DIR_OUT) 116666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 116766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson == USB_ENDPOINT_XFER_BULK) 116866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 116966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson == USB_ENDPOINT_XFER_INT))) { 117066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 117166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ep_out = ep; 117266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ep_out->bmAttributes = USB_ENDPOINT_XFER_INT; 1173d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson ep_out->bInterval = 1; 11745ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(&intf->dev, "acceptable outbound endpoint " 1175d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson "found\n"); 117666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 117766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 117866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ep_in == NULL) { 11795ae8f9a3757e4010c7ea9c07c047088fb812335eJarod Wilson mce_dbg(&intf->dev, "inbound and/or endpoint not found\n"); 118066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return -ENODEV; 118166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 118266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 118366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress); 118466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 118566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 118666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL); 118766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!ir) 118866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson goto mem_alloc_fail; 118966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 119066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->buf_in = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &ir->dma_in); 119166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!ir->buf_in) 119266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson goto buf_in_alloc_fail; 119366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 119466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); 119566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!ir->urb_in) 119666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson goto urb_in_alloc_fail; 119766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 119866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->usbdev = dev; 119966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->dev = &intf->dev; 120066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->len_in = maxp; 120166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->flags.microsoft_gen1 = is_microsoft_gen1; 1202d8cc7fd7e6371026c15254a35e618d2e5c5bf562Jarod Wilson ir->flags.tx_mask_normal = tx_mask_normal; 12036f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson ir->flags.no_tx = mceusb_model[model].no_tx; 120437dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab ir->model = model; 120537dbd3a64ed6dd62ab5a49dbfcfae7e8ac0413a9Mauro Carvalho Chehab 120666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Saving usb interface data for use by the transmitter routine */ 120766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->usb_ep_in = ep_in; 120866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->usb_ep_out = ep_out; 120966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 121066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (dev->descriptor.iManufacturer 121166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson && usb_string(dev, dev->descriptor.iManufacturer, 121266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson buf, sizeof(buf)) > 0) 121366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson strlcpy(name, buf, sizeof(name)); 121466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (dev->descriptor.iProduct 121566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson && usb_string(dev, dev->descriptor.iProduct, 121666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson buf, sizeof(buf)) > 0) 121766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson snprintf(name + strlen(name), sizeof(name) - strlen(name), 121866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson " %s", buf); 121966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 1220d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman ir->rc = mceusb_init_rc_dev(ir); 1221d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman if (!ir->rc) 1222d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman goto rc_dev_fail; 122366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 1224b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson /* flush buffers on the device */ 1225b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson mce_sync_in(ir, NULL, maxp); 1226b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson mce_sync_in(ir, NULL, maxp); 1227b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson 1228b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson /* wire up inbound data handler */ 122966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, 123066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval); 123166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->urb_in->transfer_dma = ir->dma_in; 123266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 123366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 123466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* initialize device */ 123522b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson if (ir->flags.microsoft_gen1) 123666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mceusb_gen1_init(ir); 123722b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson else if (!is_gen3) 123866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mceusb_gen2_init(ir); 123966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 124022b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mceusb_get_parameters(ir); 124166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 12426f6c625d32852ab2fbfd131ba9a1e5d55ff8032cJarod Wilson if (!ir->flags.no_tx) 1243d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman mceusb_set_tx_mask(ir->rc, MCE_DEFAULT_TX_MASK); 124466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 124566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_set_intfdata(intf, ir); 124666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 124766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(&intf->dev, "Registered %s on usb%d:%d\n", name, 124866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev->bus->busnum, dev->devnum); 124966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 125066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return 0; 125166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 125266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Error-handling path */ 1253d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdemanrc_dev_fail: 125466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_free_urb(ir->urb_in); 125566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonurb_in_alloc_fail: 125666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in); 125766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonbuf_in_alloc_fail: 125866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson kfree(ir); 125966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonmem_alloc_fail: 126066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_err(&intf->dev, "%s: device setup failed!\n", __func__); 126166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 126266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return -ENOMEM; 126366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 126466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 126566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 126666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void __devexit mceusb_dev_disconnect(struct usb_interface *intf) 126766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 126866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_device *dev = interface_to_usbdev(intf); 126966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct mceusb_dev *ir = usb_get_intfdata(intf); 127066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 127166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_set_intfdata(intf, NULL); 127266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 127366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!ir) 127466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 127566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 127666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->usbdev = NULL; 1277d8b4b5822f51e2142b731b42c81e3f03eec475b2David Härdeman rc_unregister_device(ir->rc); 127866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_kill_urb(ir->urb_in); 127966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_free_urb(ir->urb_in); 128066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in); 128166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 128266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson kfree(ir); 128366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 128466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 128566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic int mceusb_dev_suspend(struct usb_interface *intf, pm_message_t message) 128666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 128766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct mceusb_dev *ir = usb_get_intfdata(intf); 128866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(ir->dev, "suspend\n"); 128966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_kill_urb(ir->urb_in); 129066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return 0; 129166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 129266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 129366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic int mceusb_dev_resume(struct usb_interface *intf) 129466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 129566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct mceusb_dev *ir = usb_get_intfdata(intf); 129666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(ir->dev, "resume\n"); 129766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (usb_submit_urb(ir->urb_in, GFP_ATOMIC)) 129866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return -EIO; 129966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return 0; 130066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 130166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 130266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic struct usb_driver mceusb_dev_driver = { 130366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .name = DRIVER_NAME, 130466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .probe = mceusb_dev_probe, 130566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .disconnect = mceusb_dev_disconnect, 130666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .suspend = mceusb_dev_suspend, 130766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .resume = mceusb_dev_resume, 130866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .reset_resume = mceusb_dev_resume, 130966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .id_table = mceusb_dev_table 131066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson}; 131166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 131266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic int __init mceusb_dev_init(void) 131366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 131466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int ret; 131566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 131666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ret = usb_register(&mceusb_dev_driver); 131766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ret < 0) 131866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson printk(KERN_ERR DRIVER_NAME 131966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ": usb register failed, result = %d\n", ret); 132066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 132166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return ret; 132266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 132366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 132466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void __exit mceusb_dev_exit(void) 132566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 132666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_deregister(&mceusb_dev_driver); 132766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 132866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 132966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonmodule_init(mceusb_dev_init); 133066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonmodule_exit(mceusb_dev_exit); 133166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 133266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod WilsonMODULE_DESCRIPTION(DRIVER_DESC); 133366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod WilsonMODULE_AUTHOR(DRIVER_AUTHOR); 133466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod WilsonMODULE_LICENSE("GPL"); 133566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod WilsonMODULE_DEVICE_TABLE(usb, mceusb_dev_table); 133666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 133766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonmodule_param(debug, bool, S_IRUGO | S_IWUSR); 133866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod WilsonMODULE_PARM_DESC(debug, "Debug enabled or not"); 1339