mceusb.c revision 56e92f60c3baa08a66a025ba4ed10c15c4a059cb
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> 3866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#include <linux/usb.h> 3966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#include <linux/input.h> 4066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#include <media/ir-core.h> 4166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#include <media/ir-common.h> 4266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 4366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define DRIVER_VERSION "1.91" 4466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define DRIVER_AUTHOR "Jarod Wilson <jarod@wilsonet.com>" 4566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define DRIVER_DESC "Windows Media Center Ed. eHome Infrared Transceiver " \ 4666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson "device driver" 4766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define DRIVER_NAME "mceusb" 4866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 4966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define USB_BUFLEN 32 /* USB reception buffer length */ 50657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson#define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */ 51657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson#define MCE_G1_INIT_MSGS 40 /* Init messages on gen1 hw to throw out */ 5266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 5366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* MCE constants */ 5466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */ 5566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCE_TIME_UNIT 50 /* Approx 50us resolution */ 5666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */ 5766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */ 5866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCE_PACKET_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */ 5966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCE_CONTROL_HEADER 0x9F /* MCE status header */ 6066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */ 6166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */ 6266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCE_DEFAULT_TX_MASK 0x03 /* Val opts: TX1=0x01, TX2=0x02, ALL=0x03 */ 6366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCE_PULSE_BIT 0x80 /* Pulse bit, MSB set == PULSE else SPACE */ 6466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCE_PULSE_MASK 0x7F /* Pulse mask */ 6566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCE_MAX_PULSE_LENGTH 0x7F /* Longest transmittable pulse symbol */ 66d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson#define MCE_PACKET_LENGTH_MASK 0x1F /* Packet length mask */ 6766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 6866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 6966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* module parameters */ 7066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#ifdef CONFIG_USB_DEBUG 7166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic int debug = 1; 7266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#else 7366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic int debug; 7466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#endif 7566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 7666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* general constants */ 7766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define SEND_FLAG_IN_PROGRESS 1 7866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define SEND_FLAG_COMPLETE 2 7966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define RECV_FLAG_IN_PROGRESS 3 8066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define RECV_FLAG_COMPLETE 4 8166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 8266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCEUSB_RX 1 8366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define MCEUSB_TX 2 8466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 8566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_PHILIPS 0x0471 8666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_SMK 0x0609 8766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_TATUNG 0x1460 8866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_GATEWAY 0x107b 8966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_SHUTTLE 0x1308 9066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_SHUTTLE2 0x051c 9166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_MITSUMI 0x03ee 9266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_TOPSEED 0x1784 9366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_RICAVISION 0x179d 9466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_ITRON 0x195d 9566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_FIC 0x1509 9666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_LG 0x043e 9766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_MICROSOFT 0x045e 9866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_FORMOSA 0x147a 9966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_FINTEK 0x1934 10066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_PINNACLE 0x2304 10166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_ECS 0x1019 10266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_WISTRON 0x0fb8 10366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_COMPRO 0x185b 10466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_NORTHSTAR 0x04eb 10566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_REALTEK 0x0bda 10666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson#define VENDOR_TIVO 0x105a 10756e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab#define VENDOR_CONEXANT 0x0572 10866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 10966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic struct usb_device_id mceusb_dev_table[] = { 11066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Original Microsoft MCE IR Transceiver (often HP-branded) */ 11166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_MICROSOFT, 0x006d) }, 11266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Philips Infrared Transceiver - Sahara branded */ 11366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x0608) }, 11466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Philips Infrared Transceiver - HP branded */ 11566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x060c) }, 11666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Philips SRM5100 */ 11766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x060d) }, 11866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Philips Infrared Transceiver - Omaura */ 11966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x060f) }, 12066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Philips Infrared Transceiver - Spinel plus */ 12166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x0613) }, 12266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Philips eHome Infrared Transceiver */ 12366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x0815) }, 124c13df9cf6b1cad7fd088c9acceb98b6bffd9ca31Jarod Wilson /* Philips/Spinel plus IR transceiver for ASUS */ 125c13df9cf6b1cad7fd088c9acceb98b6bffd9ca31Jarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x206c) }, 126c13df9cf6b1cad7fd088c9acceb98b6bffd9ca31Jarod Wilson /* Philips/Spinel plus IR transceiver for ASUS */ 127c13df9cf6b1cad7fd088c9acceb98b6bffd9ca31Jarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x2088) }, 12866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Realtek MCE IR Receiver */ 12966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_REALTEK, 0x0161) }, 13066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* SMK/Toshiba G83C0004D410 */ 13166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_SMK, 0x031d) }, 13266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* SMK eHome Infrared Transceiver (Sony VAIO) */ 13366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_SMK, 0x0322) }, 13466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* bundled with Hauppauge PVR-150 */ 13566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_SMK, 0x0334) }, 13666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* SMK eHome Infrared Transceiver */ 13766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_SMK, 0x0338) }, 13866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Tatung eHome Infrared Transceiver */ 13966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, 14066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Shuttle eHome Infrared Transceiver */ 14166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_SHUTTLE, 0xc001) }, 14266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Shuttle eHome Infrared Transceiver */ 14366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) }, 14466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Gateway eHome Infrared Transceiver */ 14566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_GATEWAY, 0x3009) }, 14666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Mitsumi */ 14766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_MITSUMI, 0x2501) }, 14866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Topseed eHome Infrared Transceiver */ 14966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x0001) }, 15066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Topseed HP eHome Infrared Transceiver */ 15166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x0006) }, 15266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Topseed eHome Infrared Transceiver */ 15366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x0007) }, 15466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Topseed eHome Infrared Transceiver */ 15566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x0008) }, 15666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Topseed eHome Infrared Transceiver */ 15766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x000a) }, 15866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Topseed eHome Infrared Transceiver */ 15966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x0011) }, 16066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Ricavision internal Infrared Transceiver */ 16166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_RICAVISION, 0x0010) }, 16266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Itron ione Libra Q-11 */ 16366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_ITRON, 0x7002) }, 16466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* FIC eHome Infrared Transceiver */ 16566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FIC, 0x9242) }, 16666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* LG eHome Infrared Transceiver */ 16766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_LG, 0x9803) }, 16866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Microsoft MCE Infrared Transceiver */ 16966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) }, 17066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa eHome Infrared Transceiver */ 17166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe015) }, 17266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa21 / eHome Infrared Receiver */ 17366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, 17466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa aim / Trust MCE Infrared Receiver */ 17566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe017) }, 17666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa Industrial Computing / Beanbag Emulation Device */ 17766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, 17866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa21 / eHome Infrared Receiver */ 17966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe03a) }, 18066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa Industrial Computing AIM IR605/A */ 18166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) }, 18266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Formosa Industrial Computing */ 18366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FORMOSA, 0xe03e) }, 18466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Fintek eHome Infrared Transceiver */ 18566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FINTEK, 0x0602) }, 18666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Fintek eHome Infrared Transceiver (in the AOpen MP45) */ 18766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_FINTEK, 0x0702) }, 18866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Pinnacle Remote Kit */ 18966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PINNACLE, 0x0225) }, 19066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Elitegroup Computer Systems IR */ 19166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_ECS, 0x0f38) }, 19266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Wistron Corp. eHome Infrared Receiver */ 19366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_WISTRON, 0x0002) }, 19466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Compro K100 */ 19566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_COMPRO, 0x3020) }, 19666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Compro K100 v2 */ 19766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_COMPRO, 0x3082) }, 19866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Northstar Systems, Inc. eHome Infrared Transceiver */ 19966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) }, 20066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* TiVo PC IR Receiver */ 20166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_TIVO, 0x2000) }, 20256e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab /* Conexant SDK */ 20356e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab { USB_DEVICE(VENDOR_CONEXANT, 0x58a1) }, 20466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Terminating entry */ 20566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { } 20666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson}; 20766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 20866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic struct usb_device_id gen3_list[] = { 20966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_PINNACLE, 0x0225) }, 21066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x0008) }, 21166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson {} 21266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson}; 21366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 21466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic struct usb_device_id microsoft_gen1_list[] = { 21566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson { USB_DEVICE(VENDOR_MICROSOFT, 0x006d) }, 21666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson {} 21766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson}; 21866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 219657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilsonstatic struct usb_device_id std_tx_mask_list[] = { 220657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson { USB_DEVICE(VENDOR_MICROSOFT, 0x006d) }, 221657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson { USB_DEVICE(VENDOR_PHILIPS, 0x060c) }, 222657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson { USB_DEVICE(VENDOR_SMK, 0x031d) }, 223657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson { USB_DEVICE(VENDOR_SMK, 0x0322) }, 224657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson { USB_DEVICE(VENDOR_SMK, 0x0334) }, 225657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x0001) }, 226657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x0006) }, 227657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x0007) }, 228657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x0008) }, 229657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x000a) }, 230657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson { USB_DEVICE(VENDOR_TOPSEED, 0x0011) }, 231657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson { USB_DEVICE(VENDOR_PINNACLE, 0x0225) }, 232657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson {} 233657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson}; 234657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson 23556e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehabstatic struct usb_device_id cx_polaris_list[] = { 23656e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab { USB_DEVICE(VENDOR_CONEXANT, 0x58a1) }, 23756e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab {} 23856e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab}; 23956e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab 24066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* data structure for each usb transceiver */ 24166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstruct mceusb_dev { 24266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* ir-core bits */ 24366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct ir_dev_props *props; 24466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct ir_raw_event rawir; 24566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 24666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* core device bits */ 24766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct device *dev; 24866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct input_dev *idev; 24966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 25066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* usb */ 25166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_device *usbdev; 25266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct urb *urb_in; 25366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_endpoint_descriptor *usb_ep_in; 25466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_endpoint_descriptor *usb_ep_out; 25566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 25666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* buffers and dma */ 25766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson unsigned char *buf_in; 25866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson unsigned int len_in; 25966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson u8 cmd; /* MCE command type */ 26066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson u8 rem; /* Remaining IR data bytes in packet */ 26166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dma_addr_t dma_in; 26266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dma_addr_t dma_out; 26366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 26466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct { 26566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson u32 connected:1; 266657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson u32 tx_mask_inverted:1; 26766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson u32 microsoft_gen1:1; 26822b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson u32 reserved:29; 26966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } flags; 27066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 271e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* transmit support */ 27266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int send_flags; 273e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson u32 carrier; 274e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson unsigned char tx_mask; 27566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 27666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson char name[128]; 27766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson char phys[64]; 27866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson}; 27966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 28066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* 28166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * MCE Device Command Strings 28266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * Device command responses vary from device to device... 28366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - DEVICE_RESET resets the hardware to its default state 28466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - GET_REVISION fetches the hardware/software revision, common 28566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * replies are ff 0b 45 ff 1b 08 and ff 0b 50 ff 1b 42 28666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - GET_CARRIER_FREQ gets the carrier mode and frequency of the 28766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * device, with replies in the form of 9f 06 MM FF, where MM is 0-3, 28866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * meaning clk of 10000000, 2500000, 625000 or 156250, and FF is 28966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * ((clk / frequency) - 1) 29066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - GET_RX_TIMEOUT fetches the receiver timeout in units of 50us, 29166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * response in the form of 9f 0c msb lsb 29266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - GET_TX_BITMASK fetches the transmitter bitmask, replies in 29366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * the form of 9f 08 bm, where bm is the bitmask 29466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - GET_RX_SENSOR fetches the RX sensor setting -- long-range 29566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * general use one or short-range learning one, in the form of 29666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * 9f 14 ss, where ss is either 01 for long-range or 02 for short 29766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - SET_CARRIER_FREQ sets a new carrier mode and frequency 29866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - SET_TX_BITMASK sets the transmitter bitmask 29966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - SET_RX_TIMEOUT sets the receiver timeout 30066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * - SET_RX_SENSOR sets which receiver sensor to use 30166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson */ 30266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic char DEVICE_RESET[] = {0x00, 0xff, 0xaa}; 30366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic char GET_REVISION[] = {0xff, 0x0b}; 30466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic char GET_UNKNOWN[] = {0xff, 0x18}; 30522b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilsonstatic char GET_UNKNOWN2[] = {0x9f, 0x05}; 30666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic char GET_CARRIER_FREQ[] = {0x9f, 0x07}; 30766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic char GET_RX_TIMEOUT[] = {0x9f, 0x0d}; 30866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic char GET_TX_BITMASK[] = {0x9f, 0x13}; 30966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic char GET_RX_SENSOR[] = {0x9f, 0x15}; 31066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* sub in desired values in lower byte or bytes for full command */ 31166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* FIXME: make use of these for transmit. 31266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic char SET_CARRIER_FREQ[] = {0x9f, 0x06, 0x00, 0x00}; 31366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic char SET_TX_BITMASK[] = {0x9f, 0x08, 0x00}; 31466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic char SET_RX_TIMEOUT[] = {0x9f, 0x0c, 0x00, 0x00}; 31566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic char SET_RX_SENSOR[] = {0x9f, 0x14, 0x00}; 31666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson*/ 31766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 31866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, 31966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int len, bool out) 32066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 32166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson char codes[USB_BUFLEN * 3 + 1]; 32266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson char inout[9]; 32366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int i; 32466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson u8 cmd, subcmd, data1, data2; 32566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct device *dev = ir->dev; 326657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson int idx = 0; 32766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 328657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ 329657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson if (ir->flags.microsoft_gen1 && !out) 330657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson idx = 2; 33166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 332657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson if (len <= idx) 33366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 33466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 33566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson for (i = 0; i < len && i < USB_BUFLEN; i++) 33666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson snprintf(codes + i * 3, 4, "%02x ", buf[i] & 0xFF); 33766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 33866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "%sx data: %s (length=%d)\n", 33966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson (out ? "t" : "r"), codes, len); 34066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 34166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (out) 34266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson strcpy(inout, "Request\0"); 34366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson else 34466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson strcpy(inout, "Got\0"); 34566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 346657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson cmd = buf[idx] & 0xff; 347657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson subcmd = buf[idx + 1] & 0xff; 348657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson data1 = buf[idx + 2] & 0xff; 349657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson data2 = buf[idx + 3] & 0xff; 35066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 35166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson switch (cmd) { 35266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x00: 35366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (subcmd == 0xff && data1 == 0xaa) 35466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Device reset requested\n"); 35566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson else 35666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Unknown command 0x%02x 0x%02x\n", 35766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson cmd, subcmd); 35866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 35966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0xff: 36066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson switch (subcmd) { 36166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x0b: 36266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (len == 2) 36366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Get hw/sw rev?\n"); 36466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson else 36566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "hw/sw rev 0x%02x 0x%02x " 36666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson "0x%02x 0x%02x\n", data1, data2, 367657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson buf[idx + 4], buf[idx + 5]); 36866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 36966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0xaa: 37066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Device reset requested\n"); 37166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 37266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0xfe: 37366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Previous command not supported\n"); 37466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 37566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x18: 37666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x1b: 37766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson default: 37866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Unknown command 0x%02x 0x%02x\n", 37966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson cmd, subcmd); 38066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 38166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 38266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 38366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x9f: 38466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson switch (subcmd) { 38566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x03: 38666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Ping\n"); 38766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 38866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x04: 38966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n", 39066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson data1, data2); 39166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 39266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x06: 39366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "%s carrier mode and freq of " 39466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson "0x%02x 0x%02x\n", inout, data1, data2); 39566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 39666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x07: 39766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Get carrier mode and freq\n"); 39866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 39966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x08: 40066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "%s transmit blaster mask of 0x%02x\n", 40166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson inout, data1); 40266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 40366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x0c: 40466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* value is in units of 50us, so x*50/100 or x/2 ms */ 40566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "%s receive timeout of %d ms\n", 40666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson inout, ((data1 << 8) | data2) / 2); 40766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 40866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x0d: 40966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Get receive timeout\n"); 41066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 41166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x13: 41266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Get transmit blaster mask\n"); 41366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 41466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x14: 41566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "%s %s-range receive sensor in use\n", 41666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson inout, data1 == 0x02 ? "short" : "long"); 41766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 41866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x15: 41966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (len == 2) 42066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Get receive sensor\n"); 42166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson else 42266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Received pulse count is %d\n", 42366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ((data1 << 8) | data2)); 42466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 42566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0xfe: 42666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Error! Hardware is likely wedged...\n"); 42766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 42866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x05: 42966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x09: 43066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0x0f: 43166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson default: 43266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(dev, "Unknown command 0x%02x 0x%02x\n", 43366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson cmd, subcmd); 43466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 43566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 43666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 43766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson default: 43866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 43966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 44066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 44166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 4427c294402d58e22bb760c0e1a825eea5d582a8f2dJarod Wilsonstatic void mce_async_callback(struct urb *urb, struct pt_regs *regs) 44366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 44466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct mceusb_dev *ir; 44566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int len; 44666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 44766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!urb) 44866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 44966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 45066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir = urb->context; 45166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ir) { 45266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson len = urb->actual_length; 45366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 45466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(ir->dev, "callback called (status=%d len=%d)\n", 45566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson urb->status, len); 45666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 45766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (debug) 45866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mceusb_dev_printdata(ir, urb->transfer_buffer, 45966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson len, true); 46066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 46166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 46266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 46366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 46466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson/* request incoming or send outgoing usb packet - used to initialize remote */ 46566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mce_request_packet(struct mceusb_dev *ir, 46666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_endpoint_descriptor *ep, 46766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson unsigned char *data, int size, int urb_type) 46866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 46966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int res; 47066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct urb *async_urb; 47166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct device *dev = ir->dev; 47266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson unsigned char *async_buf; 47366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 47466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (urb_type == MCEUSB_TX) { 47566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson async_urb = usb_alloc_urb(0, GFP_KERNEL); 47666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (unlikely(!async_urb)) { 47766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_err(dev, "Error, couldn't allocate urb!\n"); 47866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 47966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 48066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 48166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson async_buf = kzalloc(size, GFP_KERNEL); 48266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!async_buf) { 48366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_err(dev, "Error, couldn't allocate buf!\n"); 48466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_free_urb(async_urb); 48566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 48666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 48766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 48866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* outbound data */ 48966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_fill_int_urb(async_urb, ir->usbdev, 49066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_sndintpipe(ir->usbdev, ep->bEndpointAddress), 4917c294402d58e22bb760c0e1a825eea5d582a8f2dJarod Wilson async_buf, size, (usb_complete_t)mce_async_callback, 49266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir, ep->bInterval); 49366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson memcpy(async_buf, data, size); 49466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 49566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } else if (urb_type == MCEUSB_RX) { 49666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* standard request */ 49766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson async_urb = ir->urb_in; 49866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->send_flags = RECV_FLAG_IN_PROGRESS; 49966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 50066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } else { 50166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_err(dev, "Error! Unknown urb type %d\n", urb_type); 50266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 50366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 50466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 50566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(dev, "receive request called (size=%#x)\n", size); 50666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 50766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson async_urb->transfer_buffer_length = size; 50866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson async_urb->dev = ir->usbdev; 50966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 51066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson res = usb_submit_urb(async_urb, GFP_ATOMIC); 51166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (res) { 51266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(dev, "receive request FAILED! (res=%d)\n", res); 51366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 51466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 51566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(dev, "receive request complete (res=%d)\n", res); 51666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 51766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 51866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) 51966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 52066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_request_packet(ir, ir->usb_ep_out, data, size, MCEUSB_TX); 52166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 52266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 52366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size) 52466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 52566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX); 52666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 52766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 528e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson/* Send data out the IR blaster port(s) */ 529e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilsonstatic int mceusb_tx_ir(void *priv, int *txbuf, u32 n) 530e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson{ 531e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson struct mceusb_dev *ir = priv; 532e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson int i, ret = 0; 533e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson int count, cmdcount = 0; 534e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson unsigned char *cmdbuf; /* MCE command buffer */ 535e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson long signal_duration = 0; /* Singnal length in us */ 536e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson struct timeval start_time, end_time; 537e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 538e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson do_gettimeofday(&start_time); 539e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 540e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson count = n / sizeof(int); 541e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 542e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL); 543e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if (!cmdbuf) 544e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson return -ENOMEM; 545e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 546e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* MCE tx init header */ 547e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[cmdcount++] = MCE_CONTROL_HEADER; 548e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[cmdcount++] = 0x08; 549e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[cmdcount++] = ir->tx_mask; 550e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 551e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Generate mce packet data */ 552e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) { 553e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson signal_duration += txbuf[i]; 554e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson txbuf[i] = txbuf[i] / MCE_TIME_UNIT; 555e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 556e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson do { /* loop to support long pulses/spaces > 127*50us=6.35ms */ 557e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 558e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Insert mce packet header every 4th entry */ 559e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if ((cmdcount < MCE_CMDBUF_SIZE) && 560e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson (cmdcount - MCE_TX_HEADER_LENGTH) % 561e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson MCE_CODE_LENGTH == 0) 562e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[cmdcount++] = MCE_PACKET_HEADER; 563e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 564e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Insert mce packet data */ 565e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if (cmdcount < MCE_CMDBUF_SIZE) 566e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[cmdcount++] = 567e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson (txbuf[i] < MCE_PULSE_BIT ? 568e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson txbuf[i] : MCE_MAX_PULSE_LENGTH) | 569e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson (i & 1 ? 0x00 : MCE_PULSE_BIT); 570e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson else { 571e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson ret = -EINVAL; 572e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson goto out; 573e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 574e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 575e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) && 576e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson (txbuf[i] -= MCE_MAX_PULSE_LENGTH)); 577e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 578e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 579e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Fix packet length in last header */ 580e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] = 581e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 0x80 + (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH - 1; 582e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 583e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Check if we have room for the empty packet at the end */ 584e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if (cmdcount >= MCE_CMDBUF_SIZE) { 585e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson ret = -EINVAL; 586e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson goto out; 587e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 588e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 589e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* All mce commands end with an empty packet (0x80) */ 590e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[cmdcount++] = 0x80; 591e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 592e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Transmit the command to the mce device */ 593e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson mce_async_out(ir, cmdbuf, cmdcount); 594e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 595e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* 596e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson * The lircd gap calculation expects the write function to 597e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson * wait the time it takes for the ircommand to be sent before 598e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson * it returns. 599e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson */ 600e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson do_gettimeofday(&end_time); 601e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson signal_duration -= (end_time.tv_usec - start_time.tv_usec) + 602e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson (end_time.tv_sec - start_time.tv_sec) * 1000000; 603e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 604e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* delay with the closest number of ticks */ 605e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson set_current_state(TASK_INTERRUPTIBLE); 606e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson schedule_timeout(usecs_to_jiffies(signal_duration)); 607e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 608e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilsonout: 609e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson kfree(cmdbuf); 610e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson return ret ? ret : n; 611e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson} 612e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 613657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson/* Sets active IR outputs -- mce devices typically (all?) have two */ 614657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilsonstatic int mceusb_set_tx_mask(void *priv, u32 mask) 615657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson{ 616657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson struct mceusb_dev *ir = priv; 617657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson 618657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson if (ir->flags.tx_mask_inverted) 619657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson ir->tx_mask = (mask != 0x03 ? mask ^ 0x03 : mask) << 1; 620657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson else 621657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson ir->tx_mask = mask; 622657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson 623657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson return 0; 624657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson} 625657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson 626e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson/* Sets the send carrier frequency and mode */ 627e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilsonstatic int mceusb_set_tx_carrier(void *priv, u32 carrier) 628e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson{ 629e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson struct mceusb_dev *ir = priv; 630e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson int clk = 10000000; 631e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson int prescaler = 0, divisor = 0; 632e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson unsigned char cmdbuf[4] = { 0x9f, 0x06, 0x00, 0x00 }; 633e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 634e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Carrier has changed */ 635e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if (ir->carrier != carrier) { 636e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 637e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if (carrier == 0) { 638e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson ir->carrier = carrier; 639e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[2] = 0x01; 640e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[3] = 0x80; 641e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson dev_dbg(ir->dev, "%s: disabling carrier " 642e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson "modulation\n", __func__); 643e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); 644e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson return carrier; 645e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 646e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 647e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson for (prescaler = 0; prescaler < 4; ++prescaler) { 648e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson divisor = (clk >> (2 * prescaler)) / carrier; 649e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson if (divisor <= 0xFF) { 650e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson ir->carrier = carrier; 651e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[2] = prescaler; 652e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson cmdbuf[3] = divisor; 653e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson dev_dbg(ir->dev, "%s: requesting %u HZ " 654e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson "carrier\n", __func__, carrier); 655e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 656e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson /* Transmit new carrier to mce device */ 657e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); 658e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson return carrier; 659e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 660e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 661e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 662e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson return -EINVAL; 663e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 664e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson } 665e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 666e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson return carrier; 667e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson} 668e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson 66966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) 67066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 6714651918a4afdd49bdea21d2f919b189ef17a6399Maxim Levitsky DEFINE_IR_RAW_EVENT(rawir); 67266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int i, start_index = 0; 673d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson u8 hdr = MCE_CONTROL_HEADER; 67466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 67566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ 67666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ir->flags.microsoft_gen1) 67766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson start_index = 2; 67866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 67966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson for (i = start_index; i < buf_len;) { 68066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ir->rem == 0) { 68166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* decode mce packets of the form (84),AA,BB,CC,DD */ 68266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* IR data packets can span USB messages - rem */ 683d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson hdr = ir->buf_in[i]; 684d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson ir->rem = (hdr & MCE_PACKET_LENGTH_MASK); 685d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson ir->cmd = (hdr & ~MCE_PACKET_LENGTH_MASK); 68666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(ir->dev, "New data. rem: 0x%02x, cmd: 0x%02x\n", 68766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->rem, ir->cmd); 68866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson i++; 68966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 69066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 691d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson /* don't process MCE commands */ 692d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson if (hdr == MCE_CONTROL_HEADER || hdr == 0xff) { 69366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->rem = 0; 69466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 69566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 69666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 69766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson for (; (ir->rem > 0) && (i < buf_len); i++) { 69866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->rem--; 69966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 70066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0); 70166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK) 70266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * MCE_TIME_UNIT * 1000; 70366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 70466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if ((ir->buf_in[i] & MCE_PULSE_MASK) == 0x7f) { 70566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ir->rawir.pulse == rawir.pulse) 70666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->rawir.duration += rawir.duration; 70766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson else { 70866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->rawir.duration = rawir.duration; 70966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->rawir.pulse = rawir.pulse; 71066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 71166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson continue; 71266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 71366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson rawir.duration += ir->rawir.duration; 71466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->rawir.duration = 0; 71566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->rawir.pulse = rawir.pulse; 71666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 71766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(ir->dev, "Storing %s with duration %d\n", 71866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson rawir.pulse ? "pulse" : "space", 71966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson rawir.duration); 72066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 72166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir_raw_event_store(ir->idev, &rawir); 72266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 72366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 72466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ir->buf_in[i] == 0x80 || ir->buf_in[i] == 0x9f) 72566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->rem = 0; 72666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 72766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(ir->dev, "calling ir_raw_event_handle\n"); 72866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir_raw_event_handle(ir->idev); 72966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 73066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 73166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 73266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) 73366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 73466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct mceusb_dev *ir; 73566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int buf_len; 73666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 73766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!urb) 73866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 73966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 74066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir = urb->context; 74166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!ir) { 74266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_unlink_urb(urb); 74366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 74466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 74566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 74666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson buf_len = urb->actual_length; 74766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 74866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (debug) 74966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mceusb_dev_printdata(ir, urb->transfer_buffer, buf_len, false); 75066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 75166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { 75266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->send_flags = SEND_FLAG_COMPLETE; 7537a9fcb41b9370a32bb65bece9afc83701ab2d2b6Jarod Wilson dev_dbg(ir->dev, "setup answer received %d bytes\n", 75466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson buf_len); 75566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 75666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 75766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson switch (urb->status) { 75866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* success */ 75966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case 0: 76066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mceusb_process_ir_data(ir, buf_len); 76166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 76266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 76366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case -ECONNRESET: 76466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case -ENOENT: 76566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case -ESHUTDOWN: 76666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_unlink_urb(urb); 76766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 76866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 76966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson case -EPIPE: 77066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson default: 77166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson break; 77266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 77366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 77466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_submit_urb(urb, GFP_ATOMIC); 77566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 77666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 77766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mceusb_gen1_init(struct mceusb_dev *ir) 77866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 779ca17a4f0bfc48feb3b4eb3f671a82adfe89530fbMauro Carvalho Chehab int ret; 78022b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson int maxp = ir->len_in; 78166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct device *dev = ir->dev; 782b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson char *data; 783657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson 784657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL); 785657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson if (!data) { 786657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson dev_err(dev, "%s: memory allocation failed!\n", __func__); 787657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson return; 788657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson } 78966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 79066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* 791b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson * This is a strange one. Windows issues a set address to the device 79266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson * on the receive control pipe and expect a certain value pair back 79366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson */ 79466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), 79566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0, 796657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson data, USB_CTRL_MSG_SZ, HZ * 3); 79766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(dev, "%s - ret = %d\n", __func__, ret); 79866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(dev, "%s - data[0] = %d, data[1] = %d\n", 79966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson __func__, data[0], data[1]); 80066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 80166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* set feature: bit rate 38400 bps */ 80266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), 80366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson USB_REQ_SET_FEATURE, USB_TYPE_VENDOR, 80466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 0xc04e, 0x0000, NULL, 0, HZ * 3); 80566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 80666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(dev, "%s - ret = %d\n", __func__, ret); 80766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 80866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* bRequest 4: set char length to 8 bits */ 80966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), 81066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 4, USB_TYPE_VENDOR, 81166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 0x0808, 0x0000, NULL, 0, HZ * 3); 81266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(dev, "%s - retB = %d\n", __func__, ret); 81366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 81466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* bRequest 2: set handshaking to use DTR/DSR */ 81566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), 81666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 2, USB_TYPE_VENDOR, 81766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 0x0000, 0x0100, NULL, 0, HZ * 3); 81866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(dev, "%s - retC = %d\n", __func__, ret); 819657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson 82022b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson /* device reset */ 82122b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); 82222b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mce_sync_in(ir, NULL, maxp); 82322b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson 82422b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson /* get hw/sw revision? */ 82522b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); 82622b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mce_sync_in(ir, NULL, maxp); 82722b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson 828657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson kfree(data); 82966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson}; 83066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 83166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void mceusb_gen2_init(struct mceusb_dev *ir) 83266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 83366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int maxp = ir->len_in; 83466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 83566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* device reset */ 83666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); 83766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 83866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 83966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* get hw/sw revision? */ 84066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); 84166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 84266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 84322b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson /* unknown what the next two actually return... */ 84466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN)); 84566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 84622b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2)); 84722b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mce_sync_in(ir, NULL, maxp); 84866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 84966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 85022b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilsonstatic void mceusb_get_parameters(struct mceusb_dev *ir) 85166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 85266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int maxp = ir->len_in; 85366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 85466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* get the carrier and frequency */ 85566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ)); 85666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 85766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 85866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* get the transmitter bitmask */ 85966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); 86066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 86166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 86266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* get receiver timeout value */ 86366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); 86466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 86566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 86666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* get receiver sensor setting */ 86766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR)); 86866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mce_sync_in(ir, NULL, maxp); 86966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 87066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 87166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) 87266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 87366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct input_dev *idev; 87466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct ir_dev_props *props; 87566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct device *dev = ir->dev; 87666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int ret = -ENODEV; 87766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 87866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson idev = input_allocate_device(); 87966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!idev) { 88066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_err(dev, "remote input dev allocation failed\n"); 88166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson goto idev_alloc_failed; 88266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 88366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 88466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ret = -ENOMEM; 88566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); 88666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!props) { 88766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_err(dev, "remote ir dev props allocation failed\n"); 88866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson goto props_alloc_failed; 88966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 89066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 891e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome " 89266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson "Infrared Remote Transceiver (%04x:%04x)", 89366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson le16_to_cpu(ir->usbdev->descriptor.idVendor), 89466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson le16_to_cpu(ir->usbdev->descriptor.idProduct)); 89566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 89666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson idev->name = ir->name; 89766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_make_path(ir->usbdev, ir->phys, sizeof(ir->phys)); 89866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson strlcat(ir->phys, "/input0", sizeof(ir->phys)); 89966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson idev->phys = ir->phys; 90066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 90166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson props->priv = ir; 90266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson props->driver_type = RC_DRIVER_IR_RAW; 90366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson props->allowed_protos = IR_TYPE_ALL; 904e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson props->s_tx_mask = mceusb_set_tx_mask; 905e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson props->s_tx_carrier = mceusb_set_tx_carrier; 906e23fb9643bd440fee9106e6df76f01a57db2613cJarod Wilson props->tx_ir = mceusb_tx_ir; 90766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 90866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->props = props; 90966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 91066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ret = ir_input_register(idev, RC_MAP_RC6_MCE, props, DRIVER_NAME); 91166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ret < 0) { 91266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_err(dev, "remote input device register failed\n"); 91366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson goto irdev_failed; 91466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 91566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 91666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return idev; 91766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 91866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonirdev_failed: 91966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson kfree(props); 92066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonprops_alloc_failed: 92166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson input_free_device(idev); 92266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonidev_alloc_failed: 92366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return NULL; 92466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 92566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 92666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic int __devinit mceusb_dev_probe(struct usb_interface *intf, 92766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson const struct usb_device_id *id) 92866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 92966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_device *dev = interface_to_usbdev(intf); 93066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_host_interface *idesc; 93166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_endpoint_descriptor *ep = NULL; 93266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_endpoint_descriptor *ep_in = NULL; 93366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_endpoint_descriptor *ep_out = NULL; 93466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct mceusb_dev *ir = NULL; 935d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson int pipe, maxp, i; 93666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson char buf[63], name[128] = ""; 93766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson bool is_gen3; 93866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson bool is_microsoft_gen1; 939657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson bool tx_mask_inverted; 94056e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab bool is_polaris; 94166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 94266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(&intf->dev, ": %s called\n", __func__); 94366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 94466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson idesc = intf->cur_altsetting; 94566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 94666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0; 94766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson is_microsoft_gen1 = usb_match_id(intf, microsoft_gen1_list) ? 1 : 0; 948657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson tx_mask_inverted = usb_match_id(intf, std_tx_mask_list) ? 0 : 1; 94956e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab is_polaris = usb_match_id(intf, cx_polaris_list) ? 1 : 0; 95056e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab 95156e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab if (is_polaris) { 95256e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab /* Interface 0 is IR */ 95356e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab if (idesc->desc.bInterfaceNumber) 95456e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab return -ENODEV; 95556e92f60c3baa08a66a025ba4ed10c15c4a059cbMauro Carvalho Chehab } 95666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 95766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* step through the endpoints to find first bulk in and out endpoint */ 95866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { 95966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ep = &idesc->endpoint[i].desc; 96066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 96166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if ((ep_in == NULL) 96266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) 96366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson == USB_DIR_IN) 96466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 96566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson == USB_ENDPOINT_XFER_BULK) 96666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 96766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson == USB_ENDPOINT_XFER_INT))) { 96866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 96966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ep_in = ep; 97066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ep_in->bmAttributes = USB_ENDPOINT_XFER_INT; 971d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson ep_in->bInterval = 1; 972d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson dev_dbg(&intf->dev, ": acceptable inbound endpoint " 973d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson "found\n"); 97466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 97566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 97666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if ((ep_out == NULL) 97766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) 97866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson == USB_DIR_OUT) 97966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 98066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson == USB_ENDPOINT_XFER_BULK) 98166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 98266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson == USB_ENDPOINT_XFER_INT))) { 98366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 98466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ep_out = ep; 98566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ep_out->bmAttributes = USB_ENDPOINT_XFER_INT; 986d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson ep_out->bInterval = 1; 987d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson dev_dbg(&intf->dev, ": acceptable outbound endpoint " 988d732a72de4f7dfe69eb8028da0f7cfd1852fb7dcJarod Wilson "found\n"); 98966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 99066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 99166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ep_in == NULL) { 99266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_dbg(&intf->dev, ": inbound and/or endpoint not found\n"); 99366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return -ENODEV; 99466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson } 99566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 99666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress); 99766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); 99866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 99966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL); 100066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!ir) 100166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson goto mem_alloc_fail; 100266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 100366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->buf_in = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &ir->dma_in); 100466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!ir->buf_in) 100566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson goto buf_in_alloc_fail; 100666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 100766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); 100866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!ir->urb_in) 100966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson goto urb_in_alloc_fail; 101066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 101166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->usbdev = dev; 101266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->dev = &intf->dev; 101366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->len_in = maxp; 101466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->flags.microsoft_gen1 = is_microsoft_gen1; 1015657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson ir->flags.tx_mask_inverted = tx_mask_inverted; 10164651918a4afdd49bdea21d2f919b189ef17a6399Maxim Levitsky init_ir_raw_event(&ir->rawir); 101766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 101866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Saving usb interface data for use by the transmitter routine */ 101966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->usb_ep_in = ep_in; 102066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->usb_ep_out = ep_out; 102166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 102266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (dev->descriptor.iManufacturer 102366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson && usb_string(dev, dev->descriptor.iManufacturer, 102466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson buf, sizeof(buf)) > 0) 102566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson strlcpy(name, buf, sizeof(name)); 102666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (dev->descriptor.iProduct 102766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson && usb_string(dev, dev->descriptor.iProduct, 102866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson buf, sizeof(buf)) > 0) 102966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson snprintf(name + strlen(name), sizeof(name) - strlen(name), 103066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson " %s", buf); 103166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 103266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->idev = mceusb_init_input_dev(ir); 103366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!ir->idev) 103466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson goto input_dev_fail; 103566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 1036b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson /* flush buffers on the device */ 1037b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson mce_sync_in(ir, NULL, maxp); 1038b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson mce_sync_in(ir, NULL, maxp); 1039b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson 1040b48592e496e55e4e3e6e7f27d5ba3a229a1db7a6Jarod Wilson /* wire up inbound data handler */ 104166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, 104266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval); 104366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->urb_in->transfer_dma = ir->dma_in; 104466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 104566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 104666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* initialize device */ 104722b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson if (ir->flags.microsoft_gen1) 104866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mceusb_gen1_init(ir); 104922b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson else if (!is_gen3) 105066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson mceusb_gen2_init(ir); 105166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 105222b0766b62d517a597d8155d828c5f93e3523cfaJarod Wilson mceusb_get_parameters(ir); 105366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 1054657290b63efabfbb2862a6089c3fd5dbcc8e9037Jarod Wilson mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK); 105566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 105666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_set_intfdata(intf, ir); 105766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 105866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(&intf->dev, "Registered %s on usb%d:%d\n", name, 105966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev->bus->busnum, dev->devnum); 106066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 106166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return 0; 106266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 106366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson /* Error-handling path */ 106466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsoninput_dev_fail: 106566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_free_urb(ir->urb_in); 106666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonurb_in_alloc_fail: 106766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in); 106866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonbuf_in_alloc_fail: 106966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson kfree(ir); 107066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonmem_alloc_fail: 107166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_err(&intf->dev, "%s: device setup failed!\n", __func__); 107266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 107366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return -ENOMEM; 107466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 107566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 107666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 107766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void __devexit mceusb_dev_disconnect(struct usb_interface *intf) 107866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 107966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct usb_device *dev = interface_to_usbdev(intf); 108066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct mceusb_dev *ir = usb_get_intfdata(intf); 108166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 108266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_set_intfdata(intf, NULL); 108366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 108466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (!ir) 108566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return; 108666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 108766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ir->usbdev = NULL; 1088bd3881b1cedbe6733097bd87da069bd174cc7052Jarod Wilson ir_input_unregister(ir->idev); 108966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_kill_urb(ir->urb_in); 109066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_free_urb(ir->urb_in); 109166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in); 109266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 109366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson kfree(ir); 109466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 109566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 109666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic int mceusb_dev_suspend(struct usb_interface *intf, pm_message_t message) 109766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 109866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct mceusb_dev *ir = usb_get_intfdata(intf); 109966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(ir->dev, "suspend\n"); 110066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_kill_urb(ir->urb_in); 110166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return 0; 110266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 110366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 110466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic int mceusb_dev_resume(struct usb_interface *intf) 110566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 110666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson struct mceusb_dev *ir = usb_get_intfdata(intf); 110766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson dev_info(ir->dev, "resume\n"); 110866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (usb_submit_urb(ir->urb_in, GFP_ATOMIC)) 110966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return -EIO; 111066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return 0; 111166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 111266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 111366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic struct usb_driver mceusb_dev_driver = { 111466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .name = DRIVER_NAME, 111566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .probe = mceusb_dev_probe, 111666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .disconnect = mceusb_dev_disconnect, 111766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .suspend = mceusb_dev_suspend, 111866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .resume = mceusb_dev_resume, 111966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .reset_resume = mceusb_dev_resume, 112066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson .id_table = mceusb_dev_table 112166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson}; 112266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 112366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic int __init mceusb_dev_init(void) 112466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 112566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson int ret; 112666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 112766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ret = usb_register(&mceusb_dev_driver); 112866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson if (ret < 0) 112966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson printk(KERN_ERR DRIVER_NAME 113066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson ": usb register failed, result = %d\n", ret); 113166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 113266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson return ret; 113366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 113466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 113566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonstatic void __exit mceusb_dev_exit(void) 113666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson{ 113766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson usb_deregister(&mceusb_dev_driver); 113866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson} 113966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 114066e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonmodule_init(mceusb_dev_init); 114166e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonmodule_exit(mceusb_dev_exit); 114266e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 114366e89522aff70fb2701ba8f6845fdcd365dd2adeJarod WilsonMODULE_DESCRIPTION(DRIVER_DESC); 114466e89522aff70fb2701ba8f6845fdcd365dd2adeJarod WilsonMODULE_AUTHOR(DRIVER_AUTHOR); 114566e89522aff70fb2701ba8f6845fdcd365dd2adeJarod WilsonMODULE_LICENSE("GPL"); 114666e89522aff70fb2701ba8f6845fdcd365dd2adeJarod WilsonMODULE_DEVICE_TABLE(usb, mceusb_dev_table); 114766e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilson 114866e89522aff70fb2701ba8f6845fdcd365dd2adeJarod Wilsonmodule_param(debug, bool, S_IRUGO | S_IWUSR); 114966e89522aff70fb2701ba8f6845fdcd365dd2adeJarod WilsonMODULE_PARM_DESC(debug, "Debug enabled or not"); 1150