Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/env python
      2 # Copyright 2016 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 """Use your keyboard as your phone's keyboard. Experimental."""
      7 
      8 import argparse
      9 import copy
     10 import os
     11 import sys
     12 import termios
     13 import tty
     14 
     15 if __name__ == '__main__':
     16   sys.path.append(
     17       os.path.abspath(os.path.join(os.path.dirname(__file__),
     18                                    '..', '..', '..')))
     19 from devil import base_error
     20 from devil.android.sdk import keyevent
     21 from devil.android.tools import script_common
     22 from devil.utils import logging_common
     23 
     24 
     25 _KEY_MAPPING = {
     26   '\x08': keyevent.KEYCODE_DEL,
     27   '\x0a': keyevent.KEYCODE_ENTER,
     28   ' ': keyevent.KEYCODE_SPACE,
     29   '.': keyevent.KEYCODE_PERIOD,
     30   '0': keyevent.KEYCODE_0,
     31   '1': keyevent.KEYCODE_1,
     32   '2': keyevent.KEYCODE_2,
     33   '3': keyevent.KEYCODE_3,
     34   '4': keyevent.KEYCODE_4,
     35   '5': keyevent.KEYCODE_5,
     36   '6': keyevent.KEYCODE_6,
     37   '7': keyevent.KEYCODE_7,
     38   '8': keyevent.KEYCODE_8,
     39   '9': keyevent.KEYCODE_9,
     40   'a': keyevent.KEYCODE_A,
     41   'b': keyevent.KEYCODE_B,
     42   'c': keyevent.KEYCODE_C,
     43   'd': keyevent.KEYCODE_D,
     44   'e': keyevent.KEYCODE_E,
     45   'f': keyevent.KEYCODE_F,
     46   'g': keyevent.KEYCODE_G,
     47   'h': keyevent.KEYCODE_H,
     48   'i': keyevent.KEYCODE_I,
     49   'j': keyevent.KEYCODE_J,
     50   'k': keyevent.KEYCODE_K,
     51   'l': keyevent.KEYCODE_L,
     52   'm': keyevent.KEYCODE_M,
     53   'n': keyevent.KEYCODE_N,
     54   'o': keyevent.KEYCODE_O,
     55   'p': keyevent.KEYCODE_P,
     56   'q': keyevent.KEYCODE_Q,
     57   'r': keyevent.KEYCODE_R,
     58   's': keyevent.KEYCODE_S,
     59   't': keyevent.KEYCODE_T,
     60   'u': keyevent.KEYCODE_U,
     61   'v': keyevent.KEYCODE_V,
     62   'w': keyevent.KEYCODE_W,
     63   'x': keyevent.KEYCODE_X,
     64   'y': keyevent.KEYCODE_Y,
     65   'z': keyevent.KEYCODE_Z,
     66   '\x7f': keyevent.KEYCODE_DEL,
     67 }
     68 
     69 
     70 def Keyboard(device, stream_itr):
     71   try:
     72     for c in stream_itr:
     73       k = _KEY_MAPPING.get(c)
     74       if k:
     75         device.SendKeyEvent(k)
     76       else:
     77         print
     78         print '(No mapping for character 0x%x)' % ord(c)
     79   except KeyboardInterrupt:
     80     pass
     81 
     82 
     83 class MultipleDevicesError(base_error.BaseError):
     84   def __init__(self, devices):
     85     super(MultipleDevicesError, self).__init__(
     86         'More than one device found: %s' % ', '.join(str(d) for d in devices))
     87 
     88 
     89 def main(raw_args):
     90   parser = argparse.ArgumentParser(
     91       description="Use your keyboard as your phone's keyboard.")
     92   logging_common.AddLoggingArguments(parser)
     93   script_common.AddDeviceArguments(parser)
     94   args = parser.parse_args(raw_args)
     95 
     96   logging_common.InitializeLogging(args)
     97 
     98   devices = script_common.GetDevices(args.devices, None)
     99   if len(devices) > 1:
    100     raise MultipleDevicesError(devices)
    101 
    102   def next_char():
    103     while True:
    104       yield sys.stdin.read(1)
    105 
    106   try:
    107     fd = sys.stdin.fileno()
    108 
    109     # See man 3 termios for more info on what this is doing.
    110     old_attrs = termios.tcgetattr(fd)
    111     new_attrs = copy.deepcopy(old_attrs)
    112     new_attrs[tty.LFLAG] = new_attrs[tty.LFLAG] & ~(termios.ICANON)
    113     new_attrs[tty.CC][tty.VMIN] = 1
    114     new_attrs[tty.CC][tty.VTIME] = 0
    115     termios.tcsetattr(fd, termios.TCSAFLUSH, new_attrs)
    116 
    117     Keyboard(devices[0], next_char())
    118   finally:
    119     termios.tcsetattr(fd, termios.TCSAFLUSH, old_attrs)
    120   return 0
    121 
    122 
    123 if __name__ == '__main__':
    124   sys.exit(main(sys.argv[1:]))
    125