xref: /openbmc/linux/include/media/rc-core.h (revision fcb13097867757d360d5226d36ed3ffe849dc3ae)
16bda9644SMauro Carvalho Chehab /*
26bda9644SMauro Carvalho Chehab  * Remote Controller core header
36bda9644SMauro Carvalho Chehab  *
437e59f87SMauro Carvalho Chehab  * Copyright (C) 2009-2010 by Mauro Carvalho Chehab
56bda9644SMauro Carvalho Chehab  *
66bda9644SMauro Carvalho Chehab  * This program is free software; you can redistribute it and/or modify
76bda9644SMauro Carvalho Chehab  *  it under the terms of the GNU General Public License as published by
86bda9644SMauro Carvalho Chehab  *  the Free Software Foundation version 2 of the License.
96bda9644SMauro Carvalho Chehab  *
106bda9644SMauro Carvalho Chehab  *  This program is distributed in the hope that it will be useful,
116bda9644SMauro Carvalho Chehab  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
126bda9644SMauro Carvalho Chehab  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
136bda9644SMauro Carvalho Chehab  *  GNU General Public License for more details.
146bda9644SMauro Carvalho Chehab  */
156bda9644SMauro Carvalho Chehab 
16ca86674bSMauro Carvalho Chehab #ifndef _RC_CORE
17ca86674bSMauro Carvalho Chehab #define _RC_CORE
186bda9644SMauro Carvalho Chehab 
196bda9644SMauro Carvalho Chehab #include <linux/spinlock.h>
206bda9644SMauro Carvalho Chehab #include <linux/kfifo.h>
216bda9644SMauro Carvalho Chehab #include <linux/time.h>
226bda9644SMauro Carvalho Chehab #include <linux/timer.h>
236bda9644SMauro Carvalho Chehab #include <media/rc-map.h>
246bda9644SMauro Carvalho Chehab 
256bda9644SMauro Carvalho Chehab extern int rc_core_debug;
2686b0dbefSJoe Perches #define IR_dprintk(level, fmt, ...)				\
2786b0dbefSJoe Perches do {								\
2886b0dbefSJoe Perches 	if (rc_core_debug >= level)				\
297cec72ceSMauro Carvalho Chehab 		printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__);	\
3086b0dbefSJoe Perches } while (0)
316bda9644SMauro Carvalho Chehab 
326bda9644SMauro Carvalho Chehab enum rc_driver_type {
336bda9644SMauro Carvalho Chehab 	RC_DRIVER_SCANCODE = 0,	/* Driver or hardware generates a scancode */
346bda9644SMauro Carvalho Chehab 	RC_DRIVER_IR_RAW,	/* Needs a Infra-Red pulse/space decoder */
356bda9644SMauro Carvalho Chehab };
366bda9644SMauro Carvalho Chehab 
376bda9644SMauro Carvalho Chehab /**
3800942d1aSJames Hogan  * struct rc_scancode_filter - Filter scan codes.
3900942d1aSJames Hogan  * @data:	Scancode data to match.
4000942d1aSJames Hogan  * @mask:	Mask of bits of scancode to compare.
4100942d1aSJames Hogan  */
4200942d1aSJames Hogan struct rc_scancode_filter {
4300942d1aSJames Hogan 	u32 data;
4400942d1aSJames Hogan 	u32 mask;
4500942d1aSJames Hogan };
4600942d1aSJames Hogan 
4700942d1aSJames Hogan /**
4800942d1aSJames Hogan  * enum rc_filter_type - Filter type constants.
4900942d1aSJames Hogan  * @RC_FILTER_NORMAL:	Filter for normal operation.
5000942d1aSJames Hogan  * @RC_FILTER_WAKEUP:	Filter for waking from suspend.
5100942d1aSJames Hogan  * @RC_FILTER_MAX:	Number of filter types.
5200942d1aSJames Hogan  */
5300942d1aSJames Hogan enum rc_filter_type {
5400942d1aSJames Hogan 	RC_FILTER_NORMAL = 0,
5500942d1aSJames Hogan 	RC_FILTER_WAKEUP,
5600942d1aSJames Hogan 
5700942d1aSJames Hogan 	RC_FILTER_MAX
5800942d1aSJames Hogan };
5900942d1aSJames Hogan 
6000942d1aSJames Hogan /**
616bda9644SMauro Carvalho Chehab  * struct rc_dev - represents a remote control device
626bda9644SMauro Carvalho Chehab  * @dev: driver model's view of this device
6399b0f3c9SDavid Härdeman  * @sysfs_groups: sysfs attribute groups
646bda9644SMauro Carvalho Chehab  * @input_name: name of the input child device
656bda9644SMauro Carvalho Chehab  * @input_phys: physical path to the input child device
666bda9644SMauro Carvalho Chehab  * @input_id: id of the input child device (struct input_id)
676bda9644SMauro Carvalho Chehab  * @driver_name: name of the hardware driver which registered this device
686bda9644SMauro Carvalho Chehab  * @map_name: name of the default keymap
69b088ba65SMauro Carvalho Chehab  * @rc_map: current scan/key table
7008aeb7c9SJarod Wilson  * @lock: used to ensure we've filled in all protocol details before
7108aeb7c9SJarod Wilson  *	anyone can call show_protocols or store_protocols
72*fcb13097SDavid Härdeman  * @minor: unique minor remote control device number
736bda9644SMauro Carvalho Chehab  * @raw: additional data for raw pulse/space devices
746bda9644SMauro Carvalho Chehab  * @input_dev: the input child device used to communicate events to userspace
756bda9644SMauro Carvalho Chehab  * @driver_type: specifies if protocol decoding is done in hardware or software
766bda9644SMauro Carvalho Chehab  * @idle: used to keep track of RX state
770d830b2dSJames Hogan  * @encode_wakeup: wakeup filtering uses IR encode API, therefore the allowed
780d830b2dSJames Hogan  *	wakeup protocols is the set of all raw encoders
79c5540fbbSDavid Härdeman  * @allowed_protocols: bitmask with the supported RC_BIT_* protocols
80c5540fbbSDavid Härdeman  * @enabled_protocols: bitmask with the enabled RC_BIT_* protocols
81c5540fbbSDavid Härdeman  * @allowed_wakeup_protocols: bitmask with the supported RC_BIT_* wakeup protocols
82c5540fbbSDavid Härdeman  * @enabled_wakeup_protocols: bitmask with the enabled RC_BIT_* wakeup protocols
83c5540fbbSDavid Härdeman  * @scancode_filter: scancode filter
84c5540fbbSDavid Härdeman  * @scancode_wakeup_filter: scancode wakeup filters
859d2f1d3cSDavid Härdeman  * @scancode_mask: some hardware decoders are not capable of providing the full
866bda9644SMauro Carvalho Chehab  *	scancode to the application. As this is a hardware limit, we can't do
876bda9644SMauro Carvalho Chehab  *	anything with it. Yet, as the same keycode table can be used with other
886bda9644SMauro Carvalho Chehab  *	devices, a mask is provided to allow its usage. Drivers should generally
896bda9644SMauro Carvalho Chehab  *	leave this field in blank
909d2f1d3cSDavid Härdeman  * @users: number of current users of the device
916bda9644SMauro Carvalho Chehab  * @priv: driver-specific data
926bda9644SMauro Carvalho Chehab  * @keylock: protects the remaining members of the struct
936bda9644SMauro Carvalho Chehab  * @keypressed: whether a key is currently pressed
946bda9644SMauro Carvalho Chehab  * @keyup_jiffies: time (in jiffies) when the current keypress should be released
956bda9644SMauro Carvalho Chehab  * @timer_keyup: timer for releasing a keypress
966bda9644SMauro Carvalho Chehab  * @last_keycode: keycode of last keypress
97120703f9SDavid Härdeman  * @last_protocol: protocol of last keypress
986bda9644SMauro Carvalho Chehab  * @last_scancode: scancode of last keypress
996bda9644SMauro Carvalho Chehab  * @last_toggle: toggle value of last command
1006bda9644SMauro Carvalho Chehab  * @timeout: optional time after which device stops sending data
1016bda9644SMauro Carvalho Chehab  * @min_timeout: minimum timeout supported by device
1026bda9644SMauro Carvalho Chehab  * @max_timeout: maximum timeout supported by device
1036bda9644SMauro Carvalho Chehab  * @rx_resolution : resolution (in ns) of input sampler
1046bda9644SMauro Carvalho Chehab  * @tx_resolution: resolution (in ns) of output sampler
1056bda9644SMauro Carvalho Chehab  * @change_protocol: allow changing the protocol used on hardware decoders
106ab88c66dSJames Hogan  * @change_wakeup_protocol: allow changing the protocol used for wakeup
107ab88c66dSJames Hogan  *	filtering
1086bda9644SMauro Carvalho Chehab  * @open: callback to allow drivers to enable polling/irq when IR input device
1096bda9644SMauro Carvalho Chehab  *	is opened.
1106bda9644SMauro Carvalho Chehab  * @close: callback to allow drivers to disable polling/irq when IR input device
1116bda9644SMauro Carvalho Chehab  *	is opened.
1126bda9644SMauro Carvalho Chehab  * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs)
1136bda9644SMauro Carvalho Chehab  * @s_tx_carrier: set transmit carrier frequency
1146bda9644SMauro Carvalho Chehab  * @s_tx_duty_cycle: set transmit duty cycle (0% - 100%)
1156bda9644SMauro Carvalho Chehab  * @s_rx_carrier: inform driver about carrier it is expected to handle
1166bda9644SMauro Carvalho Chehab  * @tx_ir: transmit IR
1176bda9644SMauro Carvalho Chehab  * @s_idle: enable/disable hardware idle mode, upon which,
1186bda9644SMauro Carvalho Chehab  *	device doesn't interrupt host until it sees IR pulses
1196bda9644SMauro Carvalho Chehab  * @s_learning_mode: enable wide band receiver used for learning
1206bda9644SMauro Carvalho Chehab  * @s_carrier_report: enable carrier reports
12123c843b5SDavid Härdeman  * @s_filter: set the scancode filter
12223c843b5SDavid Härdeman  * @s_wakeup_filter: set the wakeup scancode filter
1236bda9644SMauro Carvalho Chehab  */
1246bda9644SMauro Carvalho Chehab struct rc_dev {
1256bda9644SMauro Carvalho Chehab 	struct device			dev;
12699b0f3c9SDavid Härdeman 	const struct attribute_group	*sysfs_groups[5];
1276bda9644SMauro Carvalho Chehab 	const char			*input_name;
1286bda9644SMauro Carvalho Chehab 	const char			*input_phys;
1296bda9644SMauro Carvalho Chehab 	struct input_id			input_id;
1306bda9644SMauro Carvalho Chehab 	char				*driver_name;
1316bda9644SMauro Carvalho Chehab 	const char			*map_name;
132b088ba65SMauro Carvalho Chehab 	struct rc_map			rc_map;
13308aeb7c9SJarod Wilson 	struct mutex			lock;
134*fcb13097SDavid Härdeman 	unsigned int			minor;
1356bda9644SMauro Carvalho Chehab 	struct ir_raw_event_ctrl	*raw;
1366bda9644SMauro Carvalho Chehab 	struct input_dev		*input_dev;
1376bda9644SMauro Carvalho Chehab 	enum rc_driver_type		driver_type;
1386bda9644SMauro Carvalho Chehab 	bool				idle;
1390d830b2dSJames Hogan 	bool				encode_wakeup;
140c5540fbbSDavid Härdeman 	u64				allowed_protocols;
141c5540fbbSDavid Härdeman 	u64				enabled_protocols;
142c5540fbbSDavid Härdeman 	u64				allowed_wakeup_protocols;
143c5540fbbSDavid Härdeman 	u64				enabled_wakeup_protocols;
144c5540fbbSDavid Härdeman 	struct rc_scancode_filter	scancode_filter;
145c5540fbbSDavid Härdeman 	struct rc_scancode_filter	scancode_wakeup_filter;
1469d2f1d3cSDavid Härdeman 	u32				scancode_mask;
1478b2ff320SSrinivas Kandagatla 	u32				users;
1486bda9644SMauro Carvalho Chehab 	void				*priv;
1496bda9644SMauro Carvalho Chehab 	spinlock_t			keylock;
1506bda9644SMauro Carvalho Chehab 	bool				keypressed;
1516bda9644SMauro Carvalho Chehab 	unsigned long			keyup_jiffies;
1526bda9644SMauro Carvalho Chehab 	struct timer_list		timer_keyup;
1536bda9644SMauro Carvalho Chehab 	u32				last_keycode;
154120703f9SDavid Härdeman 	enum rc_type			last_protocol;
1556bda9644SMauro Carvalho Chehab 	u32				last_scancode;
1566bda9644SMauro Carvalho Chehab 	u8				last_toggle;
1576bda9644SMauro Carvalho Chehab 	u32				timeout;
1586bda9644SMauro Carvalho Chehab 	u32				min_timeout;
1596bda9644SMauro Carvalho Chehab 	u32				max_timeout;
1606bda9644SMauro Carvalho Chehab 	u32				rx_resolution;
1616bda9644SMauro Carvalho Chehab 	u32				tx_resolution;
162c003ab1bSDavid Härdeman 	int				(*change_protocol)(struct rc_dev *dev, u64 *rc_type);
163ab88c66dSJames Hogan 	int				(*change_wakeup_protocol)(struct rc_dev *dev, u64 *rc_type);
1646bda9644SMauro Carvalho Chehab 	int				(*open)(struct rc_dev *dev);
1656bda9644SMauro Carvalho Chehab 	void				(*close)(struct rc_dev *dev);
1666bda9644SMauro Carvalho Chehab 	int				(*s_tx_mask)(struct rc_dev *dev, u32 mask);
1676bda9644SMauro Carvalho Chehab 	int				(*s_tx_carrier)(struct rc_dev *dev, u32 carrier);
1686bda9644SMauro Carvalho Chehab 	int				(*s_tx_duty_cycle)(struct rc_dev *dev, u32 duty_cycle);
1696bda9644SMauro Carvalho Chehab 	int				(*s_rx_carrier_range)(struct rc_dev *dev, u32 min, u32 max);
1705588dc2bSDavid Härdeman 	int				(*tx_ir)(struct rc_dev *dev, unsigned *txbuf, unsigned n);
1716bda9644SMauro Carvalho Chehab 	void				(*s_idle)(struct rc_dev *dev, bool enable);
1726bda9644SMauro Carvalho Chehab 	int				(*s_learning_mode)(struct rc_dev *dev, int enable);
1736bda9644SMauro Carvalho Chehab 	int				(*s_carrier_report) (struct rc_dev *dev, int enable);
17400942d1aSJames Hogan 	int				(*s_filter)(struct rc_dev *dev,
17523c843b5SDavid Härdeman 						    struct rc_scancode_filter *filter);
17623c843b5SDavid Härdeman 	int				(*s_wakeup_filter)(struct rc_dev *dev,
17700942d1aSJames Hogan 							   struct rc_scancode_filter *filter);
1786bda9644SMauro Carvalho Chehab };
1796bda9644SMauro Carvalho Chehab 
180ca86674bSMauro Carvalho Chehab #define to_rc_dev(d) container_of(d, struct rc_dev, dev)
181ca86674bSMauro Carvalho Chehab 
182ca86674bSMauro Carvalho Chehab /*
183ca86674bSMauro Carvalho Chehab  * From rc-main.c
184ca86674bSMauro Carvalho Chehab  * Those functions can be used on any type of Remote Controller. They
185ca86674bSMauro Carvalho Chehab  * basically creates an input_dev and properly reports the device as a
186ca86674bSMauro Carvalho Chehab  * Remote Controller, at sys/class/rc.
187ca86674bSMauro Carvalho Chehab  */
188ca86674bSMauro Carvalho Chehab 
189ca86674bSMauro Carvalho Chehab struct rc_dev *rc_allocate_device(void);
190ca86674bSMauro Carvalho Chehab void rc_free_device(struct rc_dev *dev);
191ca86674bSMauro Carvalho Chehab int rc_register_device(struct rc_dev *dev);
192ca86674bSMauro Carvalho Chehab void rc_unregister_device(struct rc_dev *dev);
193ca86674bSMauro Carvalho Chehab 
1948b2ff320SSrinivas Kandagatla int rc_open(struct rc_dev *rdev);
1958b2ff320SSrinivas Kandagatla void rc_close(struct rc_dev *rdev);
1968b2ff320SSrinivas Kandagatla 
197ca86674bSMauro Carvalho Chehab void rc_repeat(struct rc_dev *dev);
198120703f9SDavid Härdeman void rc_keydown(struct rc_dev *dev, enum rc_type protocol, u32 scancode, u8 toggle);
199120703f9SDavid Härdeman void rc_keydown_notimeout(struct rc_dev *dev, enum rc_type protocol, u32 scancode, u8 toggle);
200ca86674bSMauro Carvalho Chehab void rc_keyup(struct rc_dev *dev);
201ca86674bSMauro Carvalho Chehab u32 rc_g_keycode_from_table(struct rc_dev *dev, u32 scancode);
202ca86674bSMauro Carvalho Chehab 
203ca86674bSMauro Carvalho Chehab /*
204ca86674bSMauro Carvalho Chehab  * From rc-raw.c
205ca86674bSMauro Carvalho Chehab  * The Raw interface is specific to InfraRed. It may be a good idea to
206ca86674bSMauro Carvalho Chehab  * split it later into a separate header.
207ca86674bSMauro Carvalho Chehab  */
208ca86674bSMauro Carvalho Chehab 
2096bda9644SMauro Carvalho Chehab enum raw_event_type {
2106bda9644SMauro Carvalho Chehab 	IR_SPACE        = (1 << 0),
2116bda9644SMauro Carvalho Chehab 	IR_PULSE        = (1 << 1),
2126bda9644SMauro Carvalho Chehab 	IR_START_EVENT  = (1 << 2),
2136bda9644SMauro Carvalho Chehab 	IR_STOP_EVENT   = (1 << 3),
2146bda9644SMauro Carvalho Chehab };
2156bda9644SMauro Carvalho Chehab 
2166bda9644SMauro Carvalho Chehab struct ir_raw_event {
2176bda9644SMauro Carvalho Chehab 	union {
2186bda9644SMauro Carvalho Chehab 		u32             duration;
2196bda9644SMauro Carvalho Chehab 
2206bda9644SMauro Carvalho Chehab 		struct {
2216bda9644SMauro Carvalho Chehab 			u32     carrier;
2226bda9644SMauro Carvalho Chehab 			u8      duty_cycle;
2236bda9644SMauro Carvalho Chehab 		};
2246bda9644SMauro Carvalho Chehab 	};
2256bda9644SMauro Carvalho Chehab 
2266bda9644SMauro Carvalho Chehab 	unsigned                pulse:1;
2276bda9644SMauro Carvalho Chehab 	unsigned                reset:1;
2286bda9644SMauro Carvalho Chehab 	unsigned                timeout:1;
2296bda9644SMauro Carvalho Chehab 	unsigned                carrier_report:1;
2306bda9644SMauro Carvalho Chehab };
2316bda9644SMauro Carvalho Chehab 
2326bda9644SMauro Carvalho Chehab #define DEFINE_IR_RAW_EVENT(event) \
2336bda9644SMauro Carvalho Chehab 	struct ir_raw_event event = { \
2346bda9644SMauro Carvalho Chehab 		{ .duration = 0 } , \
2356bda9644SMauro Carvalho Chehab 		.pulse = 0, \
2366bda9644SMauro Carvalho Chehab 		.reset = 0, \
2376bda9644SMauro Carvalho Chehab 		.timeout = 0, \
2386bda9644SMauro Carvalho Chehab 		.carrier_report = 0 }
2396bda9644SMauro Carvalho Chehab 
2406bda9644SMauro Carvalho Chehab static inline void init_ir_raw_event(struct ir_raw_event *ev)
2416bda9644SMauro Carvalho Chehab {
2426bda9644SMauro Carvalho Chehab 	memset(ev, 0, sizeof(*ev));
2436bda9644SMauro Carvalho Chehab }
2446bda9644SMauro Carvalho Chehab 
2456b20cf3cSMauro Carvalho Chehab #define IR_MAX_DURATION         500000000	/* 500 ms */
2465aad7242SJarod Wilson #define US_TO_NS(usec)		((usec) * 1000)
2475aad7242SJarod Wilson #define MS_TO_US(msec)		((msec) * 1000)
2485aad7242SJarod Wilson #define MS_TO_NS(msec)		((msec) * 1000 * 1000)
249da7ee60bSAntti Seppälä #define NS_TO_US(nsec)		DIV_ROUND_UP(nsec, 1000L)
2506bda9644SMauro Carvalho Chehab 
2516bda9644SMauro Carvalho Chehab void ir_raw_event_handle(struct rc_dev *dev);
2526bda9644SMauro Carvalho Chehab int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev);
2536bda9644SMauro Carvalho Chehab int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type);
2546bda9644SMauro Carvalho Chehab int ir_raw_event_store_with_filter(struct rc_dev *dev,
2556bda9644SMauro Carvalho Chehab 				struct ir_raw_event *ev);
2566bda9644SMauro Carvalho Chehab void ir_raw_event_set_idle(struct rc_dev *dev, bool idle);
2579869da5bSJames Hogan int ir_raw_encode_scancode(u64 protocols,
2589869da5bSJames Hogan 			   const struct rc_scancode_filter *scancode,
2599869da5bSJames Hogan 			   struct ir_raw_event *events, unsigned int max);
2606bda9644SMauro Carvalho Chehab 
2616bda9644SMauro Carvalho Chehab static inline void ir_raw_event_reset(struct rc_dev *dev)
2626bda9644SMauro Carvalho Chehab {
2636bda9644SMauro Carvalho Chehab 	DEFINE_IR_RAW_EVENT(ev);
2646bda9644SMauro Carvalho Chehab 	ev.reset = true;
2656bda9644SMauro Carvalho Chehab 
2666bda9644SMauro Carvalho Chehab 	ir_raw_event_store(dev, &ev);
2676bda9644SMauro Carvalho Chehab 	ir_raw_event_handle(dev);
2686bda9644SMauro Carvalho Chehab }
2696bda9644SMauro Carvalho Chehab 
2706bda9644SMauro Carvalho Chehab /* extract mask bits out of data and pack them into the result */
2716bda9644SMauro Carvalho Chehab static inline u32 ir_extract_bits(u32 data, u32 mask)
2726bda9644SMauro Carvalho Chehab {
2736bda9644SMauro Carvalho Chehab 	u32 vbit = 1, value = 0;
2746bda9644SMauro Carvalho Chehab 
2756bda9644SMauro Carvalho Chehab 	do {
2766bda9644SMauro Carvalho Chehab 		if (mask & 1) {
2776bda9644SMauro Carvalho Chehab 			if (data & 1)
2786bda9644SMauro Carvalho Chehab 				value |= vbit;
2796bda9644SMauro Carvalho Chehab 			vbit <<= 1;
2806bda9644SMauro Carvalho Chehab 		}
2816bda9644SMauro Carvalho Chehab 		data >>= 1;
2826bda9644SMauro Carvalho Chehab 	} while (mask >>= 1);
2836bda9644SMauro Carvalho Chehab 
2846bda9644SMauro Carvalho Chehab 	return value;
2856bda9644SMauro Carvalho Chehab }
2866bda9644SMauro Carvalho Chehab 
287ca86674bSMauro Carvalho Chehab #endif /* _RC_CORE */
288