ir-rcmm-decoder.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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 166667 /* nanosecs */
  8. #define RCMM_PREFIX_PULSE 416666 /* 166666.666666666*2.5 */
  9. #define RCMM_PULSE_0 277777 /* 166666.666666666*(1+2/3) */
  10. #define RCMM_PULSE_1 444444 /* 166666.666666666*(2+2/3) */
  11. #define RCMM_PULSE_2 611111 /* 166666.666666666*(3+2/3) */
  12. #define RCMM_PULSE_3 777778 /* 166666.666666666*(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 / 2))
  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 / 2))
  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. data->state = STATE_INACTIVE;
  136. return -EINVAL;
  137. }
  138. static const int rcmmspace[] = {
  139. RCMM_PULSE_0,
  140. RCMM_PULSE_1,
  141. RCMM_PULSE_2,
  142. RCMM_PULSE_3,
  143. };
  144. static int ir_rcmm_rawencoder(struct ir_raw_event **ev, unsigned int max,
  145. unsigned int n, u32 data)
  146. {
  147. int i;
  148. int ret;
  149. ret = ir_raw_gen_pulse_space(ev, &max, RCMM_PREFIX_PULSE, RCMM_PULSE_0);
  150. if (ret)
  151. return ret;
  152. for (i = n - 2; i >= 0; i -= 2) {
  153. const unsigned int space = rcmmspace[(data >> i) & 3];
  154. ret = ir_raw_gen_pulse_space(ev, &max, RCMM_UNIT, space);
  155. if (ret)
  156. return ret;
  157. }
  158. return ir_raw_gen_pulse_space(ev, &max, RCMM_UNIT, RCMM_PULSE_3 * 2);
  159. }
  160. static int ir_rcmm_encode(enum rc_proto protocol, u32 scancode,
  161. struct ir_raw_event *events, unsigned int max)
  162. {
  163. struct ir_raw_event *e = events;
  164. int ret;
  165. switch (protocol) {
  166. case RC_PROTO_RCMM32:
  167. ret = ir_rcmm_rawencoder(&e, max, 32, scancode);
  168. break;
  169. case RC_PROTO_RCMM24:
  170. ret = ir_rcmm_rawencoder(&e, max, 24, scancode);
  171. break;
  172. case RC_PROTO_RCMM12:
  173. ret = ir_rcmm_rawencoder(&e, max, 12, scancode);
  174. break;
  175. default:
  176. ret = -EINVAL;
  177. }
  178. if (ret < 0)
  179. return ret;
  180. return e - events;
  181. }
  182. static struct ir_raw_handler rcmm_handler = {
  183. .protocols = RC_PROTO_BIT_RCMM32 |
  184. RC_PROTO_BIT_RCMM24 |
  185. RC_PROTO_BIT_RCMM12,
  186. .decode = ir_rcmm_decode,
  187. .encode = ir_rcmm_encode,
  188. .carrier = 36000,
  189. .min_timeout = RCMM_PULSE_3 + RCMM_UNIT,
  190. };
  191. static int __init ir_rcmm_decode_init(void)
  192. {
  193. ir_raw_handler_register(&rcmm_handler);
  194. pr_info("IR RCMM protocol handler initialized\n");
  195. return 0;
  196. }
  197. static void __exit ir_rcmm_decode_exit(void)
  198. {
  199. ir_raw_handler_unregister(&rcmm_handler);
  200. }
  201. module_init(ir_rcmm_decode_init);
  202. module_exit(ir_rcmm_decode_exit);
  203. MODULE_LICENSE("GPL");
  204. MODULE_AUTHOR("Patrick Lerda");
  205. MODULE_DESCRIPTION("RCMM IR protocol decoder");