root/drivers/media/rc/ir-jvc-decoder.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ir_jvc_decode
  2. ir_jvc_encode
  3. ir_jvc_decode_init
  4. ir_jvc_decode_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* ir-jvc-decoder.c - handle JVC IR Pulse/Space protocol
   3  *
   4  * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
   5  */
   6 
   7 #include <linux/bitrev.h>
   8 #include <linux/module.h>
   9 #include "rc-core-priv.h"
  10 
  11 #define JVC_NBITS               16              /* dev(8) + func(8) */
  12 #define JVC_UNIT                525000          /* ns */
  13 #define JVC_HEADER_PULSE        (16 * JVC_UNIT) /* lack of header -> repeat */
  14 #define JVC_HEADER_SPACE        (8  * JVC_UNIT)
  15 #define JVC_BIT_PULSE           (1  * JVC_UNIT)
  16 #define JVC_BIT_0_SPACE         (1  * JVC_UNIT)
  17 #define JVC_BIT_1_SPACE         (3  * JVC_UNIT)
  18 #define JVC_TRAILER_PULSE       (1  * JVC_UNIT)
  19 #define JVC_TRAILER_SPACE       (35 * JVC_UNIT)
  20 
  21 enum jvc_state {
  22         STATE_INACTIVE,
  23         STATE_HEADER_SPACE,
  24         STATE_BIT_PULSE,
  25         STATE_BIT_SPACE,
  26         STATE_TRAILER_PULSE,
  27         STATE_TRAILER_SPACE,
  28         STATE_CHECK_REPEAT,
  29 };
  30 
  31 /**
  32  * ir_jvc_decode() - Decode one JVC pulse or space
  33  * @dev:        the struct rc_dev descriptor of the device
  34  * @ev:   the struct ir_raw_event descriptor of the pulse/space
  35  *
  36  * This function returns -EINVAL if the pulse violates the state machine
  37  */
  38 static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev)
  39 {
  40         struct jvc_dec *data = &dev->raw->jvc;
  41 
  42         if (!is_timing_event(ev)) {
  43                 if (ev.reset)
  44                         data->state = STATE_INACTIVE;
  45                 return 0;
  46         }
  47 
  48         if (!geq_margin(ev.duration, JVC_UNIT, JVC_UNIT / 2))
  49                 goto out;
  50 
  51         dev_dbg(&dev->dev, "JVC decode started at state %d (%uus %s)\n",
  52                 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
  53 
  54 again:
  55         switch (data->state) {
  56 
  57         case STATE_INACTIVE:
  58                 if (!ev.pulse)
  59                         break;
  60 
  61                 if (!eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
  62                         break;
  63 
  64                 data->count = 0;
  65                 data->first = true;
  66                 data->toggle = !data->toggle;
  67                 data->state = STATE_HEADER_SPACE;
  68                 return 0;
  69 
  70         case STATE_HEADER_SPACE:
  71                 if (ev.pulse)
  72                         break;
  73 
  74                 if (!eq_margin(ev.duration, JVC_HEADER_SPACE, JVC_UNIT / 2))
  75                         break;
  76 
  77                 data->state = STATE_BIT_PULSE;
  78                 return 0;
  79 
  80         case STATE_BIT_PULSE:
  81                 if (!ev.pulse)
  82                         break;
  83 
  84                 if (!eq_margin(ev.duration, JVC_BIT_PULSE, JVC_UNIT / 2))
  85                         break;
  86 
  87                 data->state = STATE_BIT_SPACE;
  88                 return 0;
  89 
  90         case STATE_BIT_SPACE:
  91                 if (ev.pulse)
  92                         break;
  93 
  94                 data->bits <<= 1;
  95                 if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) {
  96                         data->bits |= 1;
  97                         decrease_duration(&ev, JVC_BIT_1_SPACE);
  98                 } else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2))
  99                         decrease_duration(&ev, JVC_BIT_0_SPACE);
 100                 else
 101                         break;
 102                 data->count++;
 103 
 104                 if (data->count == JVC_NBITS)
 105                         data->state = STATE_TRAILER_PULSE;
 106                 else
 107                         data->state = STATE_BIT_PULSE;
 108                 return 0;
 109 
 110         case STATE_TRAILER_PULSE:
 111                 if (!ev.pulse)
 112                         break;
 113 
 114                 if (!eq_margin(ev.duration, JVC_TRAILER_PULSE, JVC_UNIT / 2))
 115                         break;
 116 
 117                 data->state = STATE_TRAILER_SPACE;
 118                 return 0;
 119 
 120         case STATE_TRAILER_SPACE:
 121                 if (ev.pulse)
 122                         break;
 123 
 124                 if (!geq_margin(ev.duration, JVC_TRAILER_SPACE, JVC_UNIT / 2))
 125                         break;
 126 
 127                 if (data->first) {
 128                         u32 scancode;
 129                         scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
 130                                    (bitrev8((data->bits >> 0) & 0xff) << 0);
 131                         dev_dbg(&dev->dev, "JVC scancode 0x%04x\n", scancode);
 132                         rc_keydown(dev, RC_PROTO_JVC, scancode, data->toggle);
 133                         data->first = false;
 134                         data->old_bits = data->bits;
 135                 } else if (data->bits == data->old_bits) {
 136                         dev_dbg(&dev->dev, "JVC repeat\n");
 137                         rc_repeat(dev);
 138                 } else {
 139                         dev_dbg(&dev->dev, "JVC invalid repeat msg\n");
 140                         break;
 141                 }
 142 
 143                 data->count = 0;
 144                 data->state = STATE_CHECK_REPEAT;
 145                 return 0;
 146 
 147         case STATE_CHECK_REPEAT:
 148                 if (!ev.pulse)
 149                         break;
 150 
 151                 if (eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
 152                         data->state = STATE_INACTIVE;
 153   else
 154                         data->state = STATE_BIT_PULSE;
 155                 goto again;
 156         }
 157 
 158 out:
 159         dev_dbg(&dev->dev, "JVC decode failed at state %d (%uus %s)\n",
 160                 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
 161         data->state = STATE_INACTIVE;
 162         return -EINVAL;
 163 }
 164 
 165 static const struct ir_raw_timings_pd ir_jvc_timings = {
 166         .header_pulse  = JVC_HEADER_PULSE,
 167         .header_space  = JVC_HEADER_SPACE,
 168         .bit_pulse     = JVC_BIT_PULSE,
 169         .bit_space[0]  = JVC_BIT_0_SPACE,
 170         .bit_space[1]  = JVC_BIT_1_SPACE,
 171         .trailer_pulse = JVC_TRAILER_PULSE,
 172         .trailer_space = JVC_TRAILER_SPACE,
 173         .msb_first     = 1,
 174 };
 175 
 176 /**
 177  * ir_jvc_encode() - Encode a scancode as a stream of raw events
 178  *
 179  * @protocol:   protocol to encode
 180  * @scancode:   scancode to encode
 181  * @events:     array of raw ir events to write into
 182  * @max:        maximum size of @events
 183  *
 184  * Returns:     The number of events written.
 185  *              -ENOBUFS if there isn't enough space in the array to fit the
 186  *              encoding. In this case all @max events will have been written.
 187  */
 188 static int ir_jvc_encode(enum rc_proto protocol, u32 scancode,
 189                          struct ir_raw_event *events, unsigned int max)
 190 {
 191         struct ir_raw_event *e = events;
 192         int ret;
 193         u32 raw = (bitrev8((scancode >> 8) & 0xff) << 8) |
 194                   (bitrev8((scancode >> 0) & 0xff) << 0);
 195 
 196         ret = ir_raw_gen_pd(&e, max, &ir_jvc_timings, JVC_NBITS, raw);
 197         if (ret < 0)
 198                 return ret;
 199 
 200         return e - events;
 201 }
 202 
 203 static struct ir_raw_handler jvc_handler = {
 204         .protocols      = RC_PROTO_BIT_JVC,
 205         .decode         = ir_jvc_decode,
 206         .encode         = ir_jvc_encode,
 207         .carrier        = 38000,
 208         .min_timeout    = JVC_TRAILER_SPACE,
 209 };
 210 
 211 static int __init ir_jvc_decode_init(void)
 212 {
 213         ir_raw_handler_register(&jvc_handler);
 214 
 215         printk(KERN_INFO "IR JVC protocol handler initialized\n");
 216         return 0;
 217 }
 218 
 219 static void __exit ir_jvc_decode_exit(void)
 220 {
 221         ir_raw_handler_unregister(&jvc_handler);
 222 }
 223 
 224 module_init(ir_jvc_decode_init);
 225 module_exit(ir_jvc_decode_exit);
 226 
 227 MODULE_LICENSE("GPL");
 228 MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
 229 MODULE_DESCRIPTION("JVC IR protocol decoder");

/* [<][>][^][v][top][bottom][index][help] */