Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ir-mce_kbd-decoder.c
Go to the documentation of this file.
1 /* ir-mce_kbd-decoder.c - A decoder for the RC6-ish keyboard/mouse IR protocol
2  * used by the Microsoft Remote Keyboard for Windows Media Center Edition,
3  * referred to by Microsoft's Windows Media Center remote specification docs
4  * as "an internal protocol called MCIR-2".
5  *
6  * Copyright (C) 2011 by Jarod Wilson <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation version 2 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  */
17 #include <linux/module.h>
18 
19 #include "rc-core-priv.h"
20 
21 /*
22  * This decoder currently supports:
23  * - MCIR-2 29-bit IR signals used for mouse movement and buttons
24  * - MCIR-2 32-bit IR signals used for standard keyboard keys
25  *
26  * The media keys on the keyboard send RC-6 signals that are inditinguishable
27  * from the keys of the same name on the stock MCE remote, and will be handled
28  * by the standard RC-6 decoder, and be made available to the system via the
29  * input device for the remote, rather than the keyboard/mouse one.
30  */
31 
32 #define MCIR2_UNIT 333333 /* ns */
33 #define MCIR2_HEADER_NBITS 5
34 #define MCIR2_MOUSE_NBITS 29
35 #define MCIR2_KEYBOARD_NBITS 32
36 #define MCIR2_PREFIX_PULSE (8 * MCIR2_UNIT)
37 #define MCIR2_PREFIX_SPACE (1 * MCIR2_UNIT)
38 #define MCIR2_MAX_LEN (3 * MCIR2_UNIT)
39 #define MCIR2_BIT_START (1 * MCIR2_UNIT)
40 #define MCIR2_BIT_END (1 * MCIR2_UNIT)
41 #define MCIR2_BIT_0 (1 * MCIR2_UNIT)
42 #define MCIR2_BIT_SET (2 * MCIR2_UNIT)
43 #define MCIR2_MODE_MASK 0xf /* for the header bits */
44 #define MCIR2_KEYBOARD_HEADER 0x4
45 #define MCIR2_MOUSE_HEADER 0x1
46 #define MCIR2_MASK_KEYS_START 0xe0
47 
52 };
53 
61 };
62 
63 static unsigned char kbd_keycodes[256] = {
115  KEY_RESERVED
116 };
117 
118 static void mce_kbd_rx_timeout(unsigned long data)
119 {
120  struct mce_kbd_dec *mce_kbd = (struct mce_kbd_dec *)data;
121  int i;
122  unsigned char maskcode;
123 
124  IR_dprintk(2, "timer callback clearing all keys\n");
125 
126  for (i = 0; i < 7; i++) {
127  maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
128  input_report_key(mce_kbd->idev, maskcode, 0);
129  }
130 
131  for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
132  input_report_key(mce_kbd->idev, kbd_keycodes[i], 0);
133 }
134 
135 static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data)
136 {
137  switch (data->header & MCIR2_MODE_MASK) {
139  return MCIR2_MODE_KEYBOARD;
140  case MCIR2_MOUSE_HEADER:
141  return MCIR2_MODE_MOUSE;
142  default:
143  return MCIR2_MODE_UNKNOWN;
144  }
145 }
146 
147 static void ir_mce_kbd_process_keyboard_data(struct input_dev *idev,
148  u32 scancode)
149 {
150  u8 keydata = (scancode >> 8) & 0xff;
151  u8 shiftmask = scancode & 0xff;
152  unsigned char keycode, maskcode;
153  int i, keystate;
154 
155  IR_dprintk(1, "keyboard: keydata = 0x%02x, shiftmask = 0x%02x\n",
156  keydata, shiftmask);
157 
158  for (i = 0; i < 7; i++) {
159  maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
160  if (shiftmask & (1 << i))
161  keystate = 1;
162  else
163  keystate = 0;
164  input_report_key(idev, maskcode, keystate);
165  }
166 
167  if (keydata) {
168  keycode = kbd_keycodes[keydata];
169  input_report_key(idev, keycode, 1);
170  } else {
171  for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
172  input_report_key(idev, kbd_keycodes[i], 0);
173  }
174 }
175 
176 static void ir_mce_kbd_process_mouse_data(struct input_dev *idev, u32 scancode)
177 {
178  /* raw mouse coordinates */
179  u8 xdata = (scancode >> 7) & 0x7f;
180  u8 ydata = (scancode >> 14) & 0x7f;
181  int x, y;
182  /* mouse buttons */
183  bool right = scancode & 0x40;
184  bool left = scancode & 0x20;
185 
186  if (xdata & 0x40)
187  x = -((~xdata & 0x7f) + 1);
188  else
189  x = xdata;
190 
191  if (ydata & 0x40)
192  y = -((~ydata & 0x7f) + 1);
193  else
194  y = ydata;
195 
196  IR_dprintk(1, "mouse: x = %d, y = %d, btns = %s%s\n",
197  x, y, left ? "L" : "", right ? "R" : "");
198 
199  input_report_rel(idev, REL_X, x);
200  input_report_rel(idev, REL_Y, y);
201 
202  input_report_key(idev, BTN_LEFT, left);
203  input_report_key(idev, BTN_RIGHT, right);
204 }
205 
213 static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
214 {
215  struct mce_kbd_dec *data = &dev->raw->mce_kbd;
216  u32 scancode;
217  unsigned long delay;
218 
219  if (!(dev->raw->enabled_protocols & RC_TYPE_MCE_KBD))
220  return 0;
221 
222  if (!is_timing_event(ev)) {
223  if (ev.reset)
224  data->state = STATE_INACTIVE;
225  return 0;
226  }
227 
228  if (!geq_margin(ev.duration, MCIR2_UNIT, MCIR2_UNIT / 2))
229  goto out;
230 
231 again:
232  IR_dprintk(2, "started at state %i (%uus %s)\n",
233  data->state, TO_US(ev.duration), TO_STR(ev.pulse));
234 
235  if (!geq_margin(ev.duration, MCIR2_UNIT, MCIR2_UNIT / 2))
236  return 0;
237 
238  switch (data->state) {
239 
240  case STATE_INACTIVE:
241  if (!ev.pulse)
242  break;
243 
244  /* Note: larger margin on first pulse since each MCIR2_UNIT
245  is quite short and some hardware takes some time to
246  adjust to the signal */
247  if (!eq_margin(ev.duration, MCIR2_PREFIX_PULSE, MCIR2_UNIT))
248  break;
249 
250  data->state = STATE_HEADER_BIT_START;
251  data->count = 0;
252  data->header = 0;
253  return 0;
254 
256  if (geq_margin(ev.duration, MCIR2_MAX_LEN, MCIR2_UNIT / 2))
257  break;
258 
259  data->header <<= 1;
260  if (ev.pulse)
261  data->header |= 1;
262  data->count++;
263  data->state = STATE_HEADER_BIT_END;
264  return 0;
265 
267  if (!is_transition(&ev, &dev->raw->prev_ev))
268  break;
269 
270  decrease_duration(&ev, MCIR2_BIT_END);
271 
272  if (data->count != MCIR2_HEADER_NBITS) {
273  data->state = STATE_HEADER_BIT_START;
274  goto again;
275  }
276 
277  switch (mce_kbd_mode(data)) {
278  case MCIR2_MODE_KEYBOARD:
279  data->wanted_bits = MCIR2_KEYBOARD_NBITS;
280  break;
281  case MCIR2_MODE_MOUSE:
282  data->wanted_bits = MCIR2_MOUSE_NBITS;
283  break;
284  default:
285  IR_dprintk(1, "not keyboard or mouse data\n");
286  goto out;
287  }
288 
289  data->count = 0;
290  data->body = 0;
291  data->state = STATE_BODY_BIT_START;
292  goto again;
293 
295  if (geq_margin(ev.duration, MCIR2_MAX_LEN, MCIR2_UNIT / 2))
296  break;
297 
298  data->body <<= 1;
299  if (ev.pulse)
300  data->body |= 1;
301  data->count++;
302  data->state = STATE_BODY_BIT_END;
303  return 0;
304 
305  case STATE_BODY_BIT_END:
306  if (!is_transition(&ev, &dev->raw->prev_ev))
307  break;
308 
309  if (data->count == data->wanted_bits)
310  data->state = STATE_FINISHED;
311  else
312  data->state = STATE_BODY_BIT_START;
313 
314  decrease_duration(&ev, MCIR2_BIT_END);
315  goto again;
316 
317  case STATE_FINISHED:
318  if (ev.pulse)
319  break;
320 
321  switch (data->wanted_bits) {
323  scancode = data->body & 0xffff;
324  IR_dprintk(1, "keyboard data 0x%08x\n", data->body);
325  if (dev->timeout)
326  delay = usecs_to_jiffies(dev->timeout / 1000);
327  else
328  delay = msecs_to_jiffies(100);
329  mod_timer(&data->rx_timeout, jiffies + delay);
330  /* Pass data to keyboard buffer parser */
331  ir_mce_kbd_process_keyboard_data(data->idev, scancode);
332  break;
333  case MCIR2_MOUSE_NBITS:
334  scancode = data->body & 0x1fffff;
335  IR_dprintk(1, "mouse data 0x%06x\n", scancode);
336  /* Pass data to mouse buffer parser */
337  ir_mce_kbd_process_mouse_data(data->idev, scancode);
338  break;
339  default:
340  IR_dprintk(1, "not keyboard or mouse data\n");
341  goto out;
342  }
343 
344  data->state = STATE_INACTIVE;
345  input_sync(data->idev);
346  return 0;
347  }
348 
349 out:
350  IR_dprintk(1, "failed at state %i (%uus %s)\n",
351  data->state, TO_US(ev.duration), TO_STR(ev.pulse));
352  data->state = STATE_INACTIVE;
353  input_sync(data->idev);
354  return -EINVAL;
355 }
356 
357 static int ir_mce_kbd_register(struct rc_dev *dev)
358 {
359  struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd;
360  struct input_dev *idev;
361  int i, ret;
362 
363  idev = input_allocate_device();
364  if (!idev)
365  return -ENOMEM;
366 
367  snprintf(mce_kbd->name, sizeof(mce_kbd->name),
368  "MCE IR Keyboard/Mouse (%s)", dev->driver_name);
369  strlcat(mce_kbd->phys, "/input0", sizeof(mce_kbd->phys));
370 
371  idev->name = mce_kbd->name;
372  idev->phys = mce_kbd->phys;
373 
374  /* Keyboard bits */
375  set_bit(EV_KEY, idev->evbit);
376  set_bit(EV_REP, idev->evbit);
377  for (i = 0; i < sizeof(kbd_keycodes); i++)
378  set_bit(kbd_keycodes[i], idev->keybit);
379 
380  /* Mouse bits */
381  set_bit(EV_REL, idev->evbit);
382  set_bit(REL_X, idev->relbit);
383  set_bit(REL_Y, idev->relbit);
384  set_bit(BTN_LEFT, idev->keybit);
385  set_bit(BTN_RIGHT, idev->keybit);
386 
387  /* Report scancodes too */
388  set_bit(EV_MSC, idev->evbit);
389  set_bit(MSC_SCAN, idev->mscbit);
390 
391  setup_timer(&mce_kbd->rx_timeout, mce_kbd_rx_timeout,
392  (unsigned long)mce_kbd);
393 
394  input_set_drvdata(idev, mce_kbd);
395 
396 #if 0
397  /* Adding this reference means two input devices are associated with
398  * this rc-core device, which ir-keytable doesn't cope with yet */
399  idev->dev.parent = &dev->dev;
400 #endif
401 
402  ret = input_register_device(idev);
403  if (ret < 0) {
404  input_free_device(idev);
405  return -EIO;
406  }
407 
408  mce_kbd->idev = idev;
409 
410  return 0;
411 }
412 
413 static int ir_mce_kbd_unregister(struct rc_dev *dev)
414 {
415  struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd;
416  struct input_dev *idev = mce_kbd->idev;
417 
418  del_timer_sync(&mce_kbd->rx_timeout);
419  input_unregister_device(idev);
420 
421  return 0;
422 }
423 
424 static struct ir_raw_handler mce_kbd_handler = {
425  .protocols = RC_TYPE_MCE_KBD,
426  .decode = ir_mce_kbd_decode,
427  .raw_register = ir_mce_kbd_register,
428  .raw_unregister = ir_mce_kbd_unregister,
429 };
430 
431 static int __init ir_mce_kbd_decode_init(void)
432 {
433  ir_raw_handler_register(&mce_kbd_handler);
434 
435  printk(KERN_INFO "IR MCE Keyboard/mouse protocol handler initialized\n");
436  return 0;
437 }
438 
439 static void __exit ir_mce_kbd_decode_exit(void)
440 {
441  ir_raw_handler_unregister(&mce_kbd_handler);
442 }
443 
444 module_init(ir_mce_kbd_decode_init);
445 module_exit(ir_mce_kbd_decode_exit);
446 
447 MODULE_LICENSE("GPL");
448 MODULE_AUTHOR("Jarod Wilson <[email protected]>");
449 MODULE_DESCRIPTION("MCE Keyboard/mouse IR protocol decoder");