Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 // ir-rcmm-decoder.c - A decoder for the RCMM IR protocol
0003 //
0004 // Copyright (C) 2018 by Patrick Lerda <patrick9876@free.fr>
0005 
0006 #include "rc-core-priv.h"
0007 #include <linux/module.h>
0008 
0009 #define RCMM_UNIT       166  /* microseconds */
0010 #define RCMM_PREFIX_PULSE   417  /* 166.666666666666*2.5 */
0011 #define RCMM_PULSE_0            278  /* 166.666666666666*(1+2/3) */
0012 #define RCMM_PULSE_1            444  /* 166.666666666666*(2+2/3) */
0013 #define RCMM_PULSE_2            611  /* 166.666666666666*(3+2/3) */
0014 #define RCMM_PULSE_3            778  /* 166.666666666666*(4+2/3) */
0015 
0016 enum rcmm_state {
0017     STATE_INACTIVE,
0018     STATE_LOW,
0019     STATE_BUMP,
0020     STATE_VALUE,
0021     STATE_FINISHED,
0022 };
0023 
0024 static bool rcmm_mode(const struct rcmm_dec *data)
0025 {
0026     return !((0x000c0000 & data->bits) == 0x000c0000);
0027 }
0028 
0029 static int rcmm_miscmode(struct rc_dev *dev, struct rcmm_dec *data)
0030 {
0031     switch (data->count) {
0032     case 24:
0033         if (dev->enabled_protocols & RC_PROTO_BIT_RCMM24) {
0034             rc_keydown(dev, RC_PROTO_RCMM24, data->bits, 0);
0035             data->state = STATE_INACTIVE;
0036             return 0;
0037         }
0038         return -1;
0039 
0040     case 12:
0041         if (dev->enabled_protocols & RC_PROTO_BIT_RCMM12) {
0042             rc_keydown(dev, RC_PROTO_RCMM12, data->bits, 0);
0043             data->state = STATE_INACTIVE;
0044             return 0;
0045         }
0046         return -1;
0047     }
0048 
0049     return -1;
0050 }
0051 
0052 /**
0053  * ir_rcmm_decode() - Decode one RCMM pulse or space
0054  * @dev:    the struct rc_dev descriptor of the device
0055  * @ev:     the struct ir_raw_event descriptor of the pulse/space
0056  *
0057  * This function returns -EINVAL if the pulse violates the state machine
0058  */
0059 static int ir_rcmm_decode(struct rc_dev *dev, struct ir_raw_event ev)
0060 {
0061     struct rcmm_dec *data = &dev->raw->rcmm;
0062     u32 scancode;
0063     u8 toggle;
0064     int value;
0065 
0066     if (!(dev->enabled_protocols & (RC_PROTO_BIT_RCMM32 |
0067                     RC_PROTO_BIT_RCMM24 |
0068                     RC_PROTO_BIT_RCMM12)))
0069         return 0;
0070 
0071     if (!is_timing_event(ev)) {
0072         if (ev.overflow)
0073             data->state = STATE_INACTIVE;
0074         return 0;
0075     }
0076 
0077     switch (data->state) {
0078     case STATE_INACTIVE:
0079         if (!ev.pulse)
0080             break;
0081 
0082         if (!eq_margin(ev.duration, RCMM_PREFIX_PULSE, RCMM_UNIT))
0083             break;
0084 
0085         data->state = STATE_LOW;
0086         data->count = 0;
0087         data->bits  = 0;
0088         return 0;
0089 
0090     case STATE_LOW:
0091         if (ev.pulse)
0092             break;
0093 
0094         if (!eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT))
0095             break;
0096 
0097         data->state = STATE_BUMP;
0098         return 0;
0099 
0100     case STATE_BUMP:
0101         if (!ev.pulse)
0102             break;
0103 
0104         if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
0105             break;
0106 
0107         data->state = STATE_VALUE;
0108         return 0;
0109 
0110     case STATE_VALUE:
0111         if (ev.pulse)
0112             break;
0113 
0114         if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2))
0115             value = 0;
0116         else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2))
0117             value = 1;
0118         else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2))
0119             value = 2;
0120         else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2))
0121             value = 3;
0122         else
0123             value = -1;
0124 
0125         if (value == -1) {
0126             if (!rcmm_miscmode(dev, data))
0127                 return 0;
0128             break;
0129         }
0130 
0131         data->bits <<= 2;
0132         data->bits |= value;
0133 
0134         data->count += 2;
0135 
0136         if (data->count < 32)
0137             data->state = STATE_BUMP;
0138         else
0139             data->state = STATE_FINISHED;
0140 
0141         return 0;
0142 
0143     case STATE_FINISHED:
0144         if (!ev.pulse)
0145             break;
0146 
0147         if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
0148             break;
0149 
0150         if (rcmm_mode(data)) {
0151             toggle = !!(0x8000 & data->bits);
0152             scancode = data->bits & ~0x8000;
0153         } else {
0154             toggle = 0;
0155             scancode = data->bits;
0156         }
0157 
0158         if (dev->enabled_protocols & RC_PROTO_BIT_RCMM32) {
0159             rc_keydown(dev, RC_PROTO_RCMM32, scancode, toggle);
0160             data->state = STATE_INACTIVE;
0161             return 0;
0162         }
0163 
0164         break;
0165     }
0166 
0167     dev_dbg(&dev->dev, "RC-MM decode failed at count %d state %d (%uus %s)\n",
0168         data->count, data->state, ev.duration, TO_STR(ev.pulse));
0169     data->state = STATE_INACTIVE;
0170     return -EINVAL;
0171 }
0172 
0173 static const int rcmmspace[] = {
0174     RCMM_PULSE_0,
0175     RCMM_PULSE_1,
0176     RCMM_PULSE_2,
0177     RCMM_PULSE_3,
0178 };
0179 
0180 static int ir_rcmm_rawencoder(struct ir_raw_event **ev, unsigned int max,
0181                   unsigned int n, u32 data)
0182 {
0183     int i;
0184     int ret;
0185 
0186     ret = ir_raw_gen_pulse_space(ev, &max, RCMM_PREFIX_PULSE, RCMM_PULSE_0);
0187     if (ret)
0188         return ret;
0189 
0190     for (i = n - 2; i >= 0; i -= 2) {
0191         const unsigned int space = rcmmspace[(data >> i) & 3];
0192 
0193         ret = ir_raw_gen_pulse_space(ev, &max, RCMM_UNIT, space);
0194         if (ret)
0195             return ret;
0196     }
0197 
0198     return ir_raw_gen_pulse_space(ev, &max, RCMM_UNIT, RCMM_PULSE_3 * 2);
0199 }
0200 
0201 static int ir_rcmm_encode(enum rc_proto protocol, u32 scancode,
0202               struct ir_raw_event *events, unsigned int max)
0203 {
0204     struct ir_raw_event *e = events;
0205     int ret;
0206 
0207     switch (protocol) {
0208     case RC_PROTO_RCMM32:
0209         ret = ir_rcmm_rawencoder(&e, max, 32, scancode);
0210         break;
0211     case RC_PROTO_RCMM24:
0212         ret = ir_rcmm_rawencoder(&e, max, 24, scancode);
0213         break;
0214     case RC_PROTO_RCMM12:
0215         ret = ir_rcmm_rawencoder(&e, max, 12, scancode);
0216         break;
0217     default:
0218         ret = -EINVAL;
0219     }
0220 
0221     if (ret < 0)
0222         return ret;
0223 
0224     return e - events;
0225 }
0226 
0227 static struct ir_raw_handler rcmm_handler = {
0228     .protocols  = RC_PROTO_BIT_RCMM32 |
0229               RC_PROTO_BIT_RCMM24 |
0230               RC_PROTO_BIT_RCMM12,
0231     .decode     = ir_rcmm_decode,
0232     .encode         = ir_rcmm_encode,
0233     .carrier        = 36000,
0234     .min_timeout    = RCMM_PULSE_3 + RCMM_UNIT,
0235 };
0236 
0237 static int __init ir_rcmm_decode_init(void)
0238 {
0239     ir_raw_handler_register(&rcmm_handler);
0240 
0241     pr_info("IR RCMM protocol handler initialized\n");
0242     return 0;
0243 }
0244 
0245 static void __exit ir_rcmm_decode_exit(void)
0246 {
0247     ir_raw_handler_unregister(&rcmm_handler);
0248 }
0249 
0250 module_init(ir_rcmm_decode_init);
0251 module_exit(ir_rcmm_decode_exit);
0252 
0253 MODULE_LICENSE("GPL");
0254 MODULE_AUTHOR("Patrick Lerda");
0255 MODULE_DESCRIPTION("RCMM IR protocol decoder");