| 
									
										
										
										
											2009-12-11 08:34:07 -03:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Remote Controller core header | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2010-03-24 20:47:53 -03:00
										 |  |  |  * Copyright (C) 2009-2010 by Mauro Carvalho Chehab <mchehab@redhat.com> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2009-12-11 08:34:07 -03:00
										 |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-17 13:53:11 -03:00
										 |  |  | #ifndef _RC_CORE
 | 
					
						
							|  |  |  | #define _RC_CORE
 | 
					
						
							| 
									
										
										
										
											2009-12-11 08:34:07 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <linux/spinlock.h>
 | 
					
						
							| 
									
										
										
										
											2010-03-20 20:59:44 -03:00
										 |  |  | #include <linux/kfifo.h>
 | 
					
						
							|  |  |  | #include <linux/time.h>
 | 
					
						
							| 
									
										
										
										
											2010-03-21 13:00:55 -03:00
										 |  |  | #include <linux/timer.h>
 | 
					
						
							| 
									
										
										
										
											2010-04-02 20:01:00 -03:00
										 |  |  | #include <media/rc-map.h>
 | 
					
						
							| 
									
										
										
										
											2009-12-11 08:34:07 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-17 13:28:38 -03:00
										 |  |  | extern int rc_core_debug; | 
					
						
							| 
									
										
										
										
											2011-08-21 19:56:45 -03:00
										 |  |  | #define IR_dprintk(level, fmt, ...)				\
 | 
					
						
							|  |  |  | do {								\ | 
					
						
							|  |  |  | 	if (rc_core_debug >= level)				\ | 
					
						
							|  |  |  | 		pr_debug("%s: " fmt, __func__, ##__VA_ARGS__);	\ | 
					
						
							|  |  |  | } while (0) | 
					
						
							| 
									
										
										
										
											2009-12-11 08:34:07 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-06 23:21:46 -03:00
										 |  |  | enum rc_driver_type { | 
					
						
							|  |  |  | 	RC_DRIVER_SCANCODE = 0,	/* Driver or hardware generates a scancode */ | 
					
						
							|  |  |  | 	RC_DRIVER_IR_RAW,	/* Needs a Infra-Red pulse/space decoder */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-04 14:06:55 -03:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  |  * struct rc_dev - represents a remote control device | 
					
						
							|  |  |  |  * @dev: driver model's view of this device | 
					
						
							|  |  |  |  * @input_name: name of the input child device | 
					
						
							|  |  |  |  * @input_phys: physical path to the input child device | 
					
						
							|  |  |  |  * @input_id: id of the input child device (struct input_id) | 
					
						
							|  |  |  |  * @driver_name: name of the hardware driver which registered this device | 
					
						
							|  |  |  |  * @map_name: name of the default keymap | 
					
						
							| 
									
										
										
										
											2010-11-17 14:28:27 -03:00
										 |  |  |  * @rc_map: current scan/key table | 
					
						
							| 
									
										
										
										
											2011-05-11 15:14:31 -03:00
										 |  |  |  * @lock: used to ensure we've filled in all protocol details before | 
					
						
							|  |  |  |  *	anyone can call show_protocols or store_protocols | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  |  * @devno: unique remote control device number | 
					
						
							|  |  |  |  * @raw: additional data for raw pulse/space devices | 
					
						
							|  |  |  |  * @input_dev: the input child device used to communicate events to userspace | 
					
						
							| 
									
										
										
										
											2011-05-11 15:14:31 -03:00
										 |  |  |  * @driver_type: specifies if protocol decoding is done in hardware or software | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  |  * @idle: used to keep track of RX state | 
					
						
							| 
									
										
										
										
											2012-10-11 19:11:54 -03:00
										 |  |  |  * @allowed_protos: bitmask with the supported RC_BIT_* protocols | 
					
						
							| 
									
										
										
										
											2013-03-06 16:52:05 -03:00
										 |  |  |  * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols | 
					
						
							| 
									
										
										
										
											2010-04-04 14:06:55 -03:00
										 |  |  |  * @scanmask: some hardware decoders are not capable of providing the full | 
					
						
							|  |  |  |  *	scancode to the application. As this is a hardware limit, we can't do | 
					
						
							|  |  |  |  *	anything with it. Yet, as the same keycode table can be used with other | 
					
						
							|  |  |  |  *	devices, a mask is provided to allow its usage. Drivers should generally | 
					
						
							|  |  |  |  *	leave this field in blank | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  |  * @priv: driver-specific data | 
					
						
							|  |  |  |  * @keylock: protects the remaining members of the struct | 
					
						
							|  |  |  |  * @keypressed: whether a key is currently pressed | 
					
						
							|  |  |  |  * @keyup_jiffies: time (in jiffies) when the current keypress should be released | 
					
						
							|  |  |  |  * @timer_keyup: timer for releasing a keypress | 
					
						
							|  |  |  |  * @last_keycode: keycode of last keypress | 
					
						
							|  |  |  |  * @last_scancode: scancode of last keypress | 
					
						
							|  |  |  |  * @last_toggle: toggle value of last command | 
					
						
							| 
									
										
										
										
											2010-07-31 11:59:22 -03:00
										 |  |  |  * @timeout: optional time after which device stops sending data | 
					
						
							|  |  |  |  * @min_timeout: minimum timeout supported by device | 
					
						
							|  |  |  |  * @max_timeout: maximum timeout supported by device | 
					
						
							| 
									
										
										
										
											2010-07-31 11:59:23 -03:00
										 |  |  |  * @rx_resolution : resolution (in ns) of input sampler | 
					
						
							|  |  |  |  * @tx_resolution: resolution (in ns) of output sampler | 
					
						
							| 
									
										
										
										
											2010-04-04 14:06:55 -03:00
										 |  |  |  * @change_protocol: allow changing the protocol used on hardware decoders | 
					
						
							|  |  |  |  * @open: callback to allow drivers to enable polling/irq when IR input device | 
					
						
							|  |  |  |  *	is opened. | 
					
						
							|  |  |  |  * @close: callback to allow drivers to disable polling/irq when IR input device | 
					
						
							|  |  |  |  *	is opened. | 
					
						
							| 
									
										
										
										
											2010-06-16 17:55:25 -03:00
										 |  |  |  * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs) | 
					
						
							|  |  |  |  * @s_tx_carrier: set transmit carrier frequency | 
					
						
							| 
									
										
										
										
											2010-07-31 11:59:23 -03:00
										 |  |  |  * @s_tx_duty_cycle: set transmit duty cycle (0% - 100%) | 
					
						
							|  |  |  |  * @s_rx_carrier: inform driver about carrier it is expected to handle | 
					
						
							| 
									
										
										
										
											2010-06-16 17:55:25 -03:00
										 |  |  |  * @tx_ir: transmit IR | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  |  * @s_idle: enable/disable hardware idle mode, upon which, | 
					
						
							|  |  |  |  *	device doesn't interrupt host until it sees IR pulses | 
					
						
							| 
									
										
										
										
											2010-07-31 11:59:23 -03:00
										 |  |  |  * @s_learning_mode: enable wide band receiver used for learning | 
					
						
							| 
									
										
										
										
											2010-10-16 19:56:28 -03:00
										 |  |  |  * @s_carrier_report: enable carrier reports | 
					
						
							| 
									
										
										
										
											2010-04-04 14:06:55 -03:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  | struct rc_dev { | 
					
						
							|  |  |  | 	struct device			dev; | 
					
						
							|  |  |  | 	const char			*input_name; | 
					
						
							|  |  |  | 	const char			*input_phys; | 
					
						
							|  |  |  | 	struct input_id			input_id; | 
					
						
							|  |  |  | 	char				*driver_name; | 
					
						
							|  |  |  | 	const char			*map_name; | 
					
						
							| 
									
										
										
										
											2011-05-11 15:14:31 -03:00
										 |  |  | 	struct rc_map			rc_map; | 
					
						
							|  |  |  | 	struct mutex			lock; | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  | 	unsigned long			devno; | 
					
						
							|  |  |  | 	struct ir_raw_event_ctrl	*raw; | 
					
						
							|  |  |  | 	struct input_dev		*input_dev; | 
					
						
							|  |  |  | 	enum rc_driver_type		driver_type; | 
					
						
							| 
									
										
										
										
											2010-07-31 11:59:22 -03:00
										 |  |  | 	bool				idle; | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  | 	u64				allowed_protos; | 
					
						
							| 
									
										
										
										
											2013-03-06 16:52:05 -03:00
										 |  |  | 	u64				enabled_protocols; | 
					
						
							| 
									
										
										
										
											2013-07-22 04:22:57 -03:00
										 |  |  | 	u32				users; | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  | 	u32				scanmask; | 
					
						
							|  |  |  | 	void				*priv; | 
					
						
							|  |  |  | 	spinlock_t			keylock; | 
					
						
							|  |  |  | 	bool				keypressed; | 
					
						
							|  |  |  | 	unsigned long			keyup_jiffies; | 
					
						
							|  |  |  | 	struct timer_list		timer_keyup; | 
					
						
							|  |  |  | 	u32				last_keycode; | 
					
						
							|  |  |  | 	u32				last_scancode; | 
					
						
							|  |  |  | 	u8				last_toggle; | 
					
						
							|  |  |  | 	u32				timeout; | 
					
						
							|  |  |  | 	u32				min_timeout; | 
					
						
							|  |  |  | 	u32				max_timeout; | 
					
						
							|  |  |  | 	u32				rx_resolution; | 
					
						
							|  |  |  | 	u32				tx_resolution; | 
					
						
							| 
									
										
										
										
											2012-10-11 19:11:54 -03:00
										 |  |  | 	int				(*change_protocol)(struct rc_dev *dev, u64 *rc_type); | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  | 	int				(*open)(struct rc_dev *dev); | 
					
						
							|  |  |  | 	void				(*close)(struct rc_dev *dev); | 
					
						
							|  |  |  | 	int				(*s_tx_mask)(struct rc_dev *dev, u32 mask); | 
					
						
							|  |  |  | 	int				(*s_tx_carrier)(struct rc_dev *dev, u32 carrier); | 
					
						
							|  |  |  | 	int				(*s_tx_duty_cycle)(struct rc_dev *dev, u32 duty_cycle); | 
					
						
							|  |  |  | 	int				(*s_rx_carrier_range)(struct rc_dev *dev, u32 min, u32 max); | 
					
						
							| 
									
										
										
										
											2011-04-28 12:13:58 -03:00
										 |  |  | 	int				(*tx_ir)(struct rc_dev *dev, unsigned *txbuf, unsigned n); | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  | 	void				(*s_idle)(struct rc_dev *dev, bool enable); | 
					
						
							|  |  |  | 	int				(*s_learning_mode)(struct rc_dev *dev, int enable); | 
					
						
							|  |  |  | 	int				(*s_carrier_report) (struct rc_dev *dev, int enable); | 
					
						
							| 
									
										
										
										
											2009-12-11 09:44:23 -03:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2010-03-20 20:59:44 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-17 13:53:11 -03:00
										 |  |  | #define to_rc_dev(d) container_of(d, struct rc_dev, dev)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * From rc-main.c | 
					
						
							|  |  |  |  * Those functions can be used on any type of Remote Controller. They | 
					
						
							|  |  |  |  * basically creates an input_dev and properly reports the device as a | 
					
						
							|  |  |  |  * Remote Controller, at sys/class/rc. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct rc_dev *rc_allocate_device(void); | 
					
						
							|  |  |  | void rc_free_device(struct rc_dev *dev); | 
					
						
							|  |  |  | int rc_register_device(struct rc_dev *dev); | 
					
						
							|  |  |  | void rc_unregister_device(struct rc_dev *dev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-22 04:22:57 -03:00
										 |  |  | int rc_open(struct rc_dev *rdev); | 
					
						
							|  |  |  | void rc_close(struct rc_dev *rdev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-17 13:53:11 -03:00
										 |  |  | void rc_repeat(struct rc_dev *dev); | 
					
						
							|  |  |  | void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle); | 
					
						
							|  |  |  | void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle); | 
					
						
							|  |  |  | void rc_keyup(struct rc_dev *dev); | 
					
						
							|  |  |  | u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * From rc-raw.c | 
					
						
							|  |  |  |  * The Raw interface is specific to InfraRed. It may be a good idea to | 
					
						
							|  |  |  |  * split it later into a separate header. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-08 15:10:27 -03:00
										 |  |  | enum raw_event_type { | 
					
						
							|  |  |  | 	IR_SPACE        = (1 << 0), | 
					
						
							|  |  |  | 	IR_PULSE        = (1 << 1), | 
					
						
							|  |  |  | 	IR_START_EVENT  = (1 << 2), | 
					
						
							|  |  |  | 	IR_STOP_EVENT   = (1 << 3), | 
					
						
							| 
									
										
										
										
											2010-03-24 20:47:53 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-15 18:46:00 -03:00
										 |  |  | struct ir_raw_event { | 
					
						
							| 
									
										
										
										
											2010-10-16 19:56:28 -03:00
										 |  |  | 	union { | 
					
						
							|  |  |  | 		u32             duration; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		struct { | 
					
						
							|  |  |  | 			u32     carrier; | 
					
						
							|  |  |  | 			u8      duty_cycle; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	unsigned                pulse:1; | 
					
						
							|  |  |  | 	unsigned                reset:1; | 
					
						
							|  |  |  | 	unsigned                timeout:1; | 
					
						
							|  |  |  | 	unsigned                carrier_report:1; | 
					
						
							| 
									
										
										
										
											2010-04-15 18:46:00 -03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-16 19:56:28 -03:00
										 |  |  | #define DEFINE_IR_RAW_EVENT(event) \
 | 
					
						
							|  |  |  | 	struct ir_raw_event event = { \ | 
					
						
							|  |  |  | 		{ .duration = 0 } , \ | 
					
						
							|  |  |  | 		.pulse = 0, \ | 
					
						
							|  |  |  | 		.reset = 0, \ | 
					
						
							|  |  |  | 		.timeout = 0, \ | 
					
						
							|  |  |  | 		.carrier_report = 0 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void init_ir_raw_event(struct ir_raw_event *ev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	memset(ev, 0, sizeof(*ev)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define IR_MAX_DURATION         0xFFFFFFFF      /* a bit more than 4 seconds */
 | 
					
						
							| 
									
										
										
										
											2011-01-06 16:59:36 -03:00
										 |  |  | #define US_TO_NS(usec)		((usec) * 1000)
 | 
					
						
							|  |  |  | #define MS_TO_US(msec)		((msec) * 1000)
 | 
					
						
							|  |  |  | #define MS_TO_NS(msec)		((msec) * 1000 * 1000)
 | 
					
						
							| 
									
										
										
										
											2010-04-15 18:46:00 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  | void ir_raw_event_handle(struct rc_dev *dev); | 
					
						
							|  |  |  | int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev); | 
					
						
							|  |  |  | int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type); | 
					
						
							|  |  |  | int ir_raw_event_store_with_filter(struct rc_dev *dev, | 
					
						
							| 
									
										
										
										
											2010-07-31 11:59:22 -03:00
										 |  |  | 				struct ir_raw_event *ev); | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  | void ir_raw_event_set_idle(struct rc_dev *dev, bool idle); | 
					
						
							| 
									
										
										
										
											2010-07-31 11:59:22 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  | static inline void ir_raw_event_reset(struct rc_dev *dev) | 
					
						
							| 
									
										
										
										
											2010-04-15 18:46:00 -03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-16 19:56:28 -03:00
										 |  |  | 	DEFINE_IR_RAW_EVENT(ev); | 
					
						
							|  |  |  | 	ev.reset = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:23 -03:00
										 |  |  | 	ir_raw_event_store(dev, &ev); | 
					
						
							|  |  |  | 	ir_raw_event_handle(dev); | 
					
						
							| 
									
										
										
										
											2010-04-15 18:46:00 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-04-08 13:10:00 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:12 -03:00
										 |  |  | /* extract mask bits out of data and pack them into the result */ | 
					
						
							|  |  |  | static inline u32 ir_extract_bits(u32 data, u32 mask) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u32 vbit = 1, value = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	do { | 
					
						
							| 
									
										
										
										
											2010-11-19 20:43:27 -03:00
										 |  |  | 		if (mask & 1) { | 
					
						
							|  |  |  | 			if (data & 1) | 
					
						
							|  |  |  | 				value |= vbit; | 
					
						
							|  |  |  | 			vbit <<= 1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		data >>= 1; | 
					
						
							| 
									
										
										
										
											2010-10-29 16:08:12 -03:00
										 |  |  | 	} while (mask >>= 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return value; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-11-17 13:53:11 -03:00
										 |  |  | #endif /* _RC_CORE */
 |