1# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""Keyboard device module to capture keyboard events.""" 6 7import fcntl 8import os 9import re 10import sys 11 12sys.path.append('../../bin/input') 13import input_device 14 15import mtb 16 17from linux_input import EV_KEY 18 19 20class KeyboardDevice: 21 """A class about keyboard device properties.""" 22 TYPE = '(keyboard|chromeos-ec-i2c|cros-ec-spi|cros-ec-i2c|cros_ec)' 23 24 def __init__(self, device_node=None): 25 self._device_info_file = '/proc/bus/input/devices' 26 self.device_node = (device_node if device_node 27 else self.get_device_node(self.TYPE)) 28 self.system_device = self._non_blocking_open(self.device_node) 29 self._input_event = input_device.InputEvent() 30 31 def __del__(self): 32 self.system_device.close() 33 34 def get_device_node(self, device_type): 35 """Get the keyboard device node through device info file. 36 37 Example of the keyboard device information looks like 38 39 I: Bus=0011 Vendor=0001 Product=0001 Version=ab41 40 N: Name="AT Translated Set 2 keyboard" 41 P: Phys=isa0060/serio0/input0 42 S: Sysfs=/devices/platform/i8042/serio0/input/input5 43 U: Uniq= 44 H: Handlers=sysrq kbd event5 45 """ 46 device_node = None 47 device_found = None 48 device_pattern = re.compile('N: Name=.*%s' % device_type, re.I) 49 event_number_pattern = re.compile('H: Handlers=.*event(\d?)', re.I) 50 with open(self._device_info_file) as info: 51 for line in info: 52 if device_found: 53 result = event_number_pattern.search(line) 54 if result: 55 event_number = int(result.group(1)) 56 device_node = '/dev/input/event%d' % event_number 57 break 58 else: 59 device_found = device_pattern.search(line) 60 return device_node 61 62 def exists(self): 63 """Indicate whether this device exists or not.""" 64 return bool(self.device_node) 65 66 def _non_blocking_open(self, filename): 67 """Open the system file in the non-blocking mode.""" 68 fd = open(filename) 69 fcntl.fcntl(fd, fcntl.F_SETFL, os.O_NONBLOCK) 70 return fd 71 72 def _non_blocking_read(self, fd): 73 """Non-blocking read on fd.""" 74 try: 75 self._input_event.read(fd) 76 return self._input_event 77 except Exception: 78 return None 79 80 def get_key_press_event(self, fd): 81 """Read the keyboard device node to get the key press events.""" 82 event = True 83 # Read the device node continuously until either a key press event 84 # is got or there is no more events to read. 85 while event: 86 event = self._non_blocking_read(fd) 87 if event and event.type == EV_KEY and event.value == 1: 88 return event.code 89 return None 90