Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* ir-rc6-decoder.c - A decoder for the RC6 IR protocol
0003  *
0004  * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
0005  */
0006 
0007 #include "rc-core-priv.h"
0008 #include <linux/module.h>
0009 
0010 /*
0011  * This decoder currently supports:
0012  * RC6-0-16 (standard toggle bit in header)
0013  * RC6-6A-20    (no toggle bit)
0014  * RC6-6A-24    (no toggle bit)
0015  * RC6-6A-32    (MCE version with toggle bit in body)
0016  */
0017 
0018 #define RC6_UNIT        444 /* microseconds */
0019 #define RC6_HEADER_NBITS    4   /* not including toggle bit */
0020 #define RC6_0_NBITS     16
0021 #define RC6_6A_32_NBITS     32
0022 #define RC6_6A_NBITS        128 /* Variable 8..128 */
0023 #define RC6_PREFIX_PULSE    (6 * RC6_UNIT)
0024 #define RC6_PREFIX_SPACE    (2 * RC6_UNIT)
0025 #define RC6_BIT_START       (1 * RC6_UNIT)
0026 #define RC6_BIT_END     (1 * RC6_UNIT)
0027 #define RC6_TOGGLE_START    (2 * RC6_UNIT)
0028 #define RC6_TOGGLE_END      (2 * RC6_UNIT)
0029 #define RC6_SUFFIX_SPACE    (6 * RC6_UNIT)
0030 #define RC6_MODE_MASK       0x07    /* for the header bits */
0031 #define RC6_STARTBIT_MASK   0x08    /* for the header bits */
0032 #define RC6_6A_MCE_TOGGLE_MASK  0x8000  /* for the body bits */
0033 #define RC6_6A_LCC_MASK     0xffff0000 /* RC6-6A-32 long customer code mask */
0034 #define RC6_6A_MCE_CC       0x800f0000 /* MCE customer code */
0035 #define RC6_6A_ZOTAC_CC     0x80340000 /* Zotac customer code */
0036 #define RC6_6A_KATHREIN_CC  0x80460000 /* Kathrein RCU-676 customer code */
0037 #ifndef CHAR_BIT
0038 #define CHAR_BIT 8  /* Normally in <limits.h> */
0039 #endif
0040 
0041 enum rc6_mode {
0042     RC6_MODE_0,
0043     RC6_MODE_6A,
0044     RC6_MODE_UNKNOWN,
0045 };
0046 
0047 enum rc6_state {
0048     STATE_INACTIVE,
0049     STATE_PREFIX_SPACE,
0050     STATE_HEADER_BIT_START,
0051     STATE_HEADER_BIT_END,
0052     STATE_TOGGLE_START,
0053     STATE_TOGGLE_END,
0054     STATE_BODY_BIT_START,
0055     STATE_BODY_BIT_END,
0056     STATE_FINISHED,
0057 };
0058 
0059 static enum rc6_mode rc6_mode(struct rc6_dec *data)
0060 {
0061     switch (data->header & RC6_MODE_MASK) {
0062     case 0:
0063         return RC6_MODE_0;
0064     case 6:
0065         if (!data->toggle)
0066             return RC6_MODE_6A;
0067         fallthrough;
0068     default:
0069         return RC6_MODE_UNKNOWN;
0070     }
0071 }
0072 
0073 /**
0074  * ir_rc6_decode() - Decode one RC6 pulse or space
0075  * @dev:    the struct rc_dev descriptor of the device
0076  * @ev:     the struct ir_raw_event descriptor of the pulse/space
0077  *
0078  * This function returns -EINVAL if the pulse violates the state machine
0079  */
0080 static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
0081 {
0082     struct rc6_dec *data = &dev->raw->rc6;
0083     u32 scancode;
0084     u8 toggle;
0085     enum rc_proto protocol;
0086 
0087     if (!is_timing_event(ev)) {
0088         if (ev.overflow)
0089             data->state = STATE_INACTIVE;
0090         return 0;
0091     }
0092 
0093     if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
0094         goto out;
0095 
0096 again:
0097     dev_dbg(&dev->dev, "RC6 decode started at state %i (%uus %s)\n",
0098         data->state, ev.duration, TO_STR(ev.pulse));
0099 
0100     if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
0101         return 0;
0102 
0103     switch (data->state) {
0104 
0105     case STATE_INACTIVE:
0106         if (!ev.pulse)
0107             break;
0108 
0109         /* Note: larger margin on first pulse since each RC6_UNIT
0110            is quite short and some hardware takes some time to
0111            adjust to the signal */
0112         if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
0113             break;
0114 
0115         data->state = STATE_PREFIX_SPACE;
0116         data->count = 0;
0117         return 0;
0118 
0119     case STATE_PREFIX_SPACE:
0120         if (ev.pulse)
0121             break;
0122 
0123         if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
0124             break;
0125 
0126         data->state = STATE_HEADER_BIT_START;
0127         data->header = 0;
0128         return 0;
0129 
0130     case STATE_HEADER_BIT_START:
0131         if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
0132             break;
0133 
0134         data->header <<= 1;
0135         if (ev.pulse)
0136             data->header |= 1;
0137         data->count++;
0138         data->state = STATE_HEADER_BIT_END;
0139         return 0;
0140 
0141     case STATE_HEADER_BIT_END:
0142         if (data->count == RC6_HEADER_NBITS)
0143             data->state = STATE_TOGGLE_START;
0144         else
0145             data->state = STATE_HEADER_BIT_START;
0146 
0147         decrease_duration(&ev, RC6_BIT_END);
0148         goto again;
0149 
0150     case STATE_TOGGLE_START:
0151         if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
0152             break;
0153 
0154         data->toggle = ev.pulse;
0155         data->state = STATE_TOGGLE_END;
0156         return 0;
0157 
0158     case STATE_TOGGLE_END:
0159         if (!(data->header & RC6_STARTBIT_MASK)) {
0160             dev_dbg(&dev->dev, "RC6 invalid start bit\n");
0161             break;
0162         }
0163 
0164         data->state = STATE_BODY_BIT_START;
0165         decrease_duration(&ev, RC6_TOGGLE_END);
0166         data->count = 0;
0167         data->body = 0;
0168 
0169         switch (rc6_mode(data)) {
0170         case RC6_MODE_0:
0171             data->wanted_bits = RC6_0_NBITS;
0172             break;
0173         case RC6_MODE_6A:
0174             data->wanted_bits = RC6_6A_NBITS;
0175             break;
0176         default:
0177             dev_dbg(&dev->dev, "RC6 unknown mode\n");
0178             goto out;
0179         }
0180         goto again;
0181 
0182     case STATE_BODY_BIT_START:
0183         if (eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) {
0184             /* Discard LSB's that won't fit in data->body */
0185             if (data->count++ < CHAR_BIT * sizeof data->body) {
0186                 data->body <<= 1;
0187                 if (ev.pulse)
0188                     data->body |= 1;
0189             }
0190             data->state = STATE_BODY_BIT_END;
0191             return 0;
0192         } else if (RC6_MODE_6A == rc6_mode(data) && !ev.pulse &&
0193                 geq_margin(ev.duration, RC6_SUFFIX_SPACE, RC6_UNIT / 2)) {
0194             data->state = STATE_FINISHED;
0195             goto again;
0196         }
0197         break;
0198 
0199     case STATE_BODY_BIT_END:
0200         if (data->count == data->wanted_bits)
0201             data->state = STATE_FINISHED;
0202         else
0203             data->state = STATE_BODY_BIT_START;
0204 
0205         decrease_duration(&ev, RC6_BIT_END);
0206         goto again;
0207 
0208     case STATE_FINISHED:
0209         if (ev.pulse)
0210             break;
0211 
0212         switch (rc6_mode(data)) {
0213         case RC6_MODE_0:
0214             scancode = data->body;
0215             toggle = data->toggle;
0216             protocol = RC_PROTO_RC6_0;
0217             dev_dbg(&dev->dev, "RC6(0) scancode 0x%04x (toggle: %u)\n",
0218                 scancode, toggle);
0219             break;
0220 
0221         case RC6_MODE_6A:
0222             if (data->count > CHAR_BIT * sizeof data->body) {
0223                 dev_dbg(&dev->dev, "RC6 too many (%u) data bits\n",
0224                     data->count);
0225                 goto out;
0226             }
0227 
0228             scancode = data->body;
0229             switch (data->count) {
0230             case 20:
0231                 protocol = RC_PROTO_RC6_6A_20;
0232                 toggle = 0;
0233                 break;
0234             case 24:
0235                 protocol = RC_PROTO_RC6_6A_24;
0236                 toggle = 0;
0237                 break;
0238             case 32:
0239                 switch (scancode & RC6_6A_LCC_MASK) {
0240                 case RC6_6A_MCE_CC:
0241                 case RC6_6A_KATHREIN_CC:
0242                 case RC6_6A_ZOTAC_CC:
0243                     protocol = RC_PROTO_RC6_MCE;
0244                     toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
0245                     scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
0246                     break;
0247                 default:
0248                     protocol = RC_PROTO_RC6_6A_32;
0249                     toggle = 0;
0250                     break;
0251                 }
0252                 break;
0253             default:
0254                 dev_dbg(&dev->dev, "RC6(6A) unsupported length\n");
0255                 goto out;
0256             }
0257 
0258             dev_dbg(&dev->dev, "RC6(6A) proto 0x%04x, scancode 0x%08x (toggle: %u)\n",
0259                 protocol, scancode, toggle);
0260             break;
0261         default:
0262             dev_dbg(&dev->dev, "RC6 unknown mode\n");
0263             goto out;
0264         }
0265 
0266         rc_keydown(dev, protocol, scancode, toggle);
0267         data->state = STATE_INACTIVE;
0268         return 0;
0269     }
0270 
0271 out:
0272     dev_dbg(&dev->dev, "RC6 decode failed at state %i (%uus %s)\n",
0273         data->state, ev.duration, TO_STR(ev.pulse));
0274     data->state = STATE_INACTIVE;
0275     return -EINVAL;
0276 }
0277 
0278 static const struct ir_raw_timings_manchester ir_rc6_timings[4] = {
0279     {
0280         .leader_pulse       = RC6_PREFIX_PULSE,
0281         .leader_space       = RC6_PREFIX_SPACE,
0282         .clock          = RC6_UNIT,
0283         .invert         = 1,
0284     },
0285     {
0286         .clock          = RC6_UNIT * 2,
0287         .invert         = 1,
0288     },
0289     {
0290         .clock          = RC6_UNIT,
0291         .invert         = 1,
0292         .trailer_space      = RC6_SUFFIX_SPACE,
0293     },
0294 };
0295 
0296 /**
0297  * ir_rc6_encode() - Encode a scancode as a stream of raw events
0298  *
0299  * @protocol:   protocol to encode
0300  * @scancode:   scancode to encode
0301  * @events: array of raw ir events to write into
0302  * @max:    maximum size of @events
0303  *
0304  * Returns: The number of events written.
0305  *      -ENOBUFS if there isn't enough space in the array to fit the
0306  *      encoding. In this case all @max events will have been written.
0307  *      -EINVAL if the scancode is ambiguous or invalid.
0308  */
0309 static int ir_rc6_encode(enum rc_proto protocol, u32 scancode,
0310              struct ir_raw_event *events, unsigned int max)
0311 {
0312     int ret;
0313     struct ir_raw_event *e = events;
0314 
0315     if (protocol == RC_PROTO_RC6_0) {
0316         /* Modulate the header (Start Bit & Mode-0) */
0317         ret = ir_raw_gen_manchester(&e, max - (e - events),
0318                         &ir_rc6_timings[0],
0319                         RC6_HEADER_NBITS, (1 << 3));
0320         if (ret < 0)
0321             return ret;
0322 
0323         /* Modulate Trailer Bit */
0324         ret = ir_raw_gen_manchester(&e, max - (e - events),
0325                         &ir_rc6_timings[1], 1, 0);
0326         if (ret < 0)
0327             return ret;
0328 
0329         /* Modulate rest of the data */
0330         ret = ir_raw_gen_manchester(&e, max - (e - events),
0331                         &ir_rc6_timings[2], RC6_0_NBITS,
0332                         scancode);
0333         if (ret < 0)
0334             return ret;
0335 
0336     } else {
0337         int bits;
0338 
0339         switch (protocol) {
0340         case RC_PROTO_RC6_MCE:
0341         case RC_PROTO_RC6_6A_32:
0342             bits = 32;
0343             break;
0344         case RC_PROTO_RC6_6A_24:
0345             bits = 24;
0346             break;
0347         case RC_PROTO_RC6_6A_20:
0348             bits = 20;
0349             break;
0350         default:
0351             return -EINVAL;
0352         }
0353 
0354         /* Modulate the header (Start Bit & Header-version 6 */
0355         ret = ir_raw_gen_manchester(&e, max - (e - events),
0356                         &ir_rc6_timings[0],
0357                         RC6_HEADER_NBITS, (1 << 3 | 6));
0358         if (ret < 0)
0359             return ret;
0360 
0361         /* Modulate Trailer Bit */
0362         ret = ir_raw_gen_manchester(&e, max - (e - events),
0363                         &ir_rc6_timings[1], 1, 0);
0364         if (ret < 0)
0365             return ret;
0366 
0367         /* Modulate rest of the data */
0368         ret = ir_raw_gen_manchester(&e, max - (e - events),
0369                         &ir_rc6_timings[2],
0370                         bits,
0371                         scancode);
0372         if (ret < 0)
0373             return ret;
0374     }
0375 
0376     return e - events;
0377 }
0378 
0379 static struct ir_raw_handler rc6_handler = {
0380     .protocols  = RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 |
0381               RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 |
0382               RC_PROTO_BIT_RC6_MCE,
0383     .decode     = ir_rc6_decode,
0384     .encode     = ir_rc6_encode,
0385     .carrier    = 36000,
0386     .min_timeout    = RC6_SUFFIX_SPACE,
0387 };
0388 
0389 static int __init ir_rc6_decode_init(void)
0390 {
0391     ir_raw_handler_register(&rc6_handler);
0392 
0393     printk(KERN_INFO "IR RC6 protocol handler initialized\n");
0394     return 0;
0395 }
0396 
0397 static void __exit ir_rc6_decode_exit(void)
0398 {
0399     ir_raw_handler_unregister(&rc6_handler);
0400 }
0401 
0402 module_init(ir_rc6_decode_init);
0403 module_exit(ir_rc6_decode_exit);
0404 
0405 MODULE_LICENSE("GPL");
0406 MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
0407 MODULE_DESCRIPTION("RC6 IR protocol decoder");