236 lines · c
1// SPDX-License-Identifier: GPL-2.02// ir-sanyo-decoder.c - handle SANYO IR Pulse/Space protocol3//4// Copyright (C) 2011 by Mauro Carvalho Chehab5//6// This protocol uses the NEC protocol timings. However, data is formatted as:7// 13 bits Custom Code8// 13 bits NOT(Custom Code)9// 8 bits Key data10// 8 bits NOT(Key data)11//12// According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon13// Information for this protocol is available at the Sanyo LC7461 datasheet.14 15#include <linux/module.h>16#include <linux/bitrev.h>17#include "rc-core-priv.h"18 19#define SANYO_NBITS (13+13+8+8)20#define SANYO_UNIT 563 /* us */21#define SANYO_HEADER_PULSE (16 * SANYO_UNIT)22#define SANYO_HEADER_SPACE (8 * SANYO_UNIT)23#define SANYO_BIT_PULSE (1 * SANYO_UNIT)24#define SANYO_BIT_0_SPACE (1 * SANYO_UNIT)25#define SANYO_BIT_1_SPACE (3 * SANYO_UNIT)26#define SANYO_REPEAT_SPACE (150 * SANYO_UNIT)27#define SANYO_TRAILER_PULSE (1 * SANYO_UNIT)28#define SANYO_TRAILER_SPACE (10 * SANYO_UNIT) /* in fact, 42 */29 30enum sanyo_state {31 STATE_INACTIVE,32 STATE_HEADER_SPACE,33 STATE_BIT_PULSE,34 STATE_BIT_SPACE,35 STATE_TRAILER_PULSE,36 STATE_TRAILER_SPACE,37};38 39/**40 * ir_sanyo_decode() - Decode one SANYO pulse or space41 * @dev: the struct rc_dev descriptor of the device42 * @ev: the struct ir_raw_event descriptor of the pulse/space43 *44 * This function returns -EINVAL if the pulse violates the state machine45 */46static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)47{48 struct sanyo_dec *data = &dev->raw->sanyo;49 u32 scancode;50 u16 address;51 u8 command, not_command;52 53 if (!is_timing_event(ev)) {54 if (ev.overflow) {55 dev_dbg(&dev->dev, "SANYO event overflow received. reset to state 0\n");56 data->state = STATE_INACTIVE;57 }58 return 0;59 }60 61 dev_dbg(&dev->dev, "SANYO decode started at state %d (%uus %s)\n",62 data->state, ev.duration, TO_STR(ev.pulse));63 64 switch (data->state) {65 66 case STATE_INACTIVE:67 if (!ev.pulse)68 break;69 70 if (eq_margin(ev.duration, SANYO_HEADER_PULSE, SANYO_UNIT / 2)) {71 data->count = 0;72 data->state = STATE_HEADER_SPACE;73 return 0;74 }75 break;76 77 78 case STATE_HEADER_SPACE:79 if (ev.pulse)80 break;81 82 if (eq_margin(ev.duration, SANYO_HEADER_SPACE, SANYO_UNIT / 2)) {83 data->state = STATE_BIT_PULSE;84 return 0;85 }86 87 break;88 89 case STATE_BIT_PULSE:90 if (!ev.pulse)91 break;92 93 if (!eq_margin(ev.duration, SANYO_BIT_PULSE, SANYO_UNIT / 2))94 break;95 96 data->state = STATE_BIT_SPACE;97 return 0;98 99 case STATE_BIT_SPACE:100 if (ev.pulse)101 break;102 103 if (!data->count && geq_margin(ev.duration, SANYO_REPEAT_SPACE, SANYO_UNIT / 2)) {104 rc_repeat(dev);105 dev_dbg(&dev->dev, "SANYO repeat last key\n");106 data->state = STATE_INACTIVE;107 return 0;108 }109 110 data->bits <<= 1;111 if (eq_margin(ev.duration, SANYO_BIT_1_SPACE, SANYO_UNIT / 2))112 data->bits |= 1;113 else if (!eq_margin(ev.duration, SANYO_BIT_0_SPACE, SANYO_UNIT / 2))114 break;115 data->count++;116 117 if (data->count == SANYO_NBITS)118 data->state = STATE_TRAILER_PULSE;119 else120 data->state = STATE_BIT_PULSE;121 122 return 0;123 124 case STATE_TRAILER_PULSE:125 if (!ev.pulse)126 break;127 128 if (!eq_margin(ev.duration, SANYO_TRAILER_PULSE, SANYO_UNIT / 2))129 break;130 131 data->state = STATE_TRAILER_SPACE;132 return 0;133 134 case STATE_TRAILER_SPACE:135 if (ev.pulse)136 break;137 138 if (!geq_margin(ev.duration, SANYO_TRAILER_SPACE, SANYO_UNIT / 2))139 break;140 141 address = bitrev16((data->bits >> 29) & 0x1fff) >> 3;142 /* not_address = bitrev16((data->bits >> 16) & 0x1fff) >> 3; */143 command = bitrev8((data->bits >> 8) & 0xff);144 not_command = bitrev8((data->bits >> 0) & 0xff);145 146 if ((command ^ not_command) != 0xff) {147 dev_dbg(&dev->dev, "SANYO checksum error: received 0x%08llx\n",148 data->bits);149 data->state = STATE_INACTIVE;150 return 0;151 }152 153 scancode = address << 8 | command;154 dev_dbg(&dev->dev, "SANYO scancode: 0x%06x\n", scancode);155 rc_keydown(dev, RC_PROTO_SANYO, scancode, 0);156 data->state = STATE_INACTIVE;157 return 0;158 }159 160 dev_dbg(&dev->dev, "SANYO decode failed at count %d state %d (%uus %s)\n",161 data->count, data->state, ev.duration, TO_STR(ev.pulse));162 data->state = STATE_INACTIVE;163 return -EINVAL;164}165 166static const struct ir_raw_timings_pd ir_sanyo_timings = {167 .header_pulse = SANYO_HEADER_PULSE,168 .header_space = SANYO_HEADER_SPACE,169 .bit_pulse = SANYO_BIT_PULSE,170 .bit_space[0] = SANYO_BIT_0_SPACE,171 .bit_space[1] = SANYO_BIT_1_SPACE,172 .trailer_pulse = SANYO_TRAILER_PULSE,173 .trailer_space = SANYO_TRAILER_SPACE,174 .msb_first = 1,175};176 177/**178 * ir_sanyo_encode() - Encode a scancode as a stream of raw events179 *180 * @protocol: protocol to encode181 * @scancode: scancode to encode182 * @events: array of raw ir events to write into183 * @max: maximum size of @events184 *185 * Returns: The number of events written.186 * -ENOBUFS if there isn't enough space in the array to fit the187 * encoding. In this case all @max events will have been written.188 */189static int ir_sanyo_encode(enum rc_proto protocol, u32 scancode,190 struct ir_raw_event *events, unsigned int max)191{192 struct ir_raw_event *e = events;193 int ret;194 u64 raw;195 196 raw = ((u64)(bitrev16(scancode >> 8) & 0xfff8) << (8 + 8 + 13 - 3)) |197 ((u64)(bitrev16(~scancode >> 8) & 0xfff8) << (8 + 8 + 0 - 3)) |198 ((bitrev8(scancode) & 0xff) << 8) |199 (bitrev8(~scancode) & 0xff);200 201 ret = ir_raw_gen_pd(&e, max, &ir_sanyo_timings, SANYO_NBITS, raw);202 if (ret < 0)203 return ret;204 205 return e - events;206}207 208static struct ir_raw_handler sanyo_handler = {209 .protocols = RC_PROTO_BIT_SANYO,210 .decode = ir_sanyo_decode,211 .encode = ir_sanyo_encode,212 .carrier = 38000,213 .min_timeout = SANYO_TRAILER_SPACE,214};215 216static int __init ir_sanyo_decode_init(void)217{218 ir_raw_handler_register(&sanyo_handler);219 220 printk(KERN_INFO "IR SANYO protocol handler initialized\n");221 return 0;222}223 224static void __exit ir_sanyo_decode_exit(void)225{226 ir_raw_handler_unregister(&sanyo_handler);227}228 229module_init(ir_sanyo_decode_init);230module_exit(ir_sanyo_decode_exit);231 232MODULE_LICENSE("GPL v2");233MODULE_AUTHOR("Mauro Carvalho Chehab");234MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");235MODULE_DESCRIPTION("SANYO IR protocol decoder");236