1 // SPDX-License-Identifier: GPL-2.0-only 2 /* ir-sharp-decoder.c - handle Sharp IR Pulse/Space protocol 3 * 4 * Copyright (C) 2013-2014 Imagination Technologies Ltd. 5 * 6 * Based on NEC decoder: 7 * Copyright (C) 2010 by Mauro Carvalho Chehab 8 */ 9 10 #include <linux/bitrev.h> 11 #include <linux/module.h> 12 #include "rc-core-priv.h" 13 14 #define SHARP_NBITS 15 15 #define SHARP_UNIT 40 /* us */ 16 #define SHARP_BIT_PULSE (8 * SHARP_UNIT) /* 320us */ 17 #define SHARP_BIT_0_PERIOD (25 * SHARP_UNIT) /* 1ms (680us space) */ 18 #define SHARP_BIT_1_PERIOD (50 * SHARP_UNIT) /* 2ms (1680us space) */ 19 #define SHARP_BIT_0_SPACE (17 * SHARP_UNIT) /* 680us space */ 20 #define SHARP_BIT_1_SPACE (42 * SHARP_UNIT) /* 1680us space */ 21 #define SHARP_ECHO_SPACE (1000 * SHARP_UNIT) /* 40 ms */ 22 #define SHARP_TRAILER_SPACE (125 * SHARP_UNIT) /* 5 ms (even longer) */ 23 24 enum sharp_state { 25 STATE_INACTIVE, 26 STATE_BIT_PULSE, 27 STATE_BIT_SPACE, 28 STATE_TRAILER_PULSE, 29 STATE_ECHO_SPACE, 30 STATE_TRAILER_SPACE, 31 }; 32 33 /** 34 * ir_sharp_decode() - Decode one Sharp pulse or space 35 * @dev: the struct rc_dev descriptor of the device 36 * @ev: the struct ir_raw_event descriptor of the pulse/space 37 * 38 * This function returns -EINVAL if the pulse violates the state machine 39 */ 40 static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev) 41 { 42 struct sharp_dec *data = &dev->raw->sharp; 43 u32 msg, echo, address, command, scancode; 44 45 if (!is_timing_event(ev)) { 46 if (ev.overflow) 47 data->state = STATE_INACTIVE; 48 return 0; 49 } 50 51 dev_dbg(&dev->dev, "Sharp decode started at state %d (%uus %s)\n", 52 data->state, ev.duration, TO_STR(ev.pulse)); 53 54 switch (data->state) { 55 56 case STATE_INACTIVE: 57 if (!ev.pulse) 58 break; 59 60 if (!eq_margin(ev.duration, SHARP_BIT_PULSE, 61 SHARP_BIT_PULSE / 2)) 62 break; 63 64 data->count = 0; 65 data->pulse_len = ev.duration; 66 data->state = STATE_BIT_SPACE; 67 return 0; 68 69 case STATE_BIT_PULSE: 70 if (!ev.pulse) 71 break; 72 73 if (!eq_margin(ev.duration, SHARP_BIT_PULSE, 74 SHARP_BIT_PULSE / 2)) 75 break; 76 77 data->pulse_len = ev.duration; 78 data->state = STATE_BIT_SPACE; 79 return 0; 80 81 case STATE_BIT_SPACE: 82 if (ev.pulse) 83 break; 84 85 data->bits <<= 1; 86 if (eq_margin(data->pulse_len + ev.duration, SHARP_BIT_1_PERIOD, 87 SHARP_BIT_PULSE * 2)) 88 data->bits |= 1; 89 else if (!eq_margin(data->pulse_len + ev.duration, 90 SHARP_BIT_0_PERIOD, SHARP_BIT_PULSE * 2)) 91 break; 92 data->count++; 93 94 if (data->count == SHARP_NBITS || 95 data->count == SHARP_NBITS * 2) 96 data->state = STATE_TRAILER_PULSE; 97 else 98 data->state = STATE_BIT_PULSE; 99 100 return 0; 101 102 case STATE_TRAILER_PULSE: 103 if (!ev.pulse) 104 break; 105 106 if (!eq_margin(ev.duration, SHARP_BIT_PULSE, 107 SHARP_BIT_PULSE / 2)) 108 break; 109 110 if (data->count == SHARP_NBITS) { 111 /* exp,chk bits should be 1,0 */ 112 if ((data->bits & 0x3) != 0x2 && 113 /* DENON variant, both chk bits 0 */ 114 (data->bits & 0x3) != 0x0) 115 break; 116 data->state = STATE_ECHO_SPACE; 117 } else { 118 data->state = STATE_TRAILER_SPACE; 119 } 120 return 0; 121 122 case STATE_ECHO_SPACE: 123 if (ev.pulse) 124 break; 125 126 if (!eq_margin(ev.duration, SHARP_ECHO_SPACE, 127 SHARP_ECHO_SPACE / 4)) 128 break; 129 130 data->state = STATE_BIT_PULSE; 131 132 return 0; 133 134 case STATE_TRAILER_SPACE: 135 if (ev.pulse) 136 break; 137 138 if (!geq_margin(ev.duration, SHARP_TRAILER_SPACE, 139 SHARP_BIT_PULSE / 2)) 140 break; 141 142 /* Validate - command, ext, chk should be inverted in 2nd */ 143 msg = (data->bits >> 15) & 0x7fff; 144 echo = data->bits & 0x7fff; 145 if ((msg ^ echo) != 0x3ff) { 146 dev_dbg(&dev->dev, 147 "Sharp checksum error: received 0x%04x, 0x%04x\n", 148 msg, echo); 149 break; 150 } 151 152 address = bitrev8((msg >> 7) & 0xf8); 153 command = bitrev8((msg >> 2) & 0xff); 154 155 scancode = address << 8 | command; 156 dev_dbg(&dev->dev, "Sharp scancode 0x%04x\n", scancode); 157 158 rc_keydown(dev, RC_PROTO_SHARP, scancode, 0); 159 data->state = STATE_INACTIVE; 160 return 0; 161 } 162 163 dev_dbg(&dev->dev, "Sharp decode failed at count %d state %d (%uus %s)\n", 164 data->count, data->state, ev.duration, TO_STR(ev.pulse)); 165 data->state = STATE_INACTIVE; 166 return -EINVAL; 167 } 168 169 static const struct ir_raw_timings_pd ir_sharp_timings = { 170 .header_pulse = 0, 171 .header_space = 0, 172 .bit_pulse = SHARP_BIT_PULSE, 173 .bit_space[0] = SHARP_BIT_0_SPACE, 174 .bit_space[1] = SHARP_BIT_1_SPACE, 175 .trailer_pulse = SHARP_BIT_PULSE, 176 .trailer_space = SHARP_ECHO_SPACE, 177 .msb_first = 1, 178 }; 179 180 /** 181 * ir_sharp_encode() - Encode a scancode as a stream of raw events 182 * 183 * @protocol: protocol to encode 184 * @scancode: scancode to encode 185 * @events: array of raw ir events to write into 186 * @max: maximum size of @events 187 * 188 * Returns: The number of events written. 189 * -ENOBUFS if there isn't enough space in the array to fit the 190 * encoding. In this case all @max events will have been written. 191 */ 192 static int ir_sharp_encode(enum rc_proto protocol, u32 scancode, 193 struct ir_raw_event *events, unsigned int max) 194 { 195 struct ir_raw_event *e = events; 196 int ret; 197 u32 raw; 198 199 raw = (((bitrev8(scancode >> 8) >> 3) << 8) & 0x1f00) | 200 bitrev8(scancode); 201 ret = ir_raw_gen_pd(&e, max, &ir_sharp_timings, SHARP_NBITS, 202 (raw << 2) | 2); 203 if (ret < 0) 204 return ret; 205 206 max -= ret; 207 208 raw = (((bitrev8(scancode >> 8) >> 3) << 8) & 0x1f00) | 209 bitrev8(~scancode); 210 ret = ir_raw_gen_pd(&e, max, &ir_sharp_timings, SHARP_NBITS, 211 (raw << 2) | 1); 212 if (ret < 0) 213 return ret; 214 215 return e - events; 216 } 217 218 static struct ir_raw_handler sharp_handler = { 219 .protocols = RC_PROTO_BIT_SHARP, 220 .decode = ir_sharp_decode, 221 .encode = ir_sharp_encode, 222 .carrier = 38000, 223 .min_timeout = SHARP_ECHO_SPACE + SHARP_ECHO_SPACE / 4, 224 }; 225 226 static int __init ir_sharp_decode_init(void) 227 { 228 ir_raw_handler_register(&sharp_handler); 229 230 pr_info("IR Sharp protocol handler initialized\n"); 231 return 0; 232 } 233 234 static void __exit ir_sharp_decode_exit(void) 235 { 236 ir_raw_handler_unregister(&sharp_handler); 237 } 238 239 module_init(ir_sharp_decode_init); 240 module_exit(ir_sharp_decode_exit); 241 242 MODULE_LICENSE("GPL"); 243 MODULE_AUTHOR("James Hogan <jhogan@kernel.org>"); 244 MODULE_DESCRIPTION("Sharp IR protocol decoder"); 245