Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 1 | /* |
| 2 | * Remote Controller core raw events header |
| 3 | * |
Mauro Carvalho Chehab | 37e59f8 | 2014-02-07 08:03:07 -0200 | [diff] [blame] | 4 | * Copyright (C) 2010 by Mauro Carvalho Chehab |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation version 2 of the License. |
| 9 | * |
| 10 | * This program is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | * GNU General Public License for more details. |
| 14 | */ |
| 15 | |
David Härdeman | 829ba9f | 2010-11-19 20:43:27 -0300 | [diff] [blame] | 16 | #ifndef _RC_CORE_PRIV |
| 17 | #define _RC_CORE_PRIV |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 18 | |
Heiner Kallweit | 464254e | 2015-11-27 20:02:38 -0200 | [diff] [blame] | 19 | /* Define the max number of pulse/space transitions to buffer */ |
| 20 | #define MAX_IR_EVENT_SIZE 512 |
| 21 | |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 22 | #include <linux/slab.h> |
Mauro Carvalho Chehab | 6bda964 | 2010-11-17 13:28:38 -0300 | [diff] [blame] | 23 | #include <media/rc-core.h> |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 24 | |
| 25 | struct ir_raw_handler { |
| 26 | struct list_head list; |
| 27 | |
David Härdeman | 667c9eb | 2010-06-13 17:29:31 -0300 | [diff] [blame] | 28 | u64 protocols; /* which are handled by this handler */ |
David Härdeman | d8b4b58 | 2010-10-29 16:08:23 -0300 | [diff] [blame] | 29 | int (*decode)(struct rc_dev *dev, struct ir_raw_event event); |
James Hogan | 3875233d | 2015-03-31 14:48:06 -0300 | [diff] [blame] | 30 | int (*encode)(enum rc_type protocol, u32 scancode, |
| 31 | struct ir_raw_event *events, unsigned int max); |
David Härdeman | c216369 | 2010-06-13 17:29:36 -0300 | [diff] [blame] | 32 | |
| 33 | /* These two should only be used by the lirc decoder */ |
David Härdeman | d8b4b58 | 2010-10-29 16:08:23 -0300 | [diff] [blame] | 34 | int (*raw_register)(struct rc_dev *dev); |
| 35 | int (*raw_unregister)(struct rc_dev *dev); |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 36 | }; |
| 37 | |
| 38 | struct ir_raw_event_ctrl { |
David Härdeman | c216369 | 2010-06-13 17:29:36 -0300 | [diff] [blame] | 39 | struct list_head list; /* to keep track of raw clients */ |
Maxim Levitsky | 0d2cb1d | 2010-07-31 11:59:17 -0300 | [diff] [blame] | 40 | struct task_struct *thread; |
Heiner Kallweit | 464254e | 2015-11-27 20:02:38 -0200 | [diff] [blame] | 41 | /* fifo for the pulse/space durations */ |
| 42 | DECLARE_KFIFO(kfifo, struct ir_raw_event, MAX_IR_EVENT_SIZE); |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 43 | ktime_t last_event; /* when last event occurred */ |
| 44 | enum raw_event_type last_type; /* last event type */ |
David Härdeman | d8b4b58 | 2010-10-29 16:08:23 -0300 | [diff] [blame] | 45 | struct rc_dev *dev; /* pointer to the parent rc_dev */ |
David Härdeman | c216369 | 2010-06-13 17:29:36 -0300 | [diff] [blame] | 46 | |
| 47 | /* raw decoder state follows */ |
| 48 | struct ir_raw_event prev_ev; |
Maxim Levitsky | 4a702eb | 2010-07-31 11:59:22 -0300 | [diff] [blame] | 49 | struct ir_raw_event this_ev; |
David Härdeman | c216369 | 2010-06-13 17:29:36 -0300 | [diff] [blame] | 50 | struct nec_dec { |
| 51 | int state; |
| 52 | unsigned count; |
| 53 | u32 bits; |
Maxim Levitsky | 86ff071 | 2010-07-31 11:59:20 -0300 | [diff] [blame] | 54 | bool is_nec_x; |
| 55 | bool necx_repeat; |
David Härdeman | c216369 | 2010-06-13 17:29:36 -0300 | [diff] [blame] | 56 | } nec; |
| 57 | struct rc5_dec { |
| 58 | int state; |
| 59 | u32 bits; |
| 60 | unsigned count; |
David Härdeman | e87b540 | 2014-04-03 20:32:31 -0300 | [diff] [blame] | 61 | bool is_rc5x; |
David Härdeman | c216369 | 2010-06-13 17:29:36 -0300 | [diff] [blame] | 62 | } rc5; |
| 63 | struct rc6_dec { |
| 64 | int state; |
| 65 | u8 header; |
| 66 | u32 body; |
| 67 | bool toggle; |
| 68 | unsigned count; |
| 69 | unsigned wanted_bits; |
| 70 | } rc6; |
| 71 | struct sony_dec { |
| 72 | int state; |
| 73 | u32 bits; |
| 74 | unsigned count; |
| 75 | } sony; |
| 76 | struct jvc_dec { |
| 77 | int state; |
| 78 | u16 bits; |
| 79 | u16 old_bits; |
| 80 | unsigned count; |
| 81 | bool first; |
| 82 | bool toggle; |
| 83 | } jvc; |
Mauro Carvalho Chehab | b32e724 | 2011-11-23 12:04:08 -0300 | [diff] [blame] | 84 | struct sanyo_dec { |
| 85 | int state; |
| 86 | unsigned count; |
| 87 | u64 bits; |
| 88 | } sanyo; |
James Hogan | 1d184b0 | 2014-01-17 10:58:48 -0300 | [diff] [blame] | 89 | struct sharp_dec { |
| 90 | int state; |
| 91 | unsigned count; |
| 92 | u32 bits; |
| 93 | unsigned int pulse_len; |
| 94 | } sharp; |
Jarod Wilson | f5f2cc6 | 2011-07-13 18:09:48 -0300 | [diff] [blame] | 95 | struct mce_kbd_dec { |
| 96 | struct input_dev *idev; |
| 97 | struct timer_list rx_timeout; |
| 98 | char name[64]; |
| 99 | char phys[64]; |
| 100 | int state; |
| 101 | u8 header; |
| 102 | u32 body; |
| 103 | unsigned count; |
| 104 | unsigned wanted_bits; |
| 105 | } mce_kbd; |
Jarod Wilson | ca41469 | 2010-07-03 01:07:53 -0300 | [diff] [blame] | 106 | struct lirc_codec { |
David Härdeman | d8b4b58 | 2010-10-29 16:08:23 -0300 | [diff] [blame] | 107 | struct rc_dev *dev; |
Jarod Wilson | ca41469 | 2010-07-03 01:07:53 -0300 | [diff] [blame] | 108 | struct lirc_driver *drv; |
Maxim Levitsky | e589333 | 2010-07-31 11:59:23 -0300 | [diff] [blame] | 109 | int carrier_low; |
Maxim Levitsky | 4651918 | 2010-10-16 19:56:28 -0300 | [diff] [blame] | 110 | |
| 111 | ktime_t gap_start; |
| 112 | u64 gap_duration; |
| 113 | bool gap; |
| 114 | bool send_timeout_reports; |
| 115 | |
Jarod Wilson | ca41469 | 2010-07-03 01:07:53 -0300 | [diff] [blame] | 116 | } lirc; |
Marcel J.E. Mol | 1dee9b5 | 2014-07-26 17:28:26 -0300 | [diff] [blame] | 117 | struct xmp_dec { |
| 118 | int state; |
| 119 | unsigned count; |
| 120 | u32 durations[16]; |
| 121 | } xmp; |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 122 | }; |
| 123 | |
| 124 | /* macros for IR decoders */ |
Mauro Carvalho Chehab | 384f23e | 2010-04-20 18:50:54 -0300 | [diff] [blame] | 125 | static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) |
| 126 | { |
David Härdeman | e40b112 | 2010-04-15 18:46:00 -0300 | [diff] [blame] | 127 | return d1 > (d2 - margin); |
| 128 | } |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 129 | |
Mauro Carvalho Chehab | 384f23e | 2010-04-20 18:50:54 -0300 | [diff] [blame] | 130 | static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin) |
| 131 | { |
David Härdeman | e40b112 | 2010-04-15 18:46:00 -0300 | [diff] [blame] | 132 | return ((d1 > (d2 - margin)) && (d1 < (d2 + margin))); |
| 133 | } |
| 134 | |
Mauro Carvalho Chehab | 384f23e | 2010-04-20 18:50:54 -0300 | [diff] [blame] | 135 | static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y) |
| 136 | { |
David Härdeman | e40b112 | 2010-04-15 18:46:00 -0300 | [diff] [blame] | 137 | return x->pulse != y->pulse; |
| 138 | } |
| 139 | |
Mauro Carvalho Chehab | 384f23e | 2010-04-20 18:50:54 -0300 | [diff] [blame] | 140 | static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) |
| 141 | { |
David Härdeman | e40b112 | 2010-04-15 18:46:00 -0300 | [diff] [blame] | 142 | if (duration > ev->duration) |
| 143 | ev->duration = 0; |
| 144 | else |
| 145 | ev->duration -= duration; |
| 146 | } |
| 147 | |
Maxim Levitsky | 4651918 | 2010-10-16 19:56:28 -0300 | [diff] [blame] | 148 | /* Returns true if event is normal pulse/space event */ |
| 149 | static inline bool is_timing_event(struct ir_raw_event ev) |
| 150 | { |
| 151 | return !ev.carrier_report && !ev.reset; |
| 152 | } |
| 153 | |
Maxim Levitsky | 510fcb7 | 2010-07-31 11:59:15 -0300 | [diff] [blame] | 154 | #define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000) |
David Härdeman | e40b112 | 2010-04-15 18:46:00 -0300 | [diff] [blame] | 155 | #define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 156 | |
Antti Seppälä | 844a4f4 | 2015-03-31 14:48:07 -0300 | [diff] [blame] | 157 | /* functions for IR encoders */ |
| 158 | |
| 159 | static inline void init_ir_raw_event_duration(struct ir_raw_event *ev, |
| 160 | unsigned int pulse, |
| 161 | u32 duration) |
| 162 | { |
| 163 | init_ir_raw_event(ev); |
| 164 | ev->duration = duration; |
| 165 | ev->pulse = pulse; |
| 166 | } |
| 167 | |
| 168 | /** |
| 169 | * struct ir_raw_timings_manchester - Manchester coding timings |
| 170 | * @leader: duration of leader pulse (if any) 0 if continuing |
| 171 | * existing signal (see @pulse_space_start) |
| 172 | * @pulse_space_start: 1 for starting with pulse (0 for starting with space) |
| 173 | * @clock: duration of each pulse/space in ns |
| 174 | * @invert: if set clock logic is inverted |
| 175 | * (0 = space + pulse, 1 = pulse + space) |
| 176 | * @trailer_space: duration of trailer space in ns |
| 177 | */ |
| 178 | struct ir_raw_timings_manchester { |
| 179 | unsigned int leader; |
| 180 | unsigned int pulse_space_start:1; |
| 181 | unsigned int clock; |
| 182 | unsigned int invert:1; |
| 183 | unsigned int trailer_space; |
| 184 | }; |
| 185 | |
| 186 | int ir_raw_gen_manchester(struct ir_raw_event **ev, unsigned int max, |
| 187 | const struct ir_raw_timings_manchester *timings, |
Sean Young | b73bc16 | 2017-02-11 20:33:38 -0200 | [diff] [blame] | 188 | unsigned int n, u64 data); |
Antti Seppälä | 844a4f4 | 2015-03-31 14:48:07 -0300 | [diff] [blame] | 189 | |
James Hogan | caec098 | 2014-03-14 20:04:12 -0300 | [diff] [blame] | 190 | /** |
| 191 | * ir_raw_gen_pulse_space() - generate pulse and space raw events. |
| 192 | * @ev: Pointer to pointer to next free raw event. |
| 193 | * Will be incremented for each raw event written. |
| 194 | * @max: Pointer to number of raw events available in buffer. |
| 195 | * Will be decremented for each raw event written. |
| 196 | * @pulse_width: Width of pulse in ns. |
| 197 | * @space_width: Width of space in ns. |
| 198 | * |
| 199 | * Returns: 0 on success. |
| 200 | * -ENOBUFS if there isn't enough buffer space to write both raw |
| 201 | * events. In this case @max events will have been written. |
| 202 | */ |
| 203 | static inline int ir_raw_gen_pulse_space(struct ir_raw_event **ev, |
| 204 | unsigned int *max, |
| 205 | unsigned int pulse_width, |
| 206 | unsigned int space_width) |
| 207 | { |
| 208 | if (!*max) |
| 209 | return -ENOBUFS; |
| 210 | init_ir_raw_event_duration((*ev)++, 1, pulse_width); |
| 211 | if (!--*max) |
| 212 | return -ENOBUFS; |
| 213 | init_ir_raw_event_duration((*ev)++, 0, space_width); |
| 214 | --*max; |
| 215 | return 0; |
| 216 | } |
| 217 | |
| 218 | /** |
| 219 | * struct ir_raw_timings_pd - pulse-distance modulation timings |
| 220 | * @header_pulse: duration of header pulse in ns (0 for none) |
| 221 | * @header_space: duration of header space in ns |
| 222 | * @bit_pulse: duration of bit pulse in ns |
| 223 | * @bit_space: duration of bit space (for logic 0 and 1) in ns |
| 224 | * @trailer_pulse: duration of trailer pulse in ns |
| 225 | * @trailer_space: duration of trailer space in ns |
| 226 | * @msb_first: 1 if most significant bit is sent first |
| 227 | */ |
| 228 | struct ir_raw_timings_pd { |
| 229 | unsigned int header_pulse; |
| 230 | unsigned int header_space; |
| 231 | unsigned int bit_pulse; |
| 232 | unsigned int bit_space[2]; |
| 233 | unsigned int trailer_pulse; |
| 234 | unsigned int trailer_space; |
| 235 | unsigned int msb_first:1; |
| 236 | }; |
| 237 | |
| 238 | int ir_raw_gen_pd(struct ir_raw_event **ev, unsigned int max, |
| 239 | const struct ir_raw_timings_pd *timings, |
| 240 | unsigned int n, u64 data); |
| 241 | |
Sean Young | 103293b | 2016-12-06 18:33:57 -0200 | [diff] [blame] | 242 | /** |
| 243 | * struct ir_raw_timings_pl - pulse-length modulation timings |
| 244 | * @header_pulse: duration of header pulse in ns (0 for none) |
| 245 | * @bit_space: duration of bit space in ns |
| 246 | * @bit_pulse: duration of bit pulse (for logic 0 and 1) in ns |
| 247 | * @trailer_space: duration of trailer space in ns |
| 248 | * @msb_first: 1 if most significant bit is sent first |
| 249 | */ |
| 250 | struct ir_raw_timings_pl { |
| 251 | unsigned int header_pulse; |
| 252 | unsigned int bit_space; |
| 253 | unsigned int bit_pulse[2]; |
| 254 | unsigned int trailer_space; |
| 255 | unsigned int msb_first:1; |
| 256 | }; |
| 257 | |
| 258 | int ir_raw_gen_pl(struct ir_raw_event **ev, unsigned int max, |
| 259 | const struct ir_raw_timings_pl *timings, |
| 260 | unsigned int n, u64 data); |
| 261 | |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 262 | /* |
David Härdeman | d8b4b58 | 2010-10-29 16:08:23 -0300 | [diff] [blame] | 263 | * Routines from rc-raw.c to be used internally and by decoders |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 264 | */ |
David Härdeman | 667c9eb | 2010-06-13 17:29:31 -0300 | [diff] [blame] | 265 | u64 ir_raw_get_allowed_protocols(void); |
David Härdeman | f56928a | 2017-05-03 07:04:00 -0300 | [diff] [blame] | 266 | int ir_raw_event_prepare(struct rc_dev *dev); |
David Härdeman | d8b4b58 | 2010-10-29 16:08:23 -0300 | [diff] [blame] | 267 | int ir_raw_event_register(struct rc_dev *dev); |
David Härdeman | f56928a | 2017-05-03 07:04:00 -0300 | [diff] [blame] | 268 | void ir_raw_event_free(struct rc_dev *dev); |
David Härdeman | d8b4b58 | 2010-10-29 16:08:23 -0300 | [diff] [blame] | 269 | void ir_raw_event_unregister(struct rc_dev *dev); |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 270 | int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); |
| 271 | void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); |
| 272 | void ir_raw_init(void); |
| 273 | |
Mauro Carvalho Chehab | 3f113e3 | 2010-04-08 15:10:27 -0300 | [diff] [blame] | 274 | /* |
| 275 | * Decoder initialization code |
| 276 | * |
| 277 | * Those load logic are called during ir-core init, and automatically |
| 278 | * loads the compiled decoders for their usage with IR raw events |
| 279 | */ |
| 280 | |
David Härdeman | 829ba9f | 2010-11-19 20:43:27 -0300 | [diff] [blame] | 281 | #endif /* _RC_CORE_PRIV */ |