PageRenderTime 37ms CodeModel.GetById 23ms app.highlight 12ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/media/rc/ir-sony-decoder.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2
C | 181 lines | 126 code | 34 blank | 21 comment | 19 complexity | a7c798058955a25c3bdd146cb7f2a016 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/* ir-sony-decoder.c - handle Sony IR Pulse/Space protocol
  2 *
  3 * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
  4 *
  5 * This program is free software; you can redistribute it and/or modify
  6 * it under the terms of the GNU General Public License as published by
  7 * the Free Software Foundation version 2 of the License.
  8 *
  9 * This program is distributed in the hope that it will be useful,
 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 * GNU General Public License for more details.
 13 */
 14
 15#include <linux/bitrev.h>
 16#include "rc-core-priv.h"
 17
 18#define SONY_UNIT		600000 /* ns */
 19#define SONY_HEADER_PULSE	(4 * SONY_UNIT)
 20#define	SONY_HEADER_SPACE	(1 * SONY_UNIT)
 21#define SONY_BIT_0_PULSE	(1 * SONY_UNIT)
 22#define SONY_BIT_1_PULSE	(2 * SONY_UNIT)
 23#define SONY_BIT_SPACE		(1 * SONY_UNIT)
 24#define SONY_TRAILER_SPACE	(10 * SONY_UNIT) /* minimum */
 25
 26enum sony_state {
 27	STATE_INACTIVE,
 28	STATE_HEADER_SPACE,
 29	STATE_BIT_PULSE,
 30	STATE_BIT_SPACE,
 31	STATE_FINISHED,
 32};
 33
 34/**
 35 * ir_sony_decode() - Decode one Sony pulse or space
 36 * @dev:	the struct rc_dev descriptor of the device
 37 * @ev:         the struct ir_raw_event descriptor of the pulse/space
 38 *
 39 * This function returns -EINVAL if the pulse violates the state machine
 40 */
 41static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
 42{
 43	struct sony_dec *data = &dev->raw->sony;
 44	u32 scancode;
 45	u8 device, subdevice, function;
 46
 47	if (!(dev->raw->enabled_protocols & RC_TYPE_SONY))
 48		return 0;
 49
 50	if (!is_timing_event(ev)) {
 51		if (ev.reset)
 52			data->state = STATE_INACTIVE;
 53		return 0;
 54	}
 55
 56	if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2))
 57		goto out;
 58
 59	IR_dprintk(2, "Sony decode started at state %d (%uus %s)\n",
 60		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
 61
 62	switch (data->state) {
 63
 64	case STATE_INACTIVE:
 65		if (!ev.pulse)
 66			break;
 67
 68		if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2))
 69			break;
 70
 71		data->count = 0;
 72		data->state = STATE_HEADER_SPACE;
 73		return 0;
 74
 75	case STATE_HEADER_SPACE:
 76		if (ev.pulse)
 77			break;
 78
 79		if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2))
 80			break;
 81
 82		data->state = STATE_BIT_PULSE;
 83		return 0;
 84
 85	case STATE_BIT_PULSE:
 86		if (!ev.pulse)
 87			break;
 88
 89		data->bits <<= 1;
 90		if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
 91			data->bits |= 1;
 92		else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
 93			break;
 94
 95		data->count++;
 96		data->state = STATE_BIT_SPACE;
 97		return 0;
 98
 99	case STATE_BIT_SPACE:
100		if (ev.pulse)
101			break;
102
103		if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2))
104			break;
105
106		decrease_duration(&ev, SONY_BIT_SPACE);
107
108		if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) {
109			data->state = STATE_BIT_PULSE;
110			return 0;
111		}
112
113		data->state = STATE_FINISHED;
114		/* Fall through */
115
116	case STATE_FINISHED:
117		if (ev.pulse)
118			break;
119
120		if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2))
121			break;
122
123		switch (data->count) {
124		case 12:
125			device    = bitrev8((data->bits <<  3) & 0xF8);
126			subdevice = 0;
127			function  = bitrev8((data->bits >>  4) & 0xFE);
128			break;
129		case 15:
130			device    = bitrev8((data->bits >>  0) & 0xFF);
131			subdevice = 0;
132			function  = bitrev8((data->bits >>  7) & 0xFD);
133			break;
134		case 20:
135			device    = bitrev8((data->bits >>  5) & 0xF8);
136			subdevice = bitrev8((data->bits >>  0) & 0xFF);
137			function  = bitrev8((data->bits >> 12) & 0xFE);
138			break;
139		default:
140			IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
141			goto out;
142		}
143
144		scancode = device << 16 | subdevice << 8 | function;
145		IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
146		rc_keydown(dev, scancode, 0);
147		data->state = STATE_INACTIVE;
148		return 0;
149	}
150
151out:
152	IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n",
153		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
154	data->state = STATE_INACTIVE;
155	return -EINVAL;
156}
157
158static struct ir_raw_handler sony_handler = {
159	.protocols	= RC_TYPE_SONY,
160	.decode		= ir_sony_decode,
161};
162
163static int __init ir_sony_decode_init(void)
164{
165	ir_raw_handler_register(&sony_handler);
166
167	printk(KERN_INFO "IR Sony protocol handler initialized\n");
168	return 0;
169}
170
171static void __exit ir_sony_decode_exit(void)
172{
173	ir_raw_handler_unregister(&sony_handler);
174}
175
176module_init(ir_sony_decode_init);
177module_exit(ir_sony_decode_exit);
178
179MODULE_LICENSE("GPL");
180MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
181MODULE_DESCRIPTION("Sony IR protocol decoder");