ir-rcmm-decoder.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. // SPDX-License-Identifier: GPL-2.0+
  2. // ir-rcmm-decoder.c - A decoder for the RCMM IR protocol
  3. //
  4. // Copyright (C) 2018 by Patrick Lerda <patrick9876@free.fr>
  5. #include "rc-core-priv.h"
  6. #include <linux/module.h>
  7. #define RCMM_UNIT 166 /* microseconds */
  8. #define RCMM_PREFIX_PULSE 417 /* 166.666666666666*2.5 */
  9. #define RCMM_PULSE_0 278 /* 166.666666666666*(1+2/3) */
  10. #define RCMM_PULSE_1 444 /* 166.666666666666*(2+2/3) */
  11. #define RCMM_PULSE_2 611 /* 166.666666666666*(3+2/3) */
  12. #define RCMM_PULSE_3 778 /* 166.666666666666*(4+2/3) */
  13. enum rcmm_state {
  14. STATE_INACTIVE,
  15. STATE_LOW,
  16. STATE_BUMP,
  17. STATE_VALUE,
  18. STATE_FINISHED,
  19. };
  20. static bool rcmm_mode(const struct rcmm_dec *data)
  21. {
  22. return !((0x000c0000 & data->bits) == 0x000c0000);
  23. }
  24. static int rcmm_miscmode(struct rc_dev *dev, struct rcmm_dec *data)
  25. {
  26. switch (data->count) {
  27. case 24:
  28. if (dev->enabled_protocols & RC_PROTO_BIT_RCMM24) {
  29. rc_keydown(dev, RC_PROTO_RCMM24, data->bits, 0);
  30. data->state = STATE_INACTIVE;
  31. return 0;
  32. }
  33. return -1;
  34. case 12:
  35. if (dev->enabled_protocols & RC_PROTO_BIT_RCMM12) {
  36. rc_keydown(dev, RC_PROTO_RCMM12, data->bits, 0);
  37. data->state = STATE_INACTIVE;
  38. return 0;
  39. }
  40. return -1;
  41. }
  42. return -1;
  43. }
  44. /**
  45. * ir_rcmm_decode() - Decode one RCMM pulse or space
  46. * @dev: the struct rc_dev descriptor of the device
  47. * @ev: the struct ir_raw_event descriptor of the pulse/space
  48. *
  49. * This function returns -EINVAL if the pulse violates the state machine
  50. */
  51. static int ir_rcmm_decode(struct rc_dev *dev, struct ir_raw_event ev)
  52. {
  53. struct rcmm_dec *data = &dev->raw->rcmm;
  54. u32 scancode;
  55. u8 toggle;
  56. int value;
  57. if (!(dev->enabled_protocols & (RC_PROTO_BIT_RCMM32 |
  58. RC_PROTO_BIT_RCMM24 |
  59. RC_PROTO_BIT_RCMM12)))
  60. return 0;
  61. if (!is_timing_event(ev)) {
  62. if (ev.reset)
  63. data->state = STATE_INACTIVE;
  64. return 0;
  65. }
  66. switch (data->state) {
  67. case STATE_INACTIVE:
  68. if (!ev.pulse)
  69. break;
  70. if (!eq_margin(ev.duration, RCMM_PREFIX_PULSE, RCMM_UNIT))
  71. break;
  72. data->state = STATE_LOW;
  73. data->count = 0;
  74. data->bits = 0;
  75. return 0;
  76. case STATE_LOW:
  77. if (ev.pulse)
  78. break;
  79. if (!eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT))
  80. break;
  81. data->state = STATE_BUMP;
  82. return 0;
  83. case STATE_BUMP:
  84. if (!ev.pulse)
  85. break;
  86. if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
  87. break;
  88. data->state = STATE_VALUE;
  89. return 0;
  90. case STATE_VALUE:
  91. if (ev.pulse)
  92. break;
  93. if (eq_margin(ev.duration, RCMM_PULSE_0, RCMM_UNIT / 2))
  94. value = 0;
  95. else if (eq_margin(ev.duration, RCMM_PULSE_1, RCMM_UNIT / 2))
  96. value = 1;
  97. else if (eq_margin(ev.duration, RCMM_PULSE_2, RCMM_UNIT / 2))
  98. value = 2;
  99. else if (eq_margin(ev.duration, RCMM_PULSE_3, RCMM_UNIT / 2))
  100. value = 3;
  101. else
  102. value = -1;
  103. if (value == -1) {
  104. if (!rcmm_miscmode(dev, data))
  105. return 0;
  106. break;
  107. }
  108. data->bits <<= 2;
  109. data->bits |= value;
  110. data->count += 2;
  111. if (data->count < 32)
  112. data->state = STATE_BUMP;
  113. else
  114. data->state = STATE_FINISHED;
  115. return 0;
  116. case STATE_FINISHED:
  117. if (!ev.pulse)
  118. break;
  119. if (!eq_margin(ev.duration, RCMM_UNIT, RCMM_UNIT / 2))
  120. break;
  121. if (rcmm_mode(data)) {
  122. toggle = !!(0x8000 & data->bits);
  123. scancode = data->bits & ~0x8000;
  124. } else {
  125. toggle = 0;
  126. scancode = data->bits;
  127. }
  128. if (dev->enabled_protocols & RC_PROTO_BIT_RCMM32) {
  129. rc_keydown(dev, RC_PROTO_RCMM32, scancode, toggle);
  130. data->state = STATE_INACTIVE;
  131. return 0;
  132. }
  133. break;
  134. }
  135. dev_dbg(&dev->dev, "RC-MM decode failed at count %d state %d (%uus %s)\n",
  136. data->count, data->state, ev.duration, TO_STR(ev.pulse));
  137. data->state = STATE_INACTIVE;
  138. return -EINVAL;
  139. }
  140. static const int rcmmspace[] = {
  141. RCMM_PULSE_0,
  142. RCMM_PULSE_1,
  143. RCMM_PULSE_2,
  144. RCMM_PULSE_3,
  145. };
  146. static int ir_rcmm_rawencoder(struct ir_raw_event **ev, unsigned int max,
  147. unsigned int n, u32 data)
  148. {
  149. int i;
  150. int ret;
  151. ret = ir_raw_gen_pulse_space(ev, &max, RCMM_PREFIX_PULSE, RCMM_PULSE_0);
  152. if (ret)
  153. return ret;
  154. for (i = n - 2; i >= 0; i -= 2) {
  155. const unsigned int space = rcmmspace[(data >> i) & 3];
  156. ret = ir_raw_gen_pulse_space(ev, &max, RCMM_UNIT, space);
  157. if (ret)
  158. return ret;
  159. }
  160. return ir_raw_gen_pulse_space(ev, &max, RCMM_UNIT, RCMM_PULSE_3 * 2);
  161. }
  162. static int ir_rcmm_encode(enum rc_proto protocol, u32 scancode,
  163. struct ir_raw_event *events, unsigned int max)
  164. {
  165. struct ir_raw_event *e = events;
  166. int ret;
  167. switch (protocol) {
  168. case RC_PROTO_RCMM32:
  169. ret = ir_rcmm_rawencoder(&e, max, 32, scancode);
  170. break;
  171. case RC_PROTO_RCMM24:
  172. ret = ir_rcmm_rawencoder(&e, max, 24, scancode);
  173. break;
  174. case RC_PROTO_RCMM12:
  175. ret = ir_rcmm_rawencoder(&e, max, 12, scancode);
  176. break;
  177. default:
  178. ret = -EINVAL;
  179. }
  180. if (ret < 0)
  181. return ret;
  182. return e - events;
  183. }
  184. static struct ir_raw_handler rcmm_handler = {
  185. .protocols = RC_PROTO_BIT_RCMM32 |
  186. RC_PROTO_BIT_RCMM24 |
  187. RC_PROTO_BIT_RCMM12,
  188. .decode = ir_rcmm_decode,
  189. .encode = ir_rcmm_encode,
  190. .carrier = 36000,
  191. .min_timeout = RCMM_PULSE_3 + RCMM_UNIT,
  192. };
  193. static int __init ir_rcmm_decode_init(void)
  194. {
  195. ir_raw_handler_register(&rcmm_handler);
  196. pr_info("IR RCMM protocol handler initialized\n");
  197. return 0;
  198. }
  199. static void __exit ir_rcmm_decode_exit(void)
  200. {
  201. ir_raw_handler_unregister(&rcmm_handler);
  202. }
  203. module_init(ir_rcmm_decode_init);
  204. module_exit(ir_rcmm_decode_exit);
  205. MODULE_LICENSE("GPL");
  206. MODULE_AUTHOR("Patrick Lerda");
  207. MODULE_DESCRIPTION("RCMM IR protocol decoder");