blob: b173353ad50f535563f1a312a37d51bc9af268a2 [file] [log] [blame]
#!/usr/bin/python3
# Copyright 2024 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Code to generate a mapping between Cambrionix USB hub ports to servo serials.
This is done by switching on all of the servos connected to the port then switching
them off one by one and noting which serial number was missing.
This is faster than switching them on one by one as each servo needs time to boot and
the USB device enumerated by the kernel. This way those boots are all done in parallel.
It will fail to find any completly non responsive servo or servos that do not correctly
report their serial number in the USB enumeration.
"""
import sys
from time import sleep
import usb
from usb_hubs.cambrionix import console_lib
SERVO_PIDS = [0x520B, 0x520D]
def get_all_servo_serial():
"""For each servo PID enumerate the USB devices and collect their serial number.
Returns:
list(string): List of connected servo serial numbers.
"""
serialnos = []
for product in SERVO_PIDS:
for device in list(usb.core.find(idProduct=product, find_all=True)):
serialnos.append(usb.util.get_string(device, device.iSerialNumber))
return serialnos
def reset_all(hub):
"""Reset all of the servo devices connected to the hub.
The process of working out the mapping is destructive to servod processes anyway
there is better success if the device are all reset.
Args:
hub (USBHubCommandsCambrionix): Class that wraps the serial connection to a
specific Cambrionix hub.
"""
hub.power_off_all()
hub.power_on_all()
# By experimentation 11 seconds is the minimum time it took for the 10 servos
# typically connected to boot and enumerate.
sleep(11)
def main():
"""Generate a yaml file with a servo serial number to usb port mapping.
Cycle through switching off each hub port and detecting the missing
serial number when as port is switched off.
"""
if not console_lib.USBHubCommandsCambrionix.is_hub_detected():
print("No single Cambrionix hub detected.")
sys.exit(2)
hub = console_lib.USBHubCommandsCambrionix()
reset_all(hub)
mapping = {}
current_serialnos = get_all_servo_serial()
for port in range(1, console_lib.MAX_PORT_NUMBER + 1):
hub.power_off_port(port)
sleep(1)
new_serialnos = get_all_servo_serial()
serial_no = set(current_serialnos) - set(new_serialnos)
if serial_no:
mapping[port] = list(serial_no)[0]
current_serialnos = new_serialnos
hub.power_on_all()
hub.write_serial_to_port(mapping)
if __name__ == "__main__":
main()
sys.exit(0)