ir-rc5-decoder.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol
  2. *
  3. * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation version 2 of the License.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. /*
  15. * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols.
  16. * There are other variants that use a different number of bits.
  17. * This is currently unsupported.
  18. * It considers a carrier of 36 kHz, with a total of 14/20 bits, where
  19. * the first two bits are start bits, and a third one is a filing bit
  20. */
  21. #include "ir-core-priv.h"
  22. #define RC5_NBITS 14
  23. #define RC5X_NBITS 20
  24. #define CHECK_RC5X_NBITS 8
  25. #define RC5X_SPACE SPACE(4)
  26. #define RC5_UNIT 888888 /* ns */
  27. /* Used to register rc5_decoder clients */
  28. static LIST_HEAD(decoder_list);
  29. static DEFINE_SPINLOCK(decoder_lock);
  30. enum rc5_state {
  31. STATE_INACTIVE,
  32. STATE_BIT_START,
  33. STATE_BIT_END,
  34. STATE_CHECK_RC5X,
  35. STATE_FINISHED,
  36. };
  37. struct decoder_data {
  38. struct list_head list;
  39. struct ir_input_dev *ir_dev;
  40. int enabled:1;
  41. /* State machine control */
  42. enum rc5_state state;
  43. u32 rc5_bits;
  44. int last_unit;
  45. unsigned count;
  46. unsigned wanted_bits;
  47. };
  48. /**
  49. * get_decoder_data() - gets decoder data
  50. * @input_dev: input device
  51. *
  52. * Returns the struct decoder_data that corresponds to a device
  53. */
  54. static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
  55. {
  56. struct decoder_data *data = NULL;
  57. spin_lock(&decoder_lock);
  58. list_for_each_entry(data, &decoder_list, list) {
  59. if (data->ir_dev == ir_dev)
  60. break;
  61. }
  62. spin_unlock(&decoder_lock);
  63. return data;
  64. }
  65. static ssize_t store_enabled(struct device *d,
  66. struct device_attribute *mattr,
  67. const char *buf,
  68. size_t len)
  69. {
  70. unsigned long value;
  71. struct ir_input_dev *ir_dev = dev_get_drvdata(d);
  72. struct decoder_data *data = get_decoder_data(ir_dev);
  73. if (!data)
  74. return -EINVAL;
  75. if (strict_strtoul(buf, 10, &value) || value > 1)
  76. return -EINVAL;
  77. data->enabled = value;
  78. return len;
  79. }
  80. static ssize_t show_enabled(struct device *d,
  81. struct device_attribute *mattr, char *buf)
  82. {
  83. struct ir_input_dev *ir_dev = dev_get_drvdata(d);
  84. struct decoder_data *data = get_decoder_data(ir_dev);
  85. if (!data)
  86. return -EINVAL;
  87. if (data->enabled)
  88. return sprintf(buf, "1\n");
  89. else
  90. return sprintf(buf, "0\n");
  91. }
  92. static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
  93. static struct attribute *decoder_attributes[] = {
  94. &dev_attr_enabled.attr,
  95. NULL
  96. };
  97. static struct attribute_group decoder_attribute_group = {
  98. .name = "rc5_decoder",
  99. .attrs = decoder_attributes,
  100. };
  101. /**
  102. * ir_rc5_decode() - Decode one RC-5 pulse or space
  103. * @input_dev: the struct input_dev descriptor of the device
  104. * @duration: duration of pulse/space in ns
  105. *
  106. * This function returns -EINVAL if the pulse violates the state machine
  107. */
  108. static int ir_rc5_decode(struct input_dev *input_dev, s64 duration)
  109. {
  110. struct decoder_data *data;
  111. struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
  112. u8 toggle;
  113. u32 scancode;
  114. int u;
  115. data = get_decoder_data(ir_dev);
  116. if (!data)
  117. return -EINVAL;
  118. if (!data->enabled)
  119. return 0;
  120. if (IS_RESET(duration)) {
  121. data->state = STATE_INACTIVE;
  122. return 0;
  123. }
  124. u = TO_UNITS(duration, RC5_UNIT);
  125. if (DURATION(u) == 0)
  126. goto out;
  127. again:
  128. IR_dprintk(2, "RC5(x) decode started at state %i (%i units, %ius)\n",
  129. data->state, u, TO_US(duration));
  130. if (DURATION(u) == 0 && data->state != STATE_FINISHED)
  131. return 0;
  132. switch (data->state) {
  133. case STATE_INACTIVE:
  134. if (IS_PULSE(u)) {
  135. data->state = STATE_BIT_START;
  136. data->count = 1;
  137. /* We just need enough bits to get to STATE_CHECK_RC5X */
  138. data->wanted_bits = RC5X_NBITS;
  139. DECREASE_DURATION(u, 1);
  140. goto again;
  141. }
  142. break;
  143. case STATE_BIT_START:
  144. if (DURATION(u) == 1) {
  145. data->rc5_bits <<= 1;
  146. if (IS_SPACE(u))
  147. data->rc5_bits |= 1;
  148. data->count++;
  149. data->last_unit = u;
  150. /*
  151. * If the last bit is zero, a space will merge
  152. * with the silence after the command.
  153. */
  154. if (IS_PULSE(u) && data->count == data->wanted_bits) {
  155. data->state = STATE_FINISHED;
  156. goto again;
  157. }
  158. data->state = STATE_BIT_END;
  159. return 0;
  160. }
  161. break;
  162. case STATE_BIT_END:
  163. if (IS_TRANSITION(u, data->last_unit)) {
  164. if (data->count == data->wanted_bits)
  165. data->state = STATE_FINISHED;
  166. else if (data->count == CHECK_RC5X_NBITS)
  167. data->state = STATE_CHECK_RC5X;
  168. else
  169. data->state = STATE_BIT_START;
  170. DECREASE_DURATION(u, 1);
  171. goto again;
  172. }
  173. break;
  174. case STATE_CHECK_RC5X:
  175. if (IS_SPACE(u) && DURATION(u) >= DURATION(RC5X_SPACE)) {
  176. /* RC5X */
  177. data->wanted_bits = RC5X_NBITS;
  178. DECREASE_DURATION(u, DURATION(RC5X_SPACE));
  179. } else {
  180. /* RC5 */
  181. data->wanted_bits = RC5_NBITS;
  182. }
  183. data->state = STATE_BIT_START;
  184. goto again;
  185. case STATE_FINISHED:
  186. if (data->wanted_bits == RC5X_NBITS) {
  187. /* RC5X */
  188. u8 xdata, command, system;
  189. xdata = (data->rc5_bits & 0x0003F) >> 0;
  190. command = (data->rc5_bits & 0x00FC0) >> 6;
  191. system = (data->rc5_bits & 0x1F000) >> 12;
  192. toggle = (data->rc5_bits & 0x20000) ? 1 : 0;
  193. command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
  194. scancode = system << 16 | command << 8 | xdata;
  195. IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
  196. scancode, toggle);
  197. } else {
  198. /* RC5 */
  199. u8 command, system;
  200. command = (data->rc5_bits & 0x0003F) >> 0;
  201. system = (data->rc5_bits & 0x007C0) >> 6;
  202. toggle = (data->rc5_bits & 0x00800) ? 1 : 0;
  203. command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
  204. scancode = system << 8 | command;
  205. IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
  206. scancode, toggle);
  207. }
  208. ir_keydown(input_dev, scancode, toggle);
  209. data->state = STATE_INACTIVE;
  210. return 0;
  211. }
  212. out:
  213. IR_dprintk(1, "RC5(x) decode failed at state %i (%i units, %ius)\n",
  214. data->state, u, TO_US(duration));
  215. data->state = STATE_INACTIVE;
  216. return -EINVAL;
  217. }
  218. static int ir_rc5_register(struct input_dev *input_dev)
  219. {
  220. struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
  221. struct decoder_data *data;
  222. int rc;
  223. rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
  224. if (rc < 0)
  225. return rc;
  226. data = kzalloc(sizeof(*data), GFP_KERNEL);
  227. if (!data) {
  228. sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
  229. return -ENOMEM;
  230. }
  231. data->ir_dev = ir_dev;
  232. data->enabled = 1;
  233. spin_lock(&decoder_lock);
  234. list_add_tail(&data->list, &decoder_list);
  235. spin_unlock(&decoder_lock);
  236. return 0;
  237. }
  238. static int ir_rc5_unregister(struct input_dev *input_dev)
  239. {
  240. struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
  241. static struct decoder_data *data;
  242. data = get_decoder_data(ir_dev);
  243. if (!data)
  244. return 0;
  245. sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
  246. spin_lock(&decoder_lock);
  247. list_del(&data->list);
  248. spin_unlock(&decoder_lock);
  249. return 0;
  250. }
  251. static struct ir_raw_handler rc5_handler = {
  252. .decode = ir_rc5_decode,
  253. .raw_register = ir_rc5_register,
  254. .raw_unregister = ir_rc5_unregister,
  255. };
  256. static int __init ir_rc5_decode_init(void)
  257. {
  258. ir_raw_handler_register(&rc5_handler);
  259. printk(KERN_INFO "IR RC5(x) protocol handler initialized\n");
  260. return 0;
  261. }
  262. static void __exit ir_rc5_decode_exit(void)
  263. {
  264. ir_raw_handler_unregister(&rc5_handler);
  265. }
  266. module_init(ir_rc5_decode_init);
  267. module_exit(ir_rc5_decode_exit);
  268. MODULE_LICENSE("GPL");
  269. MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
  270. MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
  271. MODULE_DESCRIPTION("RC5(x) IR protocol decoder");