faft: Send the key press and release commands together to EC UART

In the Beaglebone setup, autoserv and servod run in two different machines.
The network connection between them may have some latency. I tried to emulate
20ms round-trip delay in this connection. The firmware_ECKeyboard test failed
as the EC keyboard emulation created double key press's.

Some background: we use EC UART console to emulate keypress, like sending
'kbpress 3 7 1' to EC UART to emulate pressing 'r' key, and sending
'kbpress 3 7 0' to emualte releasing 'r' key. The main logic is controlled
in the autoserv side. It sends two separated RPCs (press and release) for
each key. When the connection has long latency, like 20ms. The long duration
between press and release results double press's and fails the test.

One fix is to support a new RPC which can send multiple commands in servod
side, check: https://gerrit.chromium.org/gerrit/44165 ,
such that the release can be called immediately after the press, no matter
the connection is bad.

BUG=chrome-os-partner:18045
TEST=manual
Emulate a long latency in the connection between autoserv and servod,
run the firmware_ECKeyboard test, over 50 time, all passed.

Change-Id: I1683dabe5ddeb87b7455b3b672afc3fa16407b6a
Reviewed-on: https://gerrit.chromium.org/gerrit/44166
Reviewed-by: Todd Broch <tbroch@chromium.org>
Commit-Queue: Tom Wai-Hong Tam <waihong@chromium.org>
Tested-by: Tom Wai-Hong Tam <waihong@chromium.org>
diff --git a/server/cros/chrome_ec.py b/server/cros/chrome_ec.py
index 0922450..4363b6e 100644
--- a/server/cros/chrome_ec.py
+++ b/server/cros/chrome_ec.py
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import ast, re
+import ast, logging, re
 
 from autotest_lib.client.common_lib import error
 
@@ -77,17 +77,30 @@
         self._servo.set('ec_uart_regexp', regexp)
 
 
-    def send_command(self, command):
+    def send_command(self, commands):
         """Send command through UART.
 
         This function opens UART pty when called, and then command is sent
         through UART.
 
         Args:
-          command: The command string to send.
+          commands: The commands to send, either a list or a string.
         """
         self.set_uart_regexp('None')
-        self._servo.set_nocheck('ec_uart_cmd', command)
+        if isinstance(commands, list):
+            try:
+                self._servo.set_nocheck('ec_uart_multicmd', ';'.join(commands))
+            except error.TestFail as e:
+                if 'No control named' in str(e):
+                    logging.warning(
+                            'The servod is too old that ec_uart_multicmd '
+                            'not supported. Use ec_uart_cmd instead.')
+                    for command in commands:
+                        self._servo.set_nocheck('ec_uart_cmd', command)
+                else:
+                    raise
+        else:
+            self._servo.set_nocheck('ec_uart_cmd', commands)
 
 
     def send_command_get_output(self, command, regexp_list):
@@ -150,8 +163,12 @@
         Args:
           keyname: Key name, one of the keys of KEYMATRIX.
         """
-        self.key_down(keyname)
-        self.key_up(keyname)
+        self.send_command([
+                'kbpress %d %d 1' %
+                    (KEYMATRIX[keyname][1], KEYMATRIX[keyname][0]),
+                'kbpress %d %d 0' %
+                    (KEYMATRIX[keyname][1], KEYMATRIX[keyname][0]),
+                ])
 
 
     def send_key_string_raw(self, string):