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