Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* ir-sharp-decoder.c - handle Sharp IR Pulse/Space protocol
0003  *
0004  * Copyright (C) 2013-2014 Imagination Technologies Ltd.
0005  *
0006  * Based on NEC decoder:
0007  * Copyright (C) 2010 by Mauro Carvalho Chehab
0008  */
0009 
0010 #include <linux/bitrev.h>
0011 #include <linux/module.h>
0012 #include "rc-core-priv.h"
0013 
0014 #define SHARP_NBITS     15
0015 #define SHARP_UNIT      40  /* us */
0016 #define SHARP_BIT_PULSE     (8    * SHARP_UNIT) /* 320us */
0017 #define SHARP_BIT_0_PERIOD  (25   * SHARP_UNIT) /* 1ms (680us space) */
0018 #define SHARP_BIT_1_PERIOD  (50   * SHARP_UNIT) /* 2ms (1680ms space) */
0019 #define SHARP_ECHO_SPACE    (1000 * SHARP_UNIT) /* 40 ms */
0020 #define SHARP_TRAILER_SPACE (125  * SHARP_UNIT) /* 5 ms (even longer) */
0021 
0022 enum sharp_state {
0023     STATE_INACTIVE,
0024     STATE_BIT_PULSE,
0025     STATE_BIT_SPACE,
0026     STATE_TRAILER_PULSE,
0027     STATE_ECHO_SPACE,
0028     STATE_TRAILER_SPACE,
0029 };
0030 
0031 /**
0032  * ir_sharp_decode() - Decode one Sharp pulse or space
0033  * @dev:    the struct rc_dev descriptor of the device
0034  * @ev:     the struct ir_raw_event descriptor of the pulse/space
0035  *
0036  * This function returns -EINVAL if the pulse violates the state machine
0037  */
0038 static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev)
0039 {
0040     struct sharp_dec *data = &dev->raw->sharp;
0041     u32 msg, echo, address, command, scancode;
0042 
0043     if (!is_timing_event(ev)) {
0044         if (ev.overflow)
0045             data->state = STATE_INACTIVE;
0046         return 0;
0047     }
0048 
0049     dev_dbg(&dev->dev, "Sharp decode started at state %d (%uus %s)\n",
0050         data->state, ev.duration, TO_STR(ev.pulse));
0051 
0052     switch (data->state) {
0053 
0054     case STATE_INACTIVE:
0055         if (!ev.pulse)
0056             break;
0057 
0058         if (!eq_margin(ev.duration, SHARP_BIT_PULSE,
0059                    SHARP_BIT_PULSE / 2))
0060             break;
0061 
0062         data->count = 0;
0063         data->pulse_len = ev.duration;
0064         data->state = STATE_BIT_SPACE;
0065         return 0;
0066 
0067     case STATE_BIT_PULSE:
0068         if (!ev.pulse)
0069             break;
0070 
0071         if (!eq_margin(ev.duration, SHARP_BIT_PULSE,
0072                    SHARP_BIT_PULSE / 2))
0073             break;
0074 
0075         data->pulse_len = ev.duration;
0076         data->state = STATE_BIT_SPACE;
0077         return 0;
0078 
0079     case STATE_BIT_SPACE:
0080         if (ev.pulse)
0081             break;
0082 
0083         data->bits <<= 1;
0084         if (eq_margin(data->pulse_len + ev.duration, SHARP_BIT_1_PERIOD,
0085                   SHARP_BIT_PULSE * 2))
0086             data->bits |= 1;
0087         else if (!eq_margin(data->pulse_len + ev.duration,
0088                     SHARP_BIT_0_PERIOD, SHARP_BIT_PULSE * 2))
0089             break;
0090         data->count++;
0091 
0092         if (data->count == SHARP_NBITS ||
0093             data->count == SHARP_NBITS * 2)
0094             data->state = STATE_TRAILER_PULSE;
0095         else
0096             data->state = STATE_BIT_PULSE;
0097 
0098         return 0;
0099 
0100     case STATE_TRAILER_PULSE:
0101         if (!ev.pulse)
0102             break;
0103 
0104         if (!eq_margin(ev.duration, SHARP_BIT_PULSE,
0105                    SHARP_BIT_PULSE / 2))
0106             break;
0107 
0108         if (data->count == SHARP_NBITS) {
0109             /* exp,chk bits should be 1,0 */
0110             if ((data->bits & 0x3) != 0x2 &&
0111             /* DENON variant, both chk bits 0 */
0112                 (data->bits & 0x3) != 0x0)
0113                 break;
0114             data->state = STATE_ECHO_SPACE;
0115         } else {
0116             data->state = STATE_TRAILER_SPACE;
0117         }
0118         return 0;
0119 
0120     case STATE_ECHO_SPACE:
0121         if (ev.pulse)
0122             break;
0123 
0124         if (!eq_margin(ev.duration, SHARP_ECHO_SPACE,
0125                    SHARP_ECHO_SPACE / 4))
0126             break;
0127 
0128         data->state = STATE_BIT_PULSE;
0129 
0130         return 0;
0131 
0132     case STATE_TRAILER_SPACE:
0133         if (ev.pulse)
0134             break;
0135 
0136         if (!geq_margin(ev.duration, SHARP_TRAILER_SPACE,
0137                 SHARP_BIT_PULSE / 2))
0138             break;
0139 
0140         /* Validate - command, ext, chk should be inverted in 2nd */
0141         msg = (data->bits >> 15) & 0x7fff;
0142         echo = data->bits & 0x7fff;
0143         if ((msg ^ echo) != 0x3ff) {
0144             dev_dbg(&dev->dev,
0145                 "Sharp checksum error: received 0x%04x, 0x%04x\n",
0146                 msg, echo);
0147             break;
0148         }
0149 
0150         address = bitrev8((msg >> 7) & 0xf8);
0151         command = bitrev8((msg >> 2) & 0xff);
0152 
0153         scancode = address << 8 | command;
0154         dev_dbg(&dev->dev, "Sharp scancode 0x%04x\n", scancode);
0155 
0156         rc_keydown(dev, RC_PROTO_SHARP, scancode, 0);
0157         data->state = STATE_INACTIVE;
0158         return 0;
0159     }
0160 
0161     dev_dbg(&dev->dev, "Sharp decode failed at count %d state %d (%uus %s)\n",
0162         data->count, data->state, ev.duration, TO_STR(ev.pulse));
0163     data->state = STATE_INACTIVE;
0164     return -EINVAL;
0165 }
0166 
0167 static const struct ir_raw_timings_pd ir_sharp_timings = {
0168     .header_pulse  = 0,
0169     .header_space  = 0,
0170     .bit_pulse     = SHARP_BIT_PULSE,
0171     .bit_space[0]  = SHARP_BIT_0_PERIOD,
0172     .bit_space[1]  = SHARP_BIT_1_PERIOD,
0173     .trailer_pulse = SHARP_BIT_PULSE,
0174     .trailer_space = SHARP_ECHO_SPACE,
0175     .msb_first     = 1,
0176 };
0177 
0178 /**
0179  * ir_sharp_encode() - Encode a scancode as a stream of raw events
0180  *
0181  * @protocol:   protocol to encode
0182  * @scancode:   scancode to encode
0183  * @events: array of raw ir events to write into
0184  * @max:    maximum size of @events
0185  *
0186  * Returns: The number of events written.
0187  *      -ENOBUFS if there isn't enough space in the array to fit the
0188  *      encoding. In this case all @max events will have been written.
0189  */
0190 static int ir_sharp_encode(enum rc_proto protocol, u32 scancode,
0191                struct ir_raw_event *events, unsigned int max)
0192 {
0193     struct ir_raw_event *e = events;
0194     int ret;
0195     u32 raw;
0196 
0197     raw = (((bitrev8(scancode >> 8) >> 3) << 8) & 0x1f00) |
0198         bitrev8(scancode);
0199     ret = ir_raw_gen_pd(&e, max, &ir_sharp_timings, SHARP_NBITS,
0200                 (raw << 2) | 2);
0201     if (ret < 0)
0202         return ret;
0203 
0204     max -= ret;
0205 
0206     raw = (((bitrev8(scancode >> 8) >> 3) << 8) & 0x1f00) |
0207         bitrev8(~scancode);
0208     ret = ir_raw_gen_pd(&e, max, &ir_sharp_timings, SHARP_NBITS,
0209                 (raw << 2) | 1);
0210     if (ret < 0)
0211         return ret;
0212 
0213     return e - events;
0214 }
0215 
0216 static struct ir_raw_handler sharp_handler = {
0217     .protocols  = RC_PROTO_BIT_SHARP,
0218     .decode     = ir_sharp_decode,
0219     .encode     = ir_sharp_encode,
0220     .carrier    = 38000,
0221     .min_timeout    = SHARP_ECHO_SPACE + SHARP_ECHO_SPACE / 4,
0222 };
0223 
0224 static int __init ir_sharp_decode_init(void)
0225 {
0226     ir_raw_handler_register(&sharp_handler);
0227 
0228     pr_info("IR Sharp protocol handler initialized\n");
0229     return 0;
0230 }
0231 
0232 static void __exit ir_sharp_decode_exit(void)
0233 {
0234     ir_raw_handler_unregister(&sharp_handler);
0235 }
0236 
0237 module_init(ir_sharp_decode_init);
0238 module_exit(ir_sharp_decode_exit);
0239 
0240 MODULE_LICENSE("GPL");
0241 MODULE_AUTHOR("James Hogan <jhogan@kernel.org>");
0242 MODULE_DESCRIPTION("Sharp IR protocol decoder");