servo: add prefix logic to set/get/has_control
With the new servod, there will be a notion of prefixes for controls.
servo should own that logic to some degree i.e. expose discovery of
devices & their prefixes, and allow to run controls based on prefixes
and control name.
This change adds the logic to run controls by providing prefix and
control-name separately, and glues it together internally. The
subsequent CL uses this to query servo firmware versions properly.
BUG=chromium:1009616
TEST=see subsequent CL
Change-Id: I4420f7523871de2196f1c4a73c382f62a2f4f976
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/2038105
Tested-by: Ruben Rodriguez Buchillon <coconutruben@chromium.org>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
Commit-Queue: Ruben Rodriguez Buchillon <coconutruben@chromium.org>
diff --git a/server/cros/servo/servo.py b/server/cros/servo/servo.py
index 54b5cba..4373dfe 100644
--- a/server/cros/servo/servo.py
+++ b/server/cros/servo/servo.py
@@ -758,40 +758,55 @@
"""
return re.sub('^.*>:', '', xmlexc.faultString)
- def has_control(self, control):
- """Query servod server to determine if |control| is a valid control.
+ def has_control(self, ctrl_name, prefix=''):
+ """Query servod server to determine if |ctrl_name| is a valid control.
- @param control: str, control name to query
+ @param ctrl_name Name of the control.
+ @param prefix: prefix to route control to correct servo device.
- @returns: true if |control| is a known control, false otherwise.
+ @returns: true if |ctrl_name| is a known control, false otherwise.
"""
- assert control
+ cltr_name = self._build_ctrl_name(ctrl_name, prefix)
try:
# If the control exists, doc() will work.
- self._server.doc(control)
+ self._server.doc(ctrl_name)
return True
except xmlrpclib.Fault as e:
- if re.search('No control %s' % control,
+ if re.search('No control %s' % ctrl_name,
self._get_xmlrpclib_exception(e)):
return False
raise e
- def get(self, gpio_name):
+ def _build_ctrl_name(self, ctrl_name, prefix):
+ """Helper to build the control name if a prefix is used.
+
+ @param ctrl_name Name of the control.
+ @param prefix: prefix to route control to correct servo device.
+
+ @returns: [|prefix|.]ctrl_name depending on whether prefix is non-empty.
+ """
+ assert ctrl_name
+ if prefix:
+ return '%s.%s' % (prefix, ctrl_name)
+ return ctrl_name
+
+ def get(self, ctrl_name, prefix=''):
"""Get the value of a gpio from Servod.
- @param gpio_name Name of the gpio.
+ @param ctrl_name Name of the control.
+ @param prefix: prefix to route control to correct servo device.
- @returns: server response to |gpio_name| request.
+ @returns: server response to |ctrl_name| request.
- @raise ControlUnavailableError: if |gpio_name| not a known control.
+ @raise ControlUnavailableError: if |ctrl_name| not a known control.
@raise error.TestFail: for all other failures doing get().
"""
- assert gpio_name
+ cltr_name = self._build_ctrl_name(ctrl_name, prefix)
try:
- return self._server.get(gpio_name)
+ return self._server.get(ctrl_name)
except xmlrpclib.Fault as e:
err_str = self._get_xmlrpclib_exception(e)
- err_msg = "Getting '%s' :: %s" % (gpio_name, err_str)
+ err_msg = "Getting '%s' :: %s" % (ctrl_name, err_str)
unknown_ctrl = re.findall(NO_CONTROL_RE, err_str)
if unknown_ctrl:
raise ControlUnavailableError('No control named %r' %
@@ -801,46 +816,50 @@
raise error.TestFail(err_msg)
- def set(self, gpio_name, gpio_value):
+ def set(self, ctrl_name, ctrl_value, prefix=''):
"""Set and check the value of a gpio using Servod.
- @param gpio_name Name of the gpio.
- @param gpio_value New setting for the gpio.
+ @param ctrl_name: Name of the control.
+ @param ctrl_value: New setting for the control.
+ @param prefix: prefix to route control to correct servo device.
@raise error.TestFail: if the control value fails to change.
"""
- self.set_nocheck(gpio_name, gpio_value)
+ cltr_name = self._build_ctrl_name(ctrl_name, prefix)
+ self.set_nocheck(ctrl_name, ctrl_value)
retry_count = Servo.GET_RETRY_MAX
- actual_value = self.get(gpio_name)
- while gpio_value != actual_value and retry_count:
- logging.warning("%s != %s, retry %d", gpio_name, gpio_value,
+ actual_value = self.get(ctrl_name)
+ while ctrl_value != actual_value and retry_count:
+ logging.warning("%s != %s, retry %d", ctrl_name, ctrl_value,
retry_count)
retry_count -= 1
time.sleep(Servo.SHORT_DELAY)
- actual_value = self.get(gpio_name)
+ actual_value = self.get(ctrl_name)
- if gpio_value != actual_value:
+ if ctrl_value != actual_value:
raise error.TestFail(
'Servo failed to set %s to %s. Got %s.'
- % (gpio_name, gpio_value, actual_value))
+ % (ctrl_name, ctrl_value, actual_value))
- def set_nocheck(self, gpio_name, gpio_value):
+ def set_nocheck(self, ctrl_name, ctrl_value, prefix=''):
"""Set the value of a gpio using Servod.
- @param gpio_name Name of the gpio.
- @param gpio_value New setting for the gpio.
+ @param ctrl_name Name of the control.
+ @param ctrl_value New setting for the control.
+ @param prefix: prefix to route control to correct servo device.
- @raise ControlUnavailableError: if |gpio_name| not a known control.
+ @raise ControlUnavailableError: if |ctrl_name| not a known control.
@raise error.TestFail: for all other failures doing set().
"""
+ cltr_name = self._build_ctrl_name(ctrl_name, prefix)
# The real danger here is to pass a None value through the xmlrpc.
- assert gpio_name and gpio_value is not None
- logging.debug('Setting %s to %r', gpio_name, gpio_value)
+ assert ctrl_value is not None
+ logging.debug('Setting %s to %r', ctrl_name, ctrl_value)
try:
- self._server.set(gpio_name, gpio_value)
+ self._server.set(ctrl_name, ctrl_value)
except xmlrpclib.Fault as e:
err_str = self._get_xmlrpclib_exception(e)
- err_msg = "Setting '%s' :: %s" % (gpio_name, err_str)
+ err_msg = "Setting '%s' :: %s" % (ctrl_name, err_str)
unknown_ctrl = re.findall(NO_CONTROL_RE, err_str)
if unknown_ctrl:
raise ControlUnavailableError('No control named %r' %