diff options
Diffstat (limited to 'drivers/media/rc')
| -rw-r--r-- | drivers/media/rc/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/media/rc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/media/rc/ene_ir.c | 4 | ||||
| -rw-r--r-- | drivers/media/rc/ene_ir.h | 2 | ||||
| -rw-r--r-- | drivers/media/rc/fintek-cir.c | 5 | ||||
| -rw-r--r-- | drivers/media/rc/imon.c | 19 | ||||
| -rw-r--r-- | drivers/media/rc/ir-lirc-codec.c | 15 | ||||
| -rw-r--r-- | drivers/media/rc/ir-mce_kbd-decoder.c | 449 | ||||
| -rw-r--r-- | drivers/media/rc/ir-raw.c | 5 | ||||
| -rw-r--r-- | drivers/media/rc/ite-cir.c | 18 | ||||
| -rw-r--r-- | drivers/media/rc/ite-cir.h | 3 | ||||
| -rw-r--r-- | drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c | 58 | ||||
| -rw-r--r-- | drivers/media/rc/keymaps/rc-rc6-mce.c | 3 | ||||
| -rw-r--r-- | drivers/media/rc/lirc_dev.c | 37 | ||||
| -rw-r--r-- | drivers/media/rc/mceusb.c | 99 | ||||
| -rw-r--r-- | drivers/media/rc/nuvoton-cir.c | 16 | ||||
| -rw-r--r-- | drivers/media/rc/nuvoton-cir.h | 1 | ||||
| -rw-r--r-- | drivers/media/rc/rc-core-priv.h | 18 | ||||
| -rw-r--r-- | drivers/media/rc/rc-loopback.c | 13 | ||||
| -rw-r--r-- | drivers/media/rc/rc-main.c | 52 | ||||
| -rw-r--r-- | drivers/media/rc/redrat3.c | 63 | ||||
| -rw-r--r-- | drivers/media/rc/winbond-cir.c | 28 | 
22 files changed, 703 insertions, 217 deletions
| diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 7d4bbc226d06..899f783d92fb 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -87,6 +87,17 @@ config IR_RC5_SZ_DECODER  	   uses an IR protocol that is almost standard RC-5, but not quite,  	   as it uses an additional bit). +config IR_MCE_KBD_DECODER +	tristate "Enable IR raw decoder for the MCE keyboard/mouse protocol" +	depends on RC_CORE +	select BITREVERSE +	default y + +	---help--- +	   Enable this option if you have a Microsoft Remote Keyboard for +	   Windows Media Center Edition, which you would like to use with +	   a raw IR receiver in your system. +  config IR_LIRC_CODEC  	tristate "Enable IR to LIRC bridge"  	depends on RC_CORE diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 52830e5f4eaa..f224db027c41 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o  obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o  obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o  obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o +obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o  obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o  # stand-alone IR receivers/transmitters diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index a43ed6c41bfc..2b9c2569d74a 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -953,13 +953,13 @@ static void ene_set_idle(struct rc_dev *rdev, bool idle)  }  /* outside interface: transmit */ -static int ene_transmit(struct rc_dev *rdev, int *buf, u32 n) +static int ene_transmit(struct rc_dev *rdev, unsigned *buf, unsigned n)  {  	struct ene_device *dev = rdev->priv;  	unsigned long flags;  	dev->tx_buffer = buf; -	dev->tx_len = n / sizeof(int); +	dev->tx_len = n;  	dev->tx_pos = 0;  	dev->tx_reg = 0;  	dev->tx_done = 0; diff --git a/drivers/media/rc/ene_ir.h b/drivers/media/rc/ene_ir.h index 337a41d4450b..017c209cdf8a 100644 --- a/drivers/media/rc/ene_ir.h +++ b/drivers/media/rc/ene_ir.h @@ -235,7 +235,7 @@ struct ene_device {  	bool tx_sample_pulse;			/* current sample is pulse */  	/* TX buffer */ -	int *tx_buffer;				/* input samples buffer*/ +	unsigned *tx_buffer;			/* input samples buffer*/  	int tx_pos;				/* position in that bufer */  	int tx_len;				/* current len of tx buffer */  	int tx_done;				/* done transmitting */ diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c index 8fa539dde1b4..7f7079b12f23 100644 --- a/drivers/media/rc/fintek-cir.c +++ b/drivers/media/rc/fintek-cir.c @@ -597,12 +597,17 @@ static void __devexit fintek_remove(struct pnp_dev *pdev)  static int fintek_suspend(struct pnp_dev *pdev, pm_message_t state)  {  	struct fintek_dev *fintek = pnp_get_drvdata(pdev); +	unsigned long flags;  	fit_dbg("%s called", __func__); +	spin_lock_irqsave(&fintek->fintek_lock, flags); +  	/* disable all CIR interrupts */  	fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS); +	spin_unlock_irqrestore(&fintek->fintek_lock, flags); +  	fintek_config_mode_enable(fintek);  	/* disable cir logical dev */ diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c index 3f3c70716268..6bc35eeb653b 100644 --- a/drivers/media/rc/imon.c +++ b/drivers/media/rc/imon.c @@ -307,6 +307,14 @@ static const struct {  	/* 0xffdc iMON MCE VFD */  	{ 0x00010000ffffffeell, KEY_VOLUMEUP },  	{ 0x01000000ffffffeell, KEY_VOLUMEDOWN }, +	{ 0x00000001ffffffeell, KEY_MUTE }, +	{ 0x0000000fffffffeell, KEY_MEDIA }, +	{ 0x00000012ffffffeell, KEY_UP }, +	{ 0x00000013ffffffeell, KEY_DOWN }, +	{ 0x00000014ffffffeell, KEY_LEFT }, +	{ 0x00000015ffffffeell, KEY_RIGHT }, +	{ 0x00000016ffffffeell, KEY_ENTER }, +	{ 0x00000017ffffffeell, KEY_ESC },  	/* iMON Knob values */  	{ 0x000100ffffffffeell, KEY_VOLUMEUP },  	{ 0x010000ffffffffeell, KEY_VOLUMEDOWN }, @@ -1582,16 +1590,16 @@ static void imon_incoming_packet(struct imon_context *ictx,  	/* Only panel type events left to process now */  	spin_lock_irqsave(&ictx->kc_lock, flags); +	do_gettimeofday(&t);  	/* KEY_MUTE repeats from knob need to be suppressed */  	if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) { -		do_gettimeofday(&t);  		msec = tv2int(&t, &prev_time); -		prev_time = t;  		if (msec < ictx->idev->rep[REP_DELAY]) {  			spin_unlock_irqrestore(&ictx->kc_lock, flags);  			return;  		}  	} +	prev_time = t;  	kc = ictx->kc;  	spin_unlock_irqrestore(&ictx->kc_lock, flags); @@ -1603,7 +1611,9 @@ static void imon_incoming_packet(struct imon_context *ictx,  	input_report_key(ictx->idev, kc, 0);  	input_sync(ictx->idev); +	spin_lock_irqsave(&ictx->kc_lock, flags);  	ictx->last_keycode = kc; +	spin_unlock_irqrestore(&ictx->kc_lock, flags);  	return; @@ -1740,6 +1750,8 @@ static void imon_get_ffdc_type(struct imon_context *ictx)  		detected_display_type = IMON_DISPLAY_TYPE_VFD;  		break;  	/* iMON VFD, MCE IR */ +	case 0x46: +	case 0x7e:  	case 0x9e:  		dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR");  		detected_display_type = IMON_DISPLAY_TYPE_VFD; @@ -1755,6 +1767,9 @@ static void imon_get_ffdc_type(struct imon_context *ictx)  		dev_info(ictx->dev, "Unknown 0xffdc device, "  			 "defaulting to VFD and iMON IR");  		detected_display_type = IMON_DISPLAY_TYPE_VFD; +		/* We don't know which one it is, allow user to set the +		 * RC6 one from userspace if OTHER wasn't correct. */ +		allowed_protos |= RC_TYPE_RC6;  		break;  	} diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index 1c5cc65ea1e1..e5eeec4da76e 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -103,19 +103,19 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,  {  	struct lirc_codec *lirc;  	struct rc_dev *dev; -	int *txbuf; /* buffer with values to transmit */ -	int ret = 0; +	unsigned int *txbuf; /* buffer with values to transmit */ +	ssize_t ret = 0;  	size_t count;  	lirc = lirc_get_pdata(file);  	if (!lirc)  		return -EFAULT; -	if (n % sizeof(int)) +	if (n < sizeof(unsigned) || n % sizeof(unsigned))  		return -EINVAL; -	count = n / sizeof(int); -	if (count > LIRCBUF_SIZE || count % 2 == 0 || n % sizeof(int) != 0) +	count = n / sizeof(unsigned); +	if (count > LIRCBUF_SIZE || count % 2 == 0)  		return -EINVAL;  	txbuf = memdup_user(buf, n); @@ -129,7 +129,10 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,  	}  	if (dev->tx_ir) -		ret = dev->tx_ir(dev, txbuf, (u32)n); +		ret = dev->tx_ir(dev, txbuf, count); + +	if (ret > 0) +		ret *= sizeof(unsigned);  out:  	kfree(txbuf); diff --git a/drivers/media/rc/ir-mce_kbd-decoder.c b/drivers/media/rc/ir-mce_kbd-decoder.c new file mode 100644 index 000000000000..3784ebf80ec7 --- /dev/null +++ b/drivers/media/rc/ir-mce_kbd-decoder.c @@ -0,0 +1,449 @@ +/* ir-mce_kbd-decoder.c - A decoder for the RC6-ish keyboard/mouse IR protocol + * used by the Microsoft Remote Keyboard for Windows Media Center Edition, + * referred to by Microsoft's Windows Media Center remote specification docs + * as "an internal protocol called MCIR-2". + * + * Copyright (C) 2011 by Jarod Wilson <jarod@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ +#include <linux/module.h> + +#include "rc-core-priv.h" + +/* + * This decoder currently supports: + * - MCIR-2 29-bit IR signals used for mouse movement and buttons + * - MCIR-2 32-bit IR signals used for standard keyboard keys + * + * The media keys on the keyboard send RC-6 signals that are inditinguishable + * from the keys of the same name on the stock MCE remote, and will be handled + * by the standard RC-6 decoder, and be made available to the system via the + * input device for the remote, rather than the keyboard/mouse one. + */ + +#define MCIR2_UNIT		333333	/* ns */ +#define MCIR2_HEADER_NBITS	5 +#define MCIR2_MOUSE_NBITS	29 +#define MCIR2_KEYBOARD_NBITS	32 +#define MCIR2_PREFIX_PULSE	(8 * MCIR2_UNIT) +#define MCIR2_PREFIX_SPACE	(1 * MCIR2_UNIT) +#define MCIR2_MAX_LEN		(3 * MCIR2_UNIT) +#define MCIR2_BIT_START		(1 * MCIR2_UNIT) +#define MCIR2_BIT_END		(1 * MCIR2_UNIT) +#define MCIR2_BIT_0		(1 * MCIR2_UNIT) +#define MCIR2_BIT_SET		(2 * MCIR2_UNIT) +#define MCIR2_MODE_MASK		0xf	/* for the header bits */ +#define MCIR2_KEYBOARD_HEADER	0x4 +#define MCIR2_MOUSE_HEADER	0x1 +#define MCIR2_MASK_KEYS_START	0xe0 + +enum mce_kbd_mode { +	MCIR2_MODE_KEYBOARD, +	MCIR2_MODE_MOUSE, +	MCIR2_MODE_UNKNOWN, +}; + +enum mce_kbd_state { +	STATE_INACTIVE, +	STATE_HEADER_BIT_START, +	STATE_HEADER_BIT_END, +	STATE_BODY_BIT_START, +	STATE_BODY_BIT_END, +	STATE_FINISHED, +}; + +static unsigned char kbd_keycodes[256] = { +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_A, +	KEY_B,		KEY_C,		KEY_D,		KEY_E,		KEY_F, +	KEY_G,		KEY_H,		KEY_I,		KEY_J,		KEY_K, +	KEY_L,		KEY_M,		KEY_N,		KEY_O,		KEY_P, +	KEY_Q,		KEY_R,		KEY_S,		KEY_T,		KEY_U, +	KEY_V,		KEY_W,		KEY_X,		KEY_Y,		KEY_Z, +	KEY_1,		KEY_2,		KEY_3,		KEY_4,		KEY_5, +	KEY_6,		KEY_7,		KEY_8,		KEY_9,		KEY_0, +	KEY_ENTER,	KEY_ESC,	KEY_BACKSPACE,	KEY_TAB,	KEY_SPACE, +	KEY_MINUS,	KEY_EQUAL,	KEY_LEFTBRACE,	KEY_RIGHTBRACE,	KEY_BACKSLASH, +	KEY_RESERVED,	KEY_SEMICOLON,	KEY_APOSTROPHE,	KEY_GRAVE,	KEY_COMMA, +	KEY_DOT,	KEY_SLASH,	KEY_CAPSLOCK,	KEY_F1,		KEY_F2, +	KEY_F3,		KEY_F4,		KEY_F5,		KEY_F6,		KEY_F7, +	KEY_F8,		KEY_F9,		KEY_F10,	KEY_F11,	KEY_F12, +	KEY_SYSRQ,	KEY_SCROLLLOCK,	KEY_PAUSE,	KEY_INSERT,	KEY_HOME, +	KEY_PAGEUP,	KEY_DELETE,	KEY_END,	KEY_PAGEDOWN,	KEY_RIGHT, +	KEY_LEFT,	KEY_DOWN,	KEY_UP,		KEY_NUMLOCK,	KEY_KPSLASH, +	KEY_KPASTERISK,	KEY_KPMINUS,	KEY_KPPLUS,	KEY_KPENTER,	KEY_KP1, +	KEY_KP2,	KEY_KP3,	KEY_KP4,	KEY_KP5,	KEY_KP6, +	KEY_KP7,	KEY_KP8,	KEY_KP9,	KEY_KP0,	KEY_KPDOT, +	KEY_102ND,	KEY_COMPOSE,	KEY_POWER,	KEY_KPEQUAL,	KEY_F13, +	KEY_F14,	KEY_F15,	KEY_F16,	KEY_F17,	KEY_F18, +	KEY_F19,	KEY_F20,	KEY_F21,	KEY_F22,	KEY_F23, +	KEY_F24,	KEY_OPEN,	KEY_HELP,	KEY_PROPS,	KEY_FRONT, +	KEY_STOP,	KEY_AGAIN,	KEY_UNDO,	KEY_CUT,	KEY_COPY, +	KEY_PASTE,	KEY_FIND,	KEY_MUTE,	KEY_VOLUMEUP,	KEY_VOLUMEDOWN, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_KPCOMMA,	KEY_RESERVED, +	KEY_RO,		KEY_KATAKANAHIRAGANA, KEY_YEN,	KEY_HENKAN,	KEY_MUHENKAN, +	KEY_KPJPCOMMA,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_HANGUEL, +	KEY_HANJA,	KEY_KATAKANA,	KEY_HIRAGANA,	KEY_ZENKAKUHANKAKU, KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_LEFTCTRL, +	KEY_LEFTSHIFT,	KEY_LEFTALT,	KEY_LEFTMETA,	KEY_RIGHTCTRL,	KEY_RIGHTSHIFT, +	KEY_RIGHTALT,	KEY_RIGHTMETA,	KEY_PLAYPAUSE,	KEY_STOPCD,	KEY_PREVIOUSSONG, +	KEY_NEXTSONG,	KEY_EJECTCD,	KEY_VOLUMEUP,	KEY_VOLUMEDOWN,	KEY_MUTE, +	KEY_WWW,	KEY_BACK,	KEY_FORWARD,	KEY_STOP,	KEY_FIND, +	KEY_SCROLLUP,	KEY_SCROLLDOWN,	KEY_EDIT,	KEY_SLEEP,	KEY_COFFEE, +	KEY_REFRESH,	KEY_CALC,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED, +	KEY_RESERVED +}; + +static void mce_kbd_rx_timeout(unsigned long data) +{ +	struct mce_kbd_dec *mce_kbd = (struct mce_kbd_dec *)data; +	int i; +	unsigned char maskcode; + +	IR_dprintk(2, "timer callback clearing all keys\n"); + +	for (i = 0; i < 7; i++) { +		maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i]; +		input_report_key(mce_kbd->idev, maskcode, 0); +	} + +	for (i = 0; i < MCIR2_MASK_KEYS_START; i++) +		input_report_key(mce_kbd->idev, kbd_keycodes[i], 0); +} + +static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data) +{ +	switch (data->header & MCIR2_MODE_MASK) { +	case MCIR2_KEYBOARD_HEADER: +		return MCIR2_MODE_KEYBOARD; +	case MCIR2_MOUSE_HEADER: +		return MCIR2_MODE_MOUSE; +	default: +		return MCIR2_MODE_UNKNOWN; +	} +} + +static void ir_mce_kbd_process_keyboard_data(struct input_dev *idev, +					     u32 scancode) +{ +	u8 keydata   = (scancode >> 8) & 0xff; +	u8 shiftmask = scancode & 0xff; +	unsigned char keycode, maskcode; +	int i, keystate; + +	IR_dprintk(1, "keyboard: keydata = 0x%02x, shiftmask = 0x%02x\n", +		   keydata, shiftmask); + +	for (i = 0; i < 7; i++) { +		maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i]; +		if (shiftmask & (1 << i)) +			keystate = 1; +		else +			keystate = 0; +		input_report_key(idev, maskcode, keystate); +	} + +	if (keydata) { +		keycode = kbd_keycodes[keydata]; +		input_report_key(idev, keycode, 1); +	} else { +		for (i = 0; i < MCIR2_MASK_KEYS_START; i++) +			input_report_key(idev, kbd_keycodes[i], 0); +	} +} + +static void ir_mce_kbd_process_mouse_data(struct input_dev *idev, u32 scancode) +{ +	/* raw mouse coordinates */ +	u8 xdata = (scancode >> 7) & 0x7f; +	u8 ydata = (scancode >> 14) & 0x7f; +	int x, y; +	/* mouse buttons */ +	bool right = scancode & 0x40; +	bool left  = scancode & 0x20; + +	if (xdata & 0x40) +		x = -((~xdata & 0x7f) + 1); +	else +		x = xdata; + +	if (ydata & 0x40) +		y = -((~ydata & 0x7f) + 1); +	else +		y = ydata; + +	IR_dprintk(1, "mouse: x = %d, y = %d, btns = %s%s\n", +		   x, y, left ? "L" : "", right ? "R" : ""); + +	input_report_rel(idev, REL_X, x); +	input_report_rel(idev, REL_Y, y); + +	input_report_key(idev, BTN_LEFT, left); +	input_report_key(idev, BTN_RIGHT, right); +} + +/** + * ir_mce_kbd_decode() - Decode one mce_kbd pulse or space + * @dev:	the struct rc_dev descriptor of the device + * @ev:		the struct ir_raw_event descriptor of the pulse/space + * + * This function returns -EINVAL if the pulse violates the state machine + */ +static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev) +{ +	struct mce_kbd_dec *data = &dev->raw->mce_kbd; +	u32 scancode; +	unsigned long delay; + +	if (!(dev->raw->enabled_protocols & RC_TYPE_MCE_KBD)) +		return 0; + +	if (!is_timing_event(ev)) { +		if (ev.reset) +			data->state = STATE_INACTIVE; +		return 0; +	} + +	if (!geq_margin(ev.duration, MCIR2_UNIT, MCIR2_UNIT / 2)) +		goto out; + +again: +	IR_dprintk(2, "started at state %i (%uus %s)\n", +		   data->state, TO_US(ev.duration), TO_STR(ev.pulse)); + +	if (!geq_margin(ev.duration, MCIR2_UNIT, MCIR2_UNIT / 2)) +		return 0; + +	switch (data->state) { + +	case STATE_INACTIVE: +		if (!ev.pulse) +			break; + +		/* Note: larger margin on first pulse since each MCIR2_UNIT +		   is quite short and some hardware takes some time to +		   adjust to the signal */ +		if (!eq_margin(ev.duration, MCIR2_PREFIX_PULSE, MCIR2_UNIT)) +			break; + +		data->state = STATE_HEADER_BIT_START; +		data->count = 0; +		data->header = 0; +		return 0; + +	case STATE_HEADER_BIT_START: +		if (geq_margin(ev.duration, MCIR2_MAX_LEN, MCIR2_UNIT / 2)) +			break; + +		data->header <<= 1; +		if (ev.pulse) +			data->header |= 1; +		data->count++; +		data->state = STATE_HEADER_BIT_END; +		return 0; + +	case STATE_HEADER_BIT_END: +		if (!is_transition(&ev, &dev->raw->prev_ev)) +			break; + +		decrease_duration(&ev, MCIR2_BIT_END); + +		if (data->count != MCIR2_HEADER_NBITS) { +			data->state = STATE_HEADER_BIT_START; +			goto again; +		} + +		switch (mce_kbd_mode(data)) { +		case MCIR2_MODE_KEYBOARD: +			data->wanted_bits = MCIR2_KEYBOARD_NBITS; +			break; +		case MCIR2_MODE_MOUSE: +			data->wanted_bits = MCIR2_MOUSE_NBITS; +			break; +		default: +			IR_dprintk(1, "not keyboard or mouse data\n"); +			goto out; +		} + +		data->count = 0; +		data->body = 0; +		data->state = STATE_BODY_BIT_START; +		goto again; + +	case STATE_BODY_BIT_START: +		if (geq_margin(ev.duration, MCIR2_MAX_LEN, MCIR2_UNIT / 2)) +			break; + +		data->body <<= 1; +		if (ev.pulse) +			data->body |= 1; +		data->count++; +		data->state = STATE_BODY_BIT_END; +		return 0; + +	case STATE_BODY_BIT_END: +		if (!is_transition(&ev, &dev->raw->prev_ev)) +			break; + +		if (data->count == data->wanted_bits) +			data->state = STATE_FINISHED; +		else +			data->state = STATE_BODY_BIT_START; + +		decrease_duration(&ev, MCIR2_BIT_END); +		goto again; + +	case STATE_FINISHED: +		if (ev.pulse) +			break; + +		switch (data->wanted_bits) { +		case MCIR2_KEYBOARD_NBITS: +			scancode = data->body & 0xffff; +			IR_dprintk(1, "keyboard data 0x%08x\n", data->body); +			if (dev->timeout) +				delay = usecs_to_jiffies(dev->timeout / 1000); +			else +				delay = msecs_to_jiffies(100); +			mod_timer(&data->rx_timeout, jiffies + delay); +			/* Pass data to keyboard buffer parser */ +			ir_mce_kbd_process_keyboard_data(data->idev, scancode); +			break; +		case MCIR2_MOUSE_NBITS: +			scancode = data->body & 0x1fffff; +			IR_dprintk(1, "mouse data 0x%06x\n", scancode); +			/* Pass data to mouse buffer parser */ +			ir_mce_kbd_process_mouse_data(data->idev, scancode); +			break; +		default: +			IR_dprintk(1, "not keyboard or mouse data\n"); +			goto out; +		} + +		data->state = STATE_INACTIVE; +		input_sync(data->idev); +		return 0; +	} + +out: +	IR_dprintk(1, "failed at state %i (%uus %s)\n", +		   data->state, TO_US(ev.duration), TO_STR(ev.pulse)); +	data->state = STATE_INACTIVE; +	input_sync(data->idev); +	return -EINVAL; +} + +static int ir_mce_kbd_register(struct rc_dev *dev) +{ +	struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd; +	struct input_dev *idev; +	int i, ret; + +	idev = input_allocate_device(); +	if (!idev) +		return -ENOMEM; + +	snprintf(mce_kbd->name, sizeof(mce_kbd->name), +		 "MCE IR Keyboard/Mouse (%s)", dev->driver_name); +	strlcat(mce_kbd->phys, "/input0", sizeof(mce_kbd->phys)); + +	idev->name = mce_kbd->name; +	idev->phys = mce_kbd->phys; + +	/* Keyboard bits */ +	set_bit(EV_KEY, idev->evbit); +	set_bit(EV_REP, idev->evbit); +	for (i = 0; i < sizeof(kbd_keycodes); i++) +		set_bit(kbd_keycodes[i], idev->keybit); + +	/* Mouse bits */ +	set_bit(EV_REL, idev->evbit); +	set_bit(REL_X, idev->relbit); +	set_bit(REL_Y, idev->relbit); +	set_bit(BTN_LEFT, idev->keybit); +	set_bit(BTN_RIGHT, idev->keybit); + +	/* Report scancodes too */ +	set_bit(EV_MSC, idev->evbit); +	set_bit(MSC_SCAN, idev->mscbit); + +	setup_timer(&mce_kbd->rx_timeout, mce_kbd_rx_timeout, +		    (unsigned long)mce_kbd); + +	input_set_drvdata(idev, mce_kbd); + +#if 0 +	/* Adding this reference means two input devices are associated with +	 * this rc-core device, which ir-keytable doesn't cope with yet */ +	idev->dev.parent = &dev->dev; +#endif + +	ret = input_register_device(idev); +	if (ret < 0) { +		input_free_device(idev); +		return -EIO; +	} + +	mce_kbd->idev = idev; + +	return 0; +} + +static int ir_mce_kbd_unregister(struct rc_dev *dev) +{ +	struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd; +	struct input_dev *idev = mce_kbd->idev; + +	del_timer_sync(&mce_kbd->rx_timeout); +	input_unregister_device(idev); + +	return 0; +} + +static struct ir_raw_handler mce_kbd_handler = { +	.protocols	= RC_TYPE_MCE_KBD, +	.decode		= ir_mce_kbd_decode, +	.raw_register	= ir_mce_kbd_register, +	.raw_unregister	= ir_mce_kbd_unregister, +}; + +static int __init ir_mce_kbd_decode_init(void) +{ +	ir_raw_handler_register(&mce_kbd_handler); + +	printk(KERN_INFO "IR MCE Keyboard/mouse protocol handler initialized\n"); +	return 0; +} + +static void __exit ir_mce_kbd_decode_exit(void) +{ +	ir_raw_handler_unregister(&mce_kbd_handler); +} + +module_init(ir_mce_kbd_decode_init); +module_exit(ir_mce_kbd_decode_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>"); +MODULE_DESCRIPTION("MCE Keyboard/mouse IR protocol decoder"); diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c index 11c19d8d0ee0..27808bb59eba 100644 --- a/drivers/media/rc/ir-raw.c +++ b/drivers/media/rc/ir-raw.c @@ -114,18 +114,20 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type)  	s64			delta; /* ns */  	DEFINE_IR_RAW_EVENT(ev);  	int			rc = 0; +	int			delay;  	if (!dev->raw)  		return -EINVAL;  	now = ktime_get();  	delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event)); +	delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]);  	/* Check for a long duration since last event or if we're  	 * being called for the first time, note that delta can't  	 * possibly be negative.  	 */ -	if (delta > IR_MAX_DURATION || !dev->raw->last_type) +	if (delta > delay || !dev->raw->last_type)  		type |= IR_START_EVENT;  	else  		ev.duration = delta; @@ -353,6 +355,7 @@ static void init_decoders(struct work_struct *work)  	load_rc6_decode();  	load_jvc_decode();  	load_sony_decode(); +	load_mce_kbd_decode();  	load_lirc_codec();  	/* If needed, we may later add some init code. In this case, diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index e716b931cf7e..682009d76cdf 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -42,7 +42,6 @@  #include <linux/bitops.h>  #include <media/rc-core.h>  #include <linux/pci_ids.h> -#include <linux/delay.h>  #include "ite-cir.h" @@ -383,7 +382,7 @@ static int ite_set_tx_duty_cycle(struct rc_dev *rcdev, u32 duty_cycle)  /* transmit out IR pulses; what you get here is a batch of alternating   * pulse/space/pulse/space lengths that we should write out completely through   * the FIFO, blocking on a full FIFO */ -static int ite_tx_ir(struct rc_dev *rcdev, int *txbuf, u32 n) +static int ite_tx_ir(struct rc_dev *rcdev, unsigned *txbuf, unsigned n)  {  	unsigned long flags;  	struct ite_dev *dev = rcdev->priv; @@ -399,9 +398,6 @@ static int ite_tx_ir(struct rc_dev *rcdev, int *txbuf, u32 n)  	/* clear the array just in case */  	memset(last_sent, 0, ARRAY_SIZE(last_sent)); -	/* n comes in bytes; convert to ints */ -	n /= sizeof(int); -  	spin_lock_irqsave(&dev->lock, flags);  	/* let everybody know we're now transmitting */ @@ -1347,6 +1343,7 @@ static const struct ite_dev_params ite_dev_descs[] = {  	{	/* 0: ITE8704 */  	       .model = "ITE8704 CIR transceiver",  	       .io_region_size = IT87_IOREG_LENGTH, +	       .io_rsrc_no = 0,  	       .hw_tx_capable = true,  	       .sample_period = (u32) (1000000000ULL / 115200),  	       .tx_carrier_freq = 38000, @@ -1371,6 +1368,7 @@ static const struct ite_dev_params ite_dev_descs[] = {  	{	/* 1: ITE8713 */  	       .model = "ITE8713 CIR transceiver",  	       .io_region_size = IT87_IOREG_LENGTH, +	       .io_rsrc_no = 0,  	       .hw_tx_capable = true,  	       .sample_period = (u32) (1000000000ULL / 115200),  	       .tx_carrier_freq = 38000, @@ -1395,6 +1393,7 @@ static const struct ite_dev_params ite_dev_descs[] = {  	{	/* 2: ITE8708 */  	       .model = "ITE8708 CIR transceiver",  	       .io_region_size = IT8708_IOREG_LENGTH, +	       .io_rsrc_no = 0,  	       .hw_tx_capable = true,  	       .sample_period = (u32) (1000000000ULL / 115200),  	       .tx_carrier_freq = 38000, @@ -1420,6 +1419,7 @@ static const struct ite_dev_params ite_dev_descs[] = {  	{	/* 3: ITE8709 */  	       .model = "ITE8709 CIR transceiver",  	       .io_region_size = IT8709_IOREG_LENGTH, +	       .io_rsrc_no = 2,  	       .hw_tx_capable = true,  	       .sample_period = (u32) (1000000000ULL / 115200),  	       .tx_carrier_freq = 38000, @@ -1461,6 +1461,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id  	struct rc_dev *rdev = NULL;  	int ret = -ENOMEM;  	int model_no; +	int io_rsrc_no;  	ite_dbg("%s called", __func__); @@ -1490,10 +1491,11 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id  	/* get the description for the device */  	dev_desc = &ite_dev_descs[model_no]; +	io_rsrc_no = dev_desc->io_rsrc_no;  	/* validate pnp resources */ -	if (!pnp_port_valid(pdev, 0) || -	    pnp_port_len(pdev, 0) != dev_desc->io_region_size) { +	if (!pnp_port_valid(pdev, io_rsrc_no) || +	    pnp_port_len(pdev, io_rsrc_no) != dev_desc->io_region_size) {  		dev_err(&pdev->dev, "IR PNP Port not valid!\n");  		goto failure;  	} @@ -1504,7 +1506,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id  	}  	/* store resource values */ -	itdev->cir_addr = pnp_port_start(pdev, 0); +	itdev->cir_addr = pnp_port_start(pdev, io_rsrc_no);  	itdev->cir_irq = pnp_irq(pdev, 0);  	/* initialize spinlocks */ diff --git a/drivers/media/rc/ite-cir.h b/drivers/media/rc/ite-cir.h index 16a19f5fd718..aa899a0b9750 100644 --- a/drivers/media/rc/ite-cir.h +++ b/drivers/media/rc/ite-cir.h @@ -57,6 +57,9 @@ struct ite_dev_params {  	/* size of the I/O region */  	int io_region_size; +	/* IR pnp I/O resource number */ +	int io_rsrc_no; +  	/* true if the hardware supports transmission */  	bool hw_tx_capable; diff --git a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c index bb10ffe086b4..8d558ae63456 100644 --- a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c +++ b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c @@ -15,43 +15,39 @@  /* Pinnacle PCTV HD 800i mini remote */  static struct rc_map_table pinnacle_pctv_hd[] = { - -	{ 0x0f, KEY_1 }, -	{ 0x15, KEY_2 }, -	{ 0x10, KEY_3 }, -	{ 0x18, KEY_4 }, -	{ 0x1b, KEY_5 }, -	{ 0x1e, KEY_6 }, -	{ 0x11, KEY_7 }, -	{ 0x21, KEY_8 }, -	{ 0x12, KEY_9 }, -	{ 0x27, KEY_0 }, - -	{ 0x24, KEY_ZOOM }, -	{ 0x2a, KEY_SUBTITLE }, - -	{ 0x00, KEY_MUTE }, -	{ 0x01, KEY_ENTER },	/* Pinnacle Logo */ -	{ 0x39, KEY_POWER }, - -	{ 0x03, KEY_VOLUMEUP }, -	{ 0x09, KEY_VOLUMEDOWN }, -	{ 0x06, KEY_CHANNELUP }, -	{ 0x0c, KEY_CHANNELDOWN }, - -	{ 0x2d, KEY_REWIND }, -	{ 0x30, KEY_PLAYPAUSE }, -	{ 0x33, KEY_FASTFORWARD }, -	{ 0x3c, KEY_STOP }, -	{ 0x36, KEY_RECORD }, -	{ 0x3f, KEY_EPG },	/* Labeled "?" */ +	/* Key codes for the tiny Pinnacle remote*/ +	{ 0x0700, KEY_MUTE }, +	{ 0x0701, KEY_MENU }, /* Pinnacle logo */ +	{ 0x0739, KEY_POWER }, +	{ 0x0703, KEY_VOLUMEUP }, +	{ 0x0709, KEY_VOLUMEDOWN }, +	{ 0x0706, KEY_CHANNELUP }, +	{ 0x070c, KEY_CHANNELDOWN }, +	{ 0x070f, KEY_1 }, +	{ 0x0715, KEY_2 }, +	{ 0x0710, KEY_3 }, +	{ 0x0718, KEY_4 }, +	{ 0x071b, KEY_5 }, +	{ 0x071e, KEY_6 }, +	{ 0x0711, KEY_7 }, +	{ 0x0721, KEY_8 }, +	{ 0x0712, KEY_9 }, +	{ 0x0727, KEY_0 }, +	{ 0x0724, KEY_ZOOM }, /* 'Square' key */ +	{ 0x072a, KEY_SUBTITLE },   /* 'T' key */ +	{ 0x072d, KEY_REWIND }, +	{ 0x0730, KEY_PLAYPAUSE }, +	{ 0x0733, KEY_FASTFORWARD }, +	{ 0x0736, KEY_RECORD }, +	{ 0x073c, KEY_STOP }, +	{ 0x073f, KEY_HELP }, /* '?' key */  };  static struct rc_map_list pinnacle_pctv_hd_map = {  	.map = {  		.scan    = pinnacle_pctv_hd,  		.size    = ARRAY_SIZE(pinnacle_pctv_hd), -		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */ +		.rc_type = RC_TYPE_RC5,  		.name    = RC_MAP_PINNACLE_PCTV_HD,  	}  }; diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c index 01b69bcc8666..c3907e211d39 100644 --- a/drivers/media/rc/keymaps/rc-rc6-mce.c +++ b/drivers/media/rc/keymaps/rc-rc6-mce.c @@ -29,7 +29,7 @@ static struct rc_map_table rc6_mce[] = {  	{ 0x800f040a, KEY_DELETE },  	{ 0x800f040b, KEY_ENTER }, -	{ 0x800f040c, KEY_POWER },		/* PC Power */ +	{ 0x800f040c, KEY_SLEEP },		/* Formerly PC Power */  	{ 0x800f040d, KEY_MEDIA },		/* Windows MCE button */  	{ 0x800f040e, KEY_MUTE },  	{ 0x800f040f, KEY_INFO }, @@ -44,7 +44,6 @@ static struct rc_map_table rc6_mce[] = {  	{ 0x800f0416, KEY_PLAY },  	{ 0x800f0417, KEY_RECORD },  	{ 0x800f0418, KEY_PAUSE }, -	{ 0x800f046e, KEY_PLAYPAUSE },  	{ 0x800f0419, KEY_STOP },  	{ 0x800f041a, KEY_NEXT },  	{ 0x800f041b, KEY_PREVIOUS }, diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index fd237ab120bb..27997a9ceb0d 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -55,6 +55,8 @@ struct irctl {  	struct lirc_buffer *buf;  	unsigned int chunk_size; +	struct cdev *cdev; +  	struct task_struct *task;  	long jiffies_to_wait;  }; @@ -62,7 +64,6 @@ struct irctl {  static DEFINE_MUTEX(lirc_dev_lock);  static struct irctl *irctls[MAX_IRCTL_DEVICES]; -static struct cdev cdevs[MAX_IRCTL_DEVICES];  /* Only used for sysfs but defined to void otherwise */  static struct class *lirc_class; @@ -167,9 +168,13 @@ static struct file_operations lirc_dev_fops = {  static int lirc_cdev_add(struct irctl *ir)  { -	int retval; +	int retval = -ENOMEM;  	struct lirc_driver *d = &ir->d; -	struct cdev *cdev = &cdevs[d->minor]; +	struct cdev *cdev; + +	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); +	if (!cdev) +		goto err_out;  	if (d->fops) {  		cdev_init(cdev, d->fops); @@ -180,12 +185,20 @@ static int lirc_cdev_add(struct irctl *ir)  	}  	retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);  	if (retval) -		return retval; +		goto err_out;  	retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1); -	if (retval) +	if (retval) {  		kobject_put(&cdev->kobj); +		goto err_out; +	} + +	ir->cdev = cdev; + +	return 0; +err_out: +	kfree(cdev);  	return retval;  } @@ -214,7 +227,7 @@ int lirc_register_driver(struct lirc_driver *d)  	if (MAX_IRCTL_DEVICES <= d->minor) {  		dev_err(d->dev, "lirc_dev: lirc_register_driver: "  			"\"minor\" must be between 0 and %d (%d)!\n", -			MAX_IRCTL_DEVICES-1, d->minor); +			MAX_IRCTL_DEVICES - 1, d->minor);  		err = -EBADRQC;  		goto out;  	} @@ -369,7 +382,7 @@ int lirc_unregister_driver(int minor)  	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {  		printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between " -		       "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1); +		       "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES - 1);  		return -EBADRQC;  	} @@ -380,7 +393,7 @@ int lirc_unregister_driver(int minor)  		return -ENOENT;  	} -	cdev = &cdevs[minor]; +	cdev = ir->cdev;  	mutex_lock(&lirc_dev_lock); @@ -410,6 +423,7 @@ int lirc_unregister_driver(int minor)  	} else {  		lirc_irctl_cleanup(ir);  		cdev_del(cdev); +		kfree(cdev);  		kfree(ir);  		irctls[minor] = NULL;  	} @@ -453,7 +467,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)  		goto error;  	} -	cdev = &cdevs[iminor(inode)]; +	cdev = ir->cdev;  	if (try_module_get(cdev->owner)) {  		ir->open++;  		retval = ir->d.set_use_inc(ir->d.data); @@ -484,13 +498,15 @@ EXPORT_SYMBOL(lirc_dev_fop_open);  int lirc_dev_fop_close(struct inode *inode, struct file *file)  {  	struct irctl *ir = irctls[iminor(inode)]; -	struct cdev *cdev = &cdevs[iminor(inode)]; +	struct cdev *cdev;  	if (!ir) {  		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);  		return -EINVAL;  	} +	cdev = ir->cdev; +  	dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);  	WARN_ON(mutex_lock_killable(&lirc_dev_lock)); @@ -503,6 +519,7 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file)  		lirc_irctl_cleanup(ir);  		cdev_del(cdev);  		irctls[ir->d.minor] = NULL; +		kfree(cdev);  		kfree(ir);  	} diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index ad927fcaa020..85ff9a1ffb39 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -108,6 +108,12 @@ static int debug = 1;  static int debug;  #endif +#define mce_dbg(dev, fmt, ...)					\ +	do {							\ +		if (debug)					\ +			dev_info(dev, fmt, ## __VA_ARGS__);	\ +	} while (0) +  /* general constants */  #define SEND_FLAG_IN_PROGRESS	1  #define SEND_FLAG_COMPLETE	2 @@ -246,6 +252,9 @@ static struct usb_device_id mceusb_dev_table[] = {  	  .driver_info = MCE_GEN2_TX_INV },  	/* SMK eHome Infrared Transceiver */  	{ USB_DEVICE(VENDOR_SMK, 0x0338) }, +	/* SMK/I-O Data GV-MC7/RCKIT Receiver */ +	{ USB_DEVICE(VENDOR_SMK, 0x0353), +	  .driver_info = MCE_GEN2_NO_TX },  	/* Tatung eHome Infrared Transceiver */  	{ USB_DEVICE(VENDOR_TATUNG, 0x9150) },  	/* Shuttle eHome Infrared Transceiver */ @@ -549,9 +558,10 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,  				 inout, data1);  			break;  		case MCE_CMD_S_TIMEOUT: -			/* value is in units of 50us, so x*50/100 or x/2 ms */ +			/* value is in units of 50us, so x*50/1000 ms */  			dev_info(dev, "%s receive timeout of %d ms\n", -				 inout, ((data1 << 8) | data2) / 2); +				 inout, +				 ((data1 << 8) | data2) * MCE_TIME_UNIT / 1000);  			break;  		case MCE_CMD_G_TIMEOUT:  			dev_info(dev, "Get receive timeout\n"); @@ -606,12 +616,15 @@ static void mce_async_callback(struct urb *urb, struct pt_regs *regs)  	if (ir) {  		len = urb->actual_length; -		dev_dbg(ir->dev, "callback called (status=%d len=%d)\n", +		mce_dbg(ir->dev, "callback called (status=%d len=%d)\n",  			urb->status, len);  		mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);  	} +	/* the transfer buffer and urb were allocated in mce_request_packet */ +	kfree(urb->transfer_buffer); +	usb_free_urb(urb);  }  /* request incoming or send outgoing usb packet - used to initialize remote */ @@ -655,17 +668,17 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,  		return;  	} -	dev_dbg(dev, "receive request called (size=%#x)\n", size); +	mce_dbg(dev, "receive request called (size=%#x)\n", size);  	async_urb->transfer_buffer_length = size;  	async_urb->dev = ir->usbdev;  	res = usb_submit_urb(async_urb, GFP_ATOMIC);  	if (res) { -		dev_dbg(dev, "receive request FAILED! (res=%d)\n", res); +		mce_dbg(dev, "receive request FAILED! (res=%d)\n", res);  		return;  	} -	dev_dbg(dev, "receive request complete (res=%d)\n", res); +	mce_dbg(dev, "receive request complete (res=%d)\n", res);  }  static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) @@ -673,26 +686,24 @@ static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)  	mce_request_packet(ir, data, size, MCEUSB_TX);  } -static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size) +static void mce_flush_rx_buffer(struct mceusb_dev *ir, int size)  { -	mce_request_packet(ir, data, size, MCEUSB_RX); +	mce_request_packet(ir, NULL, size, MCEUSB_RX);  }  /* Send data out the IR blaster port(s) */ -static int mceusb_tx_ir(struct rc_dev *dev, int *txbuf, u32 n) +static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)  {  	struct mceusb_dev *ir = dev->priv;  	int i, ret = 0; -	int count, cmdcount = 0; +	int cmdcount = 0;  	unsigned char *cmdbuf; /* MCE command buffer */  	long signal_duration = 0; /* Singnal length in us */  	struct timeval start_time, end_time;  	do_gettimeofday(&start_time); -	count = n / sizeof(int); - -	cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL); +	cmdbuf = kzalloc(sizeof(unsigned) * MCE_CMDBUF_SIZE, GFP_KERNEL);  	if (!cmdbuf)  		return -ENOMEM; @@ -761,7 +772,7 @@ static int mceusb_tx_ir(struct rc_dev *dev, int *txbuf, u32 n)  out:  	kfree(cmdbuf); -	return ret ? ret : n; +	return ret ? ret : count;  }  /* Sets active IR outputs -- mce devices typically have two */ @@ -794,7 +805,7 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier)  			ir->carrier = carrier;  			cmdbuf[2] = MCE_CMD_SIG_END;  			cmdbuf[3] = MCE_IRDATA_TRAILER; -			dev_dbg(ir->dev, "%s: disabling carrier " +			mce_dbg(ir->dev, "%s: disabling carrier "  				"modulation\n", __func__);  			mce_async_out(ir, cmdbuf, sizeof(cmdbuf));  			return carrier; @@ -806,7 +817,7 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier)  				ir->carrier = carrier;  				cmdbuf[2] = prescaler;  				cmdbuf[3] = divisor; -				dev_dbg(ir->dev, "%s: requesting %u HZ " +				mce_dbg(ir->dev, "%s: requesting %u HZ "  					"carrier\n", __func__, carrier);  				/* Transmit new carrier to mce device */ @@ -835,7 +846,7 @@ static void mceusb_handle_command(struct mceusb_dev *ir, int index)  	switch (ir->buf_in[index]) {  	/* 2-byte return value commands */  	case MCE_CMD_S_TIMEOUT: -		ir->rc->timeout = US_TO_NS((hi << 8 | lo) / 2); +		ir->rc->timeout = US_TO_NS((hi << 8 | lo) * MCE_TIME_UNIT);  		break;  	/* 1-byte return value commands */ @@ -879,7 +890,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)  			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)  					 * US_TO_NS(MCE_TIME_UNIT); -			dev_dbg(ir->dev, "Storing %s with duration %d\n", +			mce_dbg(ir->dev, "Storing %s with duration %d\n",  				rawir.pulse ? "pulse" : "space",  				rawir.duration); @@ -911,7 +922,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)  		if (ir->parser_state != CMD_HEADER && !ir->rem)  			ir->parser_state = CMD_HEADER;  	} -	dev_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n"); +	mce_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n");  	ir_raw_event_handle(ir->rc);  } @@ -933,7 +944,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)  	if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {  		ir->send_flags = SEND_FLAG_COMPLETE; -		dev_dbg(ir->dev, "setup answer received %d bytes\n", +		mce_dbg(ir->dev, "setup answer received %d bytes\n",  			buf_len);  	} @@ -951,7 +962,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)  	case -EPIPE:  	default: -		dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status); +		mce_dbg(ir->dev, "Error: urb status = %d\n", urb->status);  		break;  	} @@ -961,7 +972,6 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)  static void mceusb_gen1_init(struct mceusb_dev *ir)  {  	int ret; -	int maxp = ir->len_in;  	struct device *dev = ir->dev;  	char *data; @@ -978,8 +988,8 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)  	ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),  			      USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,  			      data, USB_CTRL_MSG_SZ, HZ * 3); -	dev_dbg(dev, "%s - ret = %d\n", __func__, ret); -	dev_dbg(dev, "%s - data[0] = %d, data[1] = %d\n", +	mce_dbg(dev, "%s - ret = %d\n", __func__, ret); +	mce_dbg(dev, "%s - data[0] = %d, data[1] = %d\n",  		__func__, data[0], data[1]);  	/* set feature: bit rate 38400 bps */ @@ -987,71 +997,56 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)  			      USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,  			      0xc04e, 0x0000, NULL, 0, HZ * 3); -	dev_dbg(dev, "%s - ret = %d\n", __func__, ret); +	mce_dbg(dev, "%s - ret = %d\n", __func__, ret);  	/* bRequest 4: set char length to 8 bits */  	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),  			      4, USB_TYPE_VENDOR,  			      0x0808, 0x0000, NULL, 0, HZ * 3); -	dev_dbg(dev, "%s - retB = %d\n", __func__, ret); +	mce_dbg(dev, "%s - retB = %d\n", __func__, ret);  	/* bRequest 2: set handshaking to use DTR/DSR */  	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),  			      2, USB_TYPE_VENDOR,  			      0x0000, 0x0100, NULL, 0, HZ * 3); -	dev_dbg(dev, "%s - retC = %d\n", __func__, ret); +	mce_dbg(dev, "%s - retC = %d\n", __func__, ret);  	/* device reset */  	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); -	mce_sync_in(ir, NULL, maxp);  	/* get hw/sw revision? */  	mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); -	mce_sync_in(ir, NULL, maxp);  	kfree(data);  };  static void mceusb_gen2_init(struct mceusb_dev *ir)  { -	int maxp = ir->len_in; -  	/* device reset */  	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); -	mce_sync_in(ir, NULL, maxp);  	/* get hw/sw revision? */  	mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); -	mce_sync_in(ir, NULL, maxp);  	/* unknown what the next two actually return... */  	mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN)); -	mce_sync_in(ir, NULL, maxp);  	mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2)); -	mce_sync_in(ir, NULL, maxp);  }  static void mceusb_get_parameters(struct mceusb_dev *ir)  { -	int maxp = ir->len_in; -  	/* get the carrier and frequency */  	mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ)); -	mce_sync_in(ir, NULL, maxp); -	if (!ir->flags.no_tx) { +	if (!ir->flags.no_tx)  		/* get the transmitter bitmask */  		mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); -		mce_sync_in(ir, NULL, maxp); -	}  	/* get receiver timeout value */  	mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); -	mce_sync_in(ir, NULL, maxp);  	/* get receiver sensor setting */  	mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR)); -	mce_sync_in(ir, NULL, maxp);  }  static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir) @@ -1082,7 +1077,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)  	rc->priv = ir;  	rc->driver_type = RC_DRIVER_IR_RAW;  	rc->allowed_protos = RC_TYPE_ALL; -	rc->timeout = US_TO_NS(1000); +	rc->timeout = MS_TO_NS(100);  	if (!ir->flags.no_tx) {  		rc->s_tx_mask = mceusb_set_tx_mask;  		rc->s_tx_carrier = mceusb_set_tx_carrier; @@ -1122,7 +1117,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,  	bool tx_mask_normal;  	int ir_intfnum; -	dev_dbg(&intf->dev, "%s called\n", __func__); +	mce_dbg(&intf->dev, "%s called\n", __func__);  	idesc  = intf->cur_altsetting; @@ -1150,7 +1145,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,  			ep_in = ep;  			ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;  			ep_in->bInterval = 1; -			dev_dbg(&intf->dev, "acceptable inbound endpoint " +			mce_dbg(&intf->dev, "acceptable inbound endpoint "  				"found\n");  		} @@ -1165,12 +1160,12 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,  			ep_out = ep;  			ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;  			ep_out->bInterval = 1; -			dev_dbg(&intf->dev, "acceptable outbound endpoint " +			mce_dbg(&intf->dev, "acceptable outbound endpoint "  				"found\n");  		}  	}  	if (ep_in == NULL) { -		dev_dbg(&intf->dev, "inbound and/or endpoint not found\n"); +		mce_dbg(&intf->dev, "inbound and/or endpoint not found\n");  		return -ENODEV;  	} @@ -1215,16 +1210,16 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,  	if (!ir->rc)  		goto rc_dev_fail; -	/* flush buffers on the device */ -	mce_sync_in(ir, NULL, maxp); -	mce_sync_in(ir, NULL, maxp); -  	/* wire up inbound data handler */  	usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in,  		maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval);  	ir->urb_in->transfer_dma = ir->dma_in;  	ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; +	/* flush buffers on the device */ +	mce_dbg(&intf->dev, "Flushing receive buffers\n"); +	mce_flush_rx_buffer(ir, maxp); +  	/* initialize device */  	if (ir->flags.microsoft_gen1)  		mceusb_gen1_init(ir); diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index bf3060ea6107..eae05b500476 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -546,24 +546,18 @@ static int nvt_set_tx_carrier(struct rc_dev *dev, u32 carrier)   * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to   * set TXFCONT as 0xff, until buf_count less than 0xff.   */ -static int nvt_tx_ir(struct rc_dev *dev, int *txbuf, u32 n) +static int nvt_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned n)  {  	struct nvt_dev *nvt = dev->priv;  	unsigned long flags; -	size_t cur_count;  	unsigned int i;  	u8 iren;  	int ret;  	spin_lock_irqsave(&nvt->tx.lock, flags); -	if (n >= TX_BUF_LEN) { -		nvt->tx.buf_count = cur_count = TX_BUF_LEN; -		ret = TX_BUF_LEN; -	} else { -		nvt->tx.buf_count = cur_count = n; -		ret = n; -	} +	ret = min((unsigned)(TX_BUF_LEN / sizeof(unsigned)), n); +	nvt->tx.buf_count = (ret * sizeof(unsigned));  	memcpy(nvt->tx.buf, txbuf, nvt->tx.buf_count); @@ -991,7 +985,6 @@ static int nvt_open(struct rc_dev *dev)  	unsigned long flags;  	spin_lock_irqsave(&nvt->nvt_lock, flags); -	nvt->in_use = true;  	nvt_enable_cir(nvt);  	spin_unlock_irqrestore(&nvt->nvt_lock, flags); @@ -1004,7 +997,6 @@ static void nvt_close(struct rc_dev *dev)  	unsigned long flags;  	spin_lock_irqsave(&nvt->nvt_lock, flags); -	nvt->in_use = false;  	nvt_disable_cir(nvt);  	spin_unlock_irqrestore(&nvt->nvt_lock, flags);  } @@ -1112,7 +1104,7 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)  	rdev->dev.parent = &pdev->dev;  	rdev->driver_name = NVT_DRIVER_NAME;  	rdev->map_name = RC_MAP_RC6_MCE; -	rdev->timeout = US_TO_NS(1000); +	rdev->timeout = MS_TO_NS(100);  	/* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */  	rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD);  #if 0 diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h index 379795d61ea7..1241fc89a36c 100644 --- a/drivers/media/rc/nuvoton-cir.h +++ b/drivers/media/rc/nuvoton-cir.h @@ -70,7 +70,6 @@ struct nvt_dev {  	struct ir_raw_event rawir;  	spinlock_t nvt_lock; -	bool in_use;  	/* for rx */  	u8 buf[RX_BUF_LEN]; diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 873b38789751..04c2c722b6ec 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h @@ -84,6 +84,17 @@ struct ir_raw_event_ctrl {  		unsigned count;  		unsigned wanted_bits;  	} rc5_sz; +	struct mce_kbd_dec { +		struct input_dev *idev; +		struct timer_list rx_timeout; +		char name[64]; +		char phys[64]; +		int state; +		u8 header; +		u32 body; +		unsigned count; +		unsigned wanted_bits; +	} mce_kbd;  	struct lirc_codec {  		struct rc_dev *dev;  		struct lirc_driver *drv; @@ -182,6 +193,13 @@ void ir_raw_init(void);  #define load_sony_decode()	0  #endif +/* from ir-mce_kbd-decoder.c */ +#ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE +#define load_mce_kbd_decode()	request_module("ir-mce_kbd-decoder") +#else +#define load_mce_kbd_decode()	0 +#endif +  /* from ir-lirc-codec.c */  #ifdef CONFIG_IR_LIRC_CODEC_MODULE  #define load_lirc_codec()	request_module("ir-lirc-codec") diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c index cc846b2619cf..efc6a514348a 100644 --- a/drivers/media/rc/rc-loopback.c +++ b/drivers/media/rc/rc-loopback.c @@ -101,21 +101,14 @@ static int loop_set_rx_carrier_range(struct rc_dev *dev, u32 min, u32 max)  	return 0;  } -static int loop_tx_ir(struct rc_dev *dev, int *txbuf, u32 n) +static int loop_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)  {  	struct loopback_dev *lodev = dev->priv;  	u32 rxmask; -	unsigned count;  	unsigned total_duration = 0;  	unsigned i;  	DEFINE_IR_RAW_EVENT(rawir); -	if (n == 0 || n % sizeof(int)) { -		dprintk("invalid tx buffer size\n"); -		return -EINVAL; -	} - -	count = n / sizeof(int);  	for (i = 0; i < count; i++)  		total_duration += abs(txbuf[i]); @@ -142,7 +135,7 @@ static int loop_tx_ir(struct rc_dev *dev, int *txbuf, u32 n)  	for (i = 0; i < count; i++) {  		rawir.pulse = i % 2 ? false : true; -		rawir.duration = abs(txbuf[i]) * 1000; +		rawir.duration = txbuf[i] * 1000;  		if (rawir.duration)  			ir_raw_event_store_with_filter(dev, &rawir);  	} @@ -158,7 +151,7 @@ out:  	/* Lirc expects this function to take as long as the total duration */  	set_current_state(TASK_INTERRUPTIBLE);  	schedule_timeout(usecs_to_jiffies(total_duration)); -	return n; +	return count;  }  static void loop_set_idle(struct rc_dev *dev, bool enable) diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index f57cd5677ac2..51a23f48bc7d 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -522,18 +522,20 @@ EXPORT_SYMBOL_GPL(rc_g_keycode_from_table);  /**   * ir_do_keyup() - internal function to signal the release of a keypress   * @dev:	the struct rc_dev descriptor of the device + * @sync:	whether or not to call input_sync   *   * This function is used internally to release a keypress, it must be   * called with keylock held.   */ -static void ir_do_keyup(struct rc_dev *dev) +static void ir_do_keyup(struct rc_dev *dev, bool sync)  {  	if (!dev->keypressed)  		return;  	IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode);  	input_report_key(dev->input_dev, dev->last_keycode, 0); -	input_sync(dev->input_dev); +	if (sync) +		input_sync(dev->input_dev);  	dev->keypressed = false;  } @@ -549,7 +551,7 @@ void rc_keyup(struct rc_dev *dev)  	unsigned long flags;  	spin_lock_irqsave(&dev->keylock, flags); -	ir_do_keyup(dev); +	ir_do_keyup(dev, true);  	spin_unlock_irqrestore(&dev->keylock, flags);  }  EXPORT_SYMBOL_GPL(rc_keyup); @@ -578,7 +580,7 @@ static void ir_timer_keyup(unsigned long cookie)  	 */  	spin_lock_irqsave(&dev->keylock, flags);  	if (time_is_before_eq_jiffies(dev->keyup_jiffies)) -		ir_do_keyup(dev); +		ir_do_keyup(dev, true);  	spin_unlock_irqrestore(&dev->keylock, flags);  } @@ -597,6 +599,7 @@ void rc_repeat(struct rc_dev *dev)  	spin_lock_irqsave(&dev->keylock, flags);  	input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode); +	input_sync(dev->input_dev);  	if (!dev->keypressed)  		goto out; @@ -622,29 +625,28 @@ EXPORT_SYMBOL_GPL(rc_repeat);  static void ir_do_keydown(struct rc_dev *dev, int scancode,  			  u32 keycode, u8 toggle)  { -	input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode); +	bool new_event = !dev->keypressed || +			 dev->last_scancode != scancode || +			 dev->last_toggle != toggle; -	/* Repeat event? */ -	if (dev->keypressed && -	    dev->last_scancode == scancode && -	    dev->last_toggle == toggle) -		return; - -	/* Release old keypress */ -	ir_do_keyup(dev); +	if (new_event && dev->keypressed) +		ir_do_keyup(dev, false); -	dev->last_scancode = scancode; -	dev->last_toggle = toggle; -	dev->last_keycode = keycode; +	input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode); -	if (keycode == KEY_RESERVED) -		return; +	if (new_event && keycode != KEY_RESERVED) { +		/* Register a keypress */ +		dev->keypressed = true; +		dev->last_scancode = scancode; +		dev->last_toggle = toggle; +		dev->last_keycode = keycode; + +		IR_dprintk(1, "%s: key down event, " +			   "key 0x%04x, scancode 0x%04x\n", +			   dev->input_name, keycode, scancode); +		input_report_key(dev->input_dev, keycode, 1); +	} -	/* Register a keypress */ -	dev->keypressed = true; -	IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", -		   dev->input_name, keycode, scancode); -	input_report_key(dev->input_dev, dev->last_keycode, 1);  	input_sync(dev->input_dev);  } @@ -733,6 +735,7 @@ static struct {  	{ RC_TYPE_JVC,		"jvc"		},  	{ RC_TYPE_SONY,		"sony"		},  	{ RC_TYPE_RC5_SZ,	"rc-5-sz"	}, +	{ RC_TYPE_MCE_KBD,	"mce_kbd"	},  	{ RC_TYPE_LIRC,		"lirc"		},  	{ RC_TYPE_OTHER,	"other"		},  }; @@ -1097,7 +1100,6 @@ int rc_register_device(struct rc_dev *dev)  		if (rc < 0)  			goto out_input;  	} -	mutex_unlock(&dev->lock);  	if (dev->change_protocol) {  		rc = dev->change_protocol(dev, rc_map->rc_type); @@ -1105,6 +1107,8 @@ int rc_register_device(struct rc_dev *dev)  			goto out_raw;  	} +	mutex_unlock(&dev->lock); +  	IR_dprintk(1, "Registered rc%ld (driver: %s, remote: %s, mode %s)\n",  		   dev->devno,  		   dev->driver_name ? dev->driver_name : "unknown", diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c index 5147767ccb78..a16604477917 100644 --- a/drivers/media/rc/redrat3.c +++ b/drivers/media/rc/redrat3.c @@ -205,6 +205,7 @@ struct redrat3_dev {  	/* rx signal timeout timer */  	struct timer_list rx_timeout; +	u32 hw_timeout;  	/* Is the device currently receiving? */  	bool recv_in_progress; @@ -414,20 +415,10 @@ static u32 redrat3_us_to_len(u32 microsec)  } -/* timer callback to send long trailing space on receive timeout */ +/* timer callback to send reset event */  static void redrat3_rx_timeout(unsigned long data)  {  	struct redrat3_dev *rr3 = (struct redrat3_dev *)data; -	DEFINE_IR_RAW_EVENT(rawir); - -	rawir.pulse = false; -	rawir.duration = rr3->rc->timeout; -	rr3_dbg(rr3->dev, "storing trailing space with duration %d\n", -		rawir.duration); -	ir_raw_event_store_with_filter(rr3->rc, &rawir); - -	rr3_dbg(rr3->dev, "calling ir_raw_event_handle\n"); -	ir_raw_event_handle(rr3->rc);  	rr3_dbg(rr3->dev, "calling ir_raw_event_reset\n");  	ir_raw_event_reset(rr3->rc); @@ -438,7 +429,7 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)  	DEFINE_IR_RAW_EVENT(rawir);  	struct redrat3_signal_header header;  	struct device *dev; -	int i; +	int i, trailer = 0;  	unsigned long delay;  	u32 mod_freq, single_len;  	u16 *len_vals; @@ -464,7 +455,8 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)  	if (!(header.length >= RR3_HEADER_LENGTH))  		dev_warn(dev, "read returned less than rr3 header len\n"); -	delay = usecs_to_jiffies(rr3->rc->timeout / 1000); +	/* Make sure we reset the IR kfifo after a bit of inactivity */ +	delay = usecs_to_jiffies(rr3->hw_timeout);  	mod_timer(&rr3->rx_timeout, jiffies + delay);  	memcpy(&tmp32, sig_data + RR3_PAUSE_OFFSET, sizeof(tmp32)); @@ -506,9 +498,6 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)  		u16 val = len_vals[data_vals[i]];  		single_len = redrat3_len_to_us((u32)be16_to_cpu(val)); -		/* cap the value to IR_MAX_DURATION */ -		single_len &= IR_MAX_DURATION; -  		/* we should always get pulse/space/pulse/space samples */  		if (i % 2)  			rawir.pulse = false; @@ -516,6 +505,12 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)  			rawir.pulse = true;  		rawir.duration = US_TO_NS(single_len); +		/* Save initial pulse length to fudge trailer */ +		if (i == 0) +			trailer = rawir.duration; +		/* cap the value to IR_MAX_DURATION */ +		rawir.duration &= IR_MAX_DURATION; +  		rr3_dbg(dev, "storing %s with duration %d (i: %d)\n",  			rawir.pulse ? "pulse" : "space", rawir.duration, i);  		ir_raw_event_store_with_filter(rr3->rc, &rawir); @@ -525,7 +520,10 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)  	if (i % 2) {  		rawir.pulse = false;  		/* this duration is made up, and may not be ideal... */ -		rawir.duration = rr3->rc->timeout / 2; +		if (trailer < US_TO_NS(1000)) +			rawir.duration = US_TO_NS(2800); +		else +			rawir.duration = trailer;  		rr3_dbg(dev, "storing trailing space with duration %d\n",  			rawir.duration);  		ir_raw_event_store_with_filter(rr3->rc, &rawir); @@ -629,36 +627,31 @@ static inline void redrat3_delete(struct redrat3_dev *rr3,  	kfree(rr3);  } -static u32 redrat3_get_timeout(struct device *dev, -			       struct rc_dev *rc, struct usb_device *udev) +static u32 redrat3_get_timeout(struct redrat3_dev *rr3)  {  	u32 *tmp; -	u32 timeout = MS_TO_NS(150); /* a sane default, if things go haywire */ +	u32 timeout = MS_TO_US(150); /* a sane default, if things go haywire */  	int len, ret, pipe;  	len = sizeof(*tmp);  	tmp = kzalloc(len, GFP_KERNEL);  	if (!tmp) { -		dev_warn(dev, "Memory allocation faillure\n"); +		dev_warn(rr3->dev, "Memory allocation faillure\n");  		return timeout;  	} -	pipe = usb_rcvctrlpipe(udev, 0); -	ret = usb_control_msg(udev, pipe, RR3_GET_IR_PARAM, +	pipe = usb_rcvctrlpipe(rr3->udev, 0); +	ret = usb_control_msg(rr3->udev, pipe, RR3_GET_IR_PARAM,  			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,  			      RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, HZ * 5);  	if (ret != len) { -		dev_warn(dev, "Failed to read timeout from hardware\n"); +		dev_warn(rr3->dev, "Failed to read timeout from hardware\n");  		return timeout;  	} -	timeout = US_TO_NS(redrat3_len_to_us(be32_to_cpu(*tmp))); -	if (timeout < rc->min_timeout) -		timeout = rc->min_timeout; -	else if (timeout > rc->max_timeout) -		timeout = rc->max_timeout; +	timeout = redrat3_len_to_us(be32_to_cpu(*tmp)); -	rr3_dbg(dev, "Got timeout of %d ms\n", timeout / (1000 * 1000)); +	rr3_dbg(rr3->dev, "Got timeout of %d ms\n", timeout / 1000);  	return timeout;  } @@ -1110,9 +1103,7 @@ static struct rc_dev *redrat3_init_rc_dev(struct redrat3_dev *rr3)  	rc->priv = rr3;  	rc->driver_type = RC_DRIVER_IR_RAW;  	rc->allowed_protos = RC_TYPE_ALL; -	rc->min_timeout = MS_TO_NS(RR3_RX_MIN_TIMEOUT); -	rc->max_timeout = MS_TO_NS(RR3_RX_MAX_TIMEOUT); -	rc->timeout = redrat3_get_timeout(dev, rc, rr3->udev); +	rc->timeout = US_TO_NS(2750);  	rc->tx_ir = redrat3_transmit_ir;  	rc->s_tx_carrier = redrat3_set_tx_carrier;  	rc->driver_name = DRIVER_NAME; @@ -1186,7 +1177,7 @@ static int __devinit redrat3_dev_probe(struct usb_interface *intf,  	rr3 = kzalloc(sizeof(*rr3), GFP_KERNEL);  	if (rr3 == NULL) {  		dev_err(dev, "Memory allocation failure\n"); -		goto error; +		goto no_endpoints;  	}  	rr3->dev = &intf->dev; @@ -1242,6 +1233,9 @@ static int __devinit redrat3_dev_probe(struct usb_interface *intf,  	if (retval < 0)  		goto error; +	/* store current hardware timeout, in us, will use for kfifo resets */ +	rr3->hw_timeout = redrat3_get_timeout(rr3); +  	/* default.. will get overridden by any sends with a freq defined */  	rr3->carrier = 38000; @@ -1280,6 +1274,7 @@ static void __devexit redrat3_dev_disconnect(struct usb_interface *intf)  	usb_set_intfdata(intf, NULL);  	rc_unregister_device(rr3->rc); +	del_timer_sync(&rr3->rx_timeout);  	redrat3_delete(rr3, udev);  	rr3_ftr(&intf->dev, "RedRat3 IR Transceiver now disconnected\n"); diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index 5d06b899e859..bec8abc965f7 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c @@ -6,8 +6,8 @@   *  could probably support others (Winbond WEC102X, NatSemi, etc)   *  with minor modifications.   * - *  Original Author: David Härdeman <david@hardeman.nu> - *     Copyright (C) 2009 - 2010 David Härdeman <david@hardeman.nu> + *  Original Author: David Härdeman <david@hardeman.nu> + *     Copyright (C) 2009 - 2011 David Härdeman <david@hardeman.nu>   *   *  Dedicated to my daughter Matilda, without whose loving attention this   *  driver would have been finished in half the time and with a fraction @@ -577,16 +577,12 @@ wbcir_txmask(struct rc_dev *dev, u32 mask)  }  static int -wbcir_tx(struct rc_dev *dev, int *buf, u32 bufsize) +wbcir_tx(struct rc_dev *dev, unsigned *buf, unsigned count)  {  	struct wbcir_data *data = dev->priv; -	u32 count;  	unsigned i;  	unsigned long flags; -	/* bufsize has been sanity checked by the caller */ -	count = bufsize / sizeof(int); -  	/* Not sure if this is possible, but better safe than sorry */  	spin_lock_irqsave(&data->spinlock, flags);  	if (data->txstate != WBCIR_TXSTATE_INACTIVE) { @@ -876,18 +872,8 @@ wbcir_init_hw(struct wbcir_data *data)  	/* prescaler 1.0, tx/rx fifo lvl 16 */  	outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2); -	/* Set baud divisor to generate one byte per bit/cell */ -	switch (protocol) { -	case IR_PROTOCOL_RC5: -		outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL); -		break; -	case IR_PROTOCOL_RC6: -		outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL); -		break; -	case IR_PROTOCOL_NEC: -		outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL); -		break; -	} +	/* Set baud divisor to sample every 10 us */ +	outb(0x0F, data->sbase + WBCIR_REG_SP3_BGDL);  	outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);  	/* Set CEIR mode */ @@ -896,9 +882,9 @@ wbcir_init_hw(struct wbcir_data *data)  	inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */  	inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */ -	/* Disable RX demod, run-length encoding/decoding, set freq span */ +	/* Disable RX demod, enable run-length enc/dec, set freq span */  	wbcir_select_bank(data, WBCIR_BANK_7); -	outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG); +	outb(0x90, data->sbase + WBCIR_REG_SP3_RCCFG);  	/* Disable timer */  	wbcir_select_bank(data, WBCIR_BANK_4); | 
