Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.35-rc3 419 lines 9.7 kB view raw
1/* ir-rc6-decoder.c - A decoder for the RC6 IR 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 "ir-core-priv.h" 16 17/* 18 * This decoder currently supports: 19 * RC6-0-16 (standard toggle bit in header) 20 * RC6-6A-24 (no toggle bit) 21 * RC6-6A-32 (MCE version with toggle bit in body) 22 */ 23 24#define RC6_UNIT 444444 /* us */ 25#define RC6_HEADER_NBITS 4 /* not including toggle bit */ 26#define RC6_0_NBITS 16 27#define RC6_6A_SMALL_NBITS 24 28#define RC6_6A_LARGE_NBITS 32 29#define RC6_PREFIX_PULSE (6 * RC6_UNIT) 30#define RC6_PREFIX_SPACE (2 * RC6_UNIT) 31#define RC6_BIT_START (1 * RC6_UNIT) 32#define RC6_BIT_END (1 * RC6_UNIT) 33#define RC6_TOGGLE_START (2 * RC6_UNIT) 34#define RC6_TOGGLE_END (2 * RC6_UNIT) 35#define RC6_MODE_MASK 0x07 /* for the header bits */ 36#define RC6_STARTBIT_MASK 0x08 /* for the header bits */ 37#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ 38 39/* Used to register rc6_decoder clients */ 40static LIST_HEAD(decoder_list); 41static DEFINE_SPINLOCK(decoder_lock); 42 43enum rc6_mode { 44 RC6_MODE_0, 45 RC6_MODE_6A, 46 RC6_MODE_UNKNOWN, 47}; 48 49enum rc6_state { 50 STATE_INACTIVE, 51 STATE_PREFIX_SPACE, 52 STATE_HEADER_BIT_START, 53 STATE_HEADER_BIT_END, 54 STATE_TOGGLE_START, 55 STATE_TOGGLE_END, 56 STATE_BODY_BIT_START, 57 STATE_BODY_BIT_END, 58 STATE_FINISHED, 59}; 60 61struct decoder_data { 62 struct list_head list; 63 struct ir_input_dev *ir_dev; 64 int enabled:1; 65 66 /* State machine control */ 67 enum rc6_state state; 68 u8 header; 69 u32 body; 70 struct ir_raw_event prev_ev; 71 bool toggle; 72 unsigned count; 73 unsigned wanted_bits; 74}; 75 76 77/** 78 * get_decoder_data() - gets decoder data 79 * @input_dev: input device 80 * 81 * Returns the struct decoder_data that corresponds to a device 82 */ 83static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) 84{ 85 struct decoder_data *data = NULL; 86 87 spin_lock(&decoder_lock); 88 list_for_each_entry(data, &decoder_list, list) { 89 if (data->ir_dev == ir_dev) 90 break; 91 } 92 spin_unlock(&decoder_lock); 93 return data; 94} 95 96static ssize_t store_enabled(struct device *d, 97 struct device_attribute *mattr, 98 const char *buf, 99 size_t len) 100{ 101 unsigned long value; 102 struct ir_input_dev *ir_dev = dev_get_drvdata(d); 103 struct decoder_data *data = get_decoder_data(ir_dev); 104 105 if (!data) 106 return -EINVAL; 107 108 if (strict_strtoul(buf, 10, &value) || value > 1) 109 return -EINVAL; 110 111 data->enabled = value; 112 113 return len; 114} 115 116static ssize_t show_enabled(struct device *d, 117 struct device_attribute *mattr, char *buf) 118{ 119 struct ir_input_dev *ir_dev = dev_get_drvdata(d); 120 struct decoder_data *data = get_decoder_data(ir_dev); 121 122 if (!data) 123 return -EINVAL; 124 125 if (data->enabled) 126 return sprintf(buf, "1\n"); 127 else 128 return sprintf(buf, "0\n"); 129} 130 131static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); 132 133static struct attribute *decoder_attributes[] = { 134 &dev_attr_enabled.attr, 135 NULL 136}; 137 138static struct attribute_group decoder_attribute_group = { 139 .name = "rc6_decoder", 140 .attrs = decoder_attributes, 141}; 142 143static enum rc6_mode rc6_mode(struct decoder_data *data) { 144 switch (data->header & RC6_MODE_MASK) { 145 case 0: 146 return RC6_MODE_0; 147 case 6: 148 if (!data->toggle) 149 return RC6_MODE_6A; 150 /* fall through */ 151 default: 152 return RC6_MODE_UNKNOWN; 153 } 154} 155 156/** 157 * ir_rc6_decode() - Decode one RC6 pulse or space 158 * @input_dev: the struct input_dev descriptor of the device 159 * @ev: the struct ir_raw_event descriptor of the pulse/space 160 * 161 * This function returns -EINVAL if the pulse violates the state machine 162 */ 163static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev) 164{ 165 struct decoder_data *data; 166 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 167 u32 scancode; 168 u8 toggle; 169 170 data = get_decoder_data(ir_dev); 171 if (!data) 172 return -EINVAL; 173 174 if (!data->enabled) 175 return 0; 176 177 if (IS_RESET(ev)) { 178 data->state = STATE_INACTIVE; 179 return 0; 180 } 181 182 if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) 183 goto out; 184 185again: 186 IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n", 187 data->state, TO_US(ev.duration), TO_STR(ev.pulse)); 188 189 if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) 190 return 0; 191 192 switch (data->state) { 193 194 case STATE_INACTIVE: 195 if (!ev.pulse) 196 break; 197 198 /* Note: larger margin on first pulse since each RC6_UNIT 199 is quite short and some hardware takes some time to 200 adjust to the signal */ 201 if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT)) 202 break; 203 204 data->state = STATE_PREFIX_SPACE; 205 data->count = 0; 206 return 0; 207 208 case STATE_PREFIX_SPACE: 209 if (ev.pulse) 210 break; 211 212 if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2)) 213 break; 214 215 data->state = STATE_HEADER_BIT_START; 216 return 0; 217 218 case STATE_HEADER_BIT_START: 219 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) 220 break; 221 222 data->header <<= 1; 223 if (ev.pulse) 224 data->header |= 1; 225 data->count++; 226 data->prev_ev = ev; 227 data->state = STATE_HEADER_BIT_END; 228 return 0; 229 230 case STATE_HEADER_BIT_END: 231 if (!is_transition(&ev, &data->prev_ev)) 232 break; 233 234 if (data->count == RC6_HEADER_NBITS) 235 data->state = STATE_TOGGLE_START; 236 else 237 data->state = STATE_HEADER_BIT_START; 238 239 decrease_duration(&ev, RC6_BIT_END); 240 goto again; 241 242 case STATE_TOGGLE_START: 243 if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2)) 244 break; 245 246 data->toggle = ev.pulse; 247 data->prev_ev = ev; 248 data->state = STATE_TOGGLE_END; 249 return 0; 250 251 case STATE_TOGGLE_END: 252 if (!is_transition(&ev, &data->prev_ev) || 253 !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2)) 254 break; 255 256 if (!(data->header & RC6_STARTBIT_MASK)) { 257 IR_dprintk(1, "RC6 invalid start bit\n"); 258 break; 259 } 260 261 data->state = STATE_BODY_BIT_START; 262 data->prev_ev = ev; 263 decrease_duration(&ev, RC6_TOGGLE_END); 264 data->count = 0; 265 266 switch (rc6_mode(data)) { 267 case RC6_MODE_0: 268 data->wanted_bits = RC6_0_NBITS; 269 break; 270 case RC6_MODE_6A: 271 /* This might look weird, but we basically 272 check the value of the first body bit to 273 determine the number of bits in mode 6A */ 274 if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) || 275 geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) 276 data->wanted_bits = RC6_6A_LARGE_NBITS; 277 else 278 data->wanted_bits = RC6_6A_SMALL_NBITS; 279 break; 280 default: 281 IR_dprintk(1, "RC6 unknown mode\n"); 282 goto out; 283 } 284 goto again; 285 286 case STATE_BODY_BIT_START: 287 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) 288 break; 289 290 data->body <<= 1; 291 if (ev.pulse) 292 data->body |= 1; 293 data->count++; 294 data->prev_ev = ev; 295 296 data->state = STATE_BODY_BIT_END; 297 return 0; 298 299 case STATE_BODY_BIT_END: 300 if (!is_transition(&ev, &data->prev_ev)) 301 break; 302 303 if (data->count == data->wanted_bits) 304 data->state = STATE_FINISHED; 305 else 306 data->state = STATE_BODY_BIT_START; 307 308 decrease_duration(&ev, RC6_BIT_END); 309 goto again; 310 311 case STATE_FINISHED: 312 if (ev.pulse) 313 break; 314 315 switch (rc6_mode(data)) { 316 case RC6_MODE_0: 317 scancode = data->body & 0xffff; 318 toggle = data->toggle; 319 IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n", 320 scancode, toggle); 321 break; 322 case RC6_MODE_6A: 323 if (data->wanted_bits == RC6_6A_LARGE_NBITS) { 324 toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0; 325 scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK; 326 } else { 327 toggle = 0; 328 scancode = data->body & 0xffffff; 329 } 330 331 IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n", 332 scancode, toggle); 333 break; 334 default: 335 IR_dprintk(1, "RC6 unknown mode\n"); 336 goto out; 337 } 338 339 ir_keydown(input_dev, scancode, toggle); 340 data->state = STATE_INACTIVE; 341 return 0; 342 } 343 344out: 345 IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n", 346 data->state, TO_US(ev.duration), TO_STR(ev.pulse)); 347 data->state = STATE_INACTIVE; 348 return -EINVAL; 349} 350 351static int ir_rc6_register(struct input_dev *input_dev) 352{ 353 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 354 struct decoder_data *data; 355 int rc; 356 357 rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); 358 if (rc < 0) 359 return rc; 360 361 data = kzalloc(sizeof(*data), GFP_KERNEL); 362 if (!data) { 363 sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); 364 return -ENOMEM; 365 } 366 367 data->ir_dev = ir_dev; 368 data->enabled = 1; 369 370 spin_lock(&decoder_lock); 371 list_add_tail(&data->list, &decoder_list); 372 spin_unlock(&decoder_lock); 373 374 return 0; 375} 376 377static int ir_rc6_unregister(struct input_dev *input_dev) 378{ 379 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 380 static struct decoder_data *data; 381 382 data = get_decoder_data(ir_dev); 383 if (!data) 384 return 0; 385 386 sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); 387 388 spin_lock(&decoder_lock); 389 list_del(&data->list); 390 spin_unlock(&decoder_lock); 391 392 return 0; 393} 394 395static struct ir_raw_handler rc6_handler = { 396 .decode = ir_rc6_decode, 397 .raw_register = ir_rc6_register, 398 .raw_unregister = ir_rc6_unregister, 399}; 400 401static int __init ir_rc6_decode_init(void) 402{ 403 ir_raw_handler_register(&rc6_handler); 404 405 printk(KERN_INFO "IR RC6 protocol handler initialized\n"); 406 return 0; 407} 408 409static void __exit ir_rc6_decode_exit(void) 410{ 411 ir_raw_handler_unregister(&rc6_handler); 412} 413 414module_init(ir_rc6_decode_init); 415module_exit(ir_rc6_decode_exit); 416 417MODULE_LICENSE("GPL"); 418MODULE_AUTHOR("David Härdeman <david@hardeman.nu>"); 419MODULE_DESCRIPTION("RC6 IR protocol decoder");