| # Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Keyboard device module to capture keyboard events.""" |
| |
| import fcntl |
| import os |
| import re |
| import sys |
| |
| sys.path.append('../../bin/input') |
| import input_device |
| |
| import mtb |
| |
| from linux_input import EV_KEY |
| |
| |
| class KeyboardDevice: |
| """A class about keyboard device properties.""" |
| TYPE = '(keyboard|chromeos-ec-i2c|cros-ec-spi|cros-ec-i2c)' |
| |
| def __init__(self, device_node=None): |
| self._device_info_file = '/proc/bus/input/devices' |
| self.device_node = (device_node if device_node |
| else self.get_device_node(self.TYPE)) |
| self.system_device = self._non_blocking_open(self.device_node) |
| self._input_event = input_device.InputEvent() |
| |
| def __del__(self): |
| self.system_device.close() |
| |
| def get_device_node(self, device_type): |
| """Get the keyboard device node through device info file. |
| |
| Example of the keyboard device information looks like |
| |
| I: Bus=0011 Vendor=0001 Product=0001 Version=ab41 |
| N: Name="AT Translated Set 2 keyboard" |
| P: Phys=isa0060/serio0/input0 |
| S: Sysfs=/devices/platform/i8042/serio0/input/input5 |
| U: Uniq= |
| H: Handlers=sysrq kbd event5 |
| """ |
| device_node = None |
| device_found = None |
| device_pattern = re.compile('N: Name=.*%s' % device_type, re.I) |
| event_number_pattern = re.compile('H: Handlers=.*event(\d?)', re.I) |
| with open(self._device_info_file) as info: |
| for line in info: |
| if device_found: |
| result = event_number_pattern.search(line) |
| if result: |
| event_number = int(result.group(1)) |
| device_node = '/dev/input/event%d' % event_number |
| break |
| else: |
| device_found = device_pattern.search(line) |
| return device_node |
| |
| def exists(self): |
| """Indicate whether this device exists or not.""" |
| return bool(self.device_node) |
| |
| def _non_blocking_open(self, filename): |
| """Open the system file in the non-blocking mode.""" |
| fd = open(filename) |
| fcntl.fcntl(fd, fcntl.F_SETFL, os.O_NONBLOCK) |
| return fd |
| |
| def _non_blocking_read(self, fd): |
| """Non-blocking read on fd.""" |
| try: |
| self._input_event.read(fd) |
| return self._input_event |
| except Exception: |
| return None |
| |
| def get_key_press_event(self, fd): |
| """Read the keyboard device node to get the key press events.""" |
| event = True |
| # Read the device node continuously until either a key press event |
| # is got or there is no more events to read. |
| while event: |
| event = self._non_blocking_read(fd) |
| if event and event.type == EV_KEY and event.value == 1: |
| return event.code |
| return None |