1/* ir-sharp-decoder.c - handle Sharp IR Pulse/Space protocol 2 * 3 * Copyright (C) 2013-2014 Imagination Technologies Ltd. 4 * 5 * Based on NEC decoder: 6 * Copyright (C) 2010 by Mauro Carvalho Chehab 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation version 2 of the License. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 */ 17 18#include <linux/bitrev.h> 19#include <linux/module.h> 20#include "rc-core-priv.h" 21 22#define SHARP_NBITS 15 23#define SHARP_UNIT 40000 /* ns */ 24#define SHARP_BIT_PULSE (8 * SHARP_UNIT) /* 320us */ 25#define SHARP_BIT_0_PERIOD (25 * SHARP_UNIT) /* 1ms (680us space) */ 26#define SHARP_BIT_1_PERIOD (50 * SHARP_UNIT) /* 2ms (1680ms space) */ 27#define SHARP_ECHO_SPACE (1000 * SHARP_UNIT) /* 40 ms */ 28#define SHARP_TRAILER_SPACE (125 * SHARP_UNIT) /* 5 ms (even longer) */ 29 30enum sharp_state { 31 STATE_INACTIVE, 32 STATE_BIT_PULSE, 33 STATE_BIT_SPACE, 34 STATE_TRAILER_PULSE, 35 STATE_ECHO_SPACE, 36 STATE_TRAILER_SPACE, 37}; 38 39/** 40 * ir_sharp_decode() - Decode one Sharp pulse or space 41 * @dev: the struct rc_dev descriptor of the device 42 * @duration: the struct ir_raw_event descriptor of the pulse/space 43 * 44 * This function returns -EINVAL if the pulse violates the state machine 45 */ 46static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev) 47{ 48 struct sharp_dec *data = &dev->raw->sharp; 49 u32 msg, echo, address, command, scancode; 50 51 if (!(dev->enabled_protocols & RC_BIT_SHARP)) 52 return 0; 53 54 if (!is_timing_event(ev)) { 55 if (ev.reset) 56 data->state = STATE_INACTIVE; 57 return 0; 58 } 59 60 IR_dprintk(2, "Sharp decode started at state %d (%uus %s)\n", 61 data->state, TO_US(ev.duration), TO_STR(ev.pulse)); 62 63 switch (data->state) { 64 65 case STATE_INACTIVE: 66 if (!ev.pulse) 67 break; 68 69 if (!eq_margin(ev.duration, SHARP_BIT_PULSE, 70 SHARP_BIT_PULSE / 2)) 71 break; 72 73 data->count = 0; 74 data->pulse_len = ev.duration; 75 data->state = STATE_BIT_SPACE; 76 return 0; 77 78 case STATE_BIT_PULSE: 79 if (!ev.pulse) 80 break; 81 82 if (!eq_margin(ev.duration, SHARP_BIT_PULSE, 83 SHARP_BIT_PULSE / 2)) 84 break; 85 86 data->pulse_len = ev.duration; 87 data->state = STATE_BIT_SPACE; 88 return 0; 89 90 case STATE_BIT_SPACE: 91 if (ev.pulse) 92 break; 93 94 data->bits <<= 1; 95 if (eq_margin(data->pulse_len + ev.duration, SHARP_BIT_1_PERIOD, 96 SHARP_BIT_PULSE * 2)) 97 data->bits |= 1; 98 else if (!eq_margin(data->pulse_len + ev.duration, 99 SHARP_BIT_0_PERIOD, SHARP_BIT_PULSE * 2)) 100 break; 101 data->count++; 102 103 if (data->count == SHARP_NBITS || 104 data->count == SHARP_NBITS * 2) 105 data->state = STATE_TRAILER_PULSE; 106 else 107 data->state = STATE_BIT_PULSE; 108 109 return 0; 110 111 case STATE_TRAILER_PULSE: 112 if (!ev.pulse) 113 break; 114 115 if (!eq_margin(ev.duration, SHARP_BIT_PULSE, 116 SHARP_BIT_PULSE / 2)) 117 break; 118 119 if (data->count == SHARP_NBITS) { 120 /* exp,chk bits should be 1,0 */ 121 if ((data->bits & 0x3) != 0x2) 122 break; 123 data->state = STATE_ECHO_SPACE; 124 } else { 125 data->state = STATE_TRAILER_SPACE; 126 } 127 return 0; 128 129 case STATE_ECHO_SPACE: 130 if (ev.pulse) 131 break; 132 133 if (!eq_margin(ev.duration, SHARP_ECHO_SPACE, 134 SHARP_ECHO_SPACE / 4)) 135 break; 136 137 data->state = STATE_BIT_PULSE; 138 139 return 0; 140 141 case STATE_TRAILER_SPACE: 142 if (ev.pulse) 143 break; 144 145 if (!geq_margin(ev.duration, SHARP_TRAILER_SPACE, 146 SHARP_BIT_PULSE / 2)) 147 break; 148 149 /* Validate - command, ext, chk should be inverted in 2nd */ 150 msg = (data->bits >> 15) & 0x7fff; 151 echo = data->bits & 0x7fff; 152 if ((msg ^ echo) != 0x3ff) { 153 IR_dprintk(1, 154 "Sharp checksum error: received 0x%04x, 0x%04x\n", 155 msg, echo); 156 break; 157 } 158 159 address = bitrev8((msg >> 7) & 0xf8); 160 command = bitrev8((msg >> 2) & 0xff); 161 162 scancode = address << 8 | command; 163 IR_dprintk(1, "Sharp scancode 0x%04x\n", scancode); 164 165 rc_keydown(dev, RC_TYPE_SHARP, scancode, 0); 166 data->state = STATE_INACTIVE; 167 return 0; 168 } 169 170 IR_dprintk(1, "Sharp decode failed at count %d state %d (%uus %s)\n", 171 data->count, data->state, TO_US(ev.duration), 172 TO_STR(ev.pulse)); 173 data->state = STATE_INACTIVE; 174 return -EINVAL; 175} 176 177static struct ir_raw_handler sharp_handler = { 178 .protocols = RC_BIT_SHARP, 179 .decode = ir_sharp_decode, 180}; 181 182static int __init ir_sharp_decode_init(void) 183{ 184 ir_raw_handler_register(&sharp_handler); 185 186 pr_info("IR Sharp protocol handler initialized\n"); 187 return 0; 188} 189 190static void __exit ir_sharp_decode_exit(void) 191{ 192 ir_raw_handler_unregister(&sharp_handler); 193} 194 195module_init(ir_sharp_decode_init); 196module_exit(ir_sharp_decode_exit); 197 198MODULE_LICENSE("GPL"); 199MODULE_AUTHOR("James Hogan <james.hogan@imgtec.com>"); 200MODULE_DESCRIPTION("Sharp IR protocol decoder"); 201