You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

204 lines
7.3 KiB

# License: Apache 2.0. See LICENSE file in root directory.
# Copyright(c) 2021 Intel Corporation. All Rights Reserved.
# we want this test to run first so that all tests run with updated FW versions, so we give it priority 0
#test:priority 0
#test:donotrun:gha
#test:device each(D400*)
import sys
import os
import subprocess
import re
import platform
import pyrealsense2 as rs
import pyrsutils as rsutils
from rspy import devices, log, test, file, repo
import time
# This is the first test running, discover acroname modules.
# Not relevant to MIPI devices running on jetson for LibCI
if 'jetson' not in test.context:
if not devices.hub:
log.i( "No hub library found; skipping device FW update" )
sys.exit(0)
# Following will throw if no acroname module is found
from rspy import device_hub
if device_hub.create() is None:
log.f("No hub found")
# Remove acroname -- we're likely running inside run-unit-tests in which case the
# acroname hub is likely already connected-to from there and we'll get an error
# thrown ('failed to connect to acroname (result=11)'). We do not need it -- just
# needed to verify it is available above...
devices.hub = None
def send_hardware_monitor_command(device, command):
# byte_index = -1
raw_result = rs.debug_protocol(device).send_and_receive_raw_data(command)
return raw_result[4:]
def get_update_counter(device):
product_line = device.get_info(rs.camera_info.product_line)
opcode = 0x09
start_index = 0x30
size = None
if product_line == "D400":
size = 0x2
else:
log.f( "Incompatible product line:", product_line )
raw_cmd = rs.debug_protocol(device).build_command(opcode, start_index, size)
counter = send_hardware_monitor_command(device, raw_cmd)
return counter[0]
def reset_update_counter( device ):
product_line = device.get_info( rs.camera_info.product_line )
if product_line == "D400":
opcode = 0x86
raw_cmd = rs.debug_protocol(device).build_command(opcode)
else:
log.f( "Incompatible product line:", product_line )
send_hardware_monitor_command( device, raw_cmd )
def find_image_or_exit( product_name, fw_version_regex = r'(\d+\.){3}(\d+)' ):
"""
Searches for a FW image file for the given camera name and optional version. If none are
found, exits with an error!
:param product_name: the name of the camera, from get_info(rs.camera_info.name)
:param fw_version_regex: optional regular expression specifying which FW version image to find
:return: the image file corresponding to product_name and fw_version if exist, otherwise exit
"""
pattern = re.compile( r'^Intel RealSense (((\S+?)(\d+))(\S*))' )
match = pattern.search( product_name )
if not match:
raise RuntimeError( "Failed to parse product name '" + product_name + "'" )
# For a product 'PR567abc', we want to search, in order, these combinations:
# PR567abc
# PR306abX
# PR306aXX
# PR306
# PR30X
# PR3XX
# Each of the above, combined with the FW version, should yield an image name like:
# PR567aXX_FW_Image-<fw-version>.bin
suffix = 5 # the suffix
for j in range(1, 3): # with suffix, then without
start_index, end_index = match.span(j)
for i in range(0, len(match.group(suffix))):
pn = product_name[start_index:end_index-i]
image_name = '(^|/)' + pn + i*'X' + "_FW_Image-" + fw_version_regex + r'\.bin$'
for image in file.find(repo.root, image_name):
return os.path.join( repo.root, image )
suffix -= 1
#
# If we get here, we didn't find any image...
global product_line
log.f( "Could not find image file for", product_line )
# find the update tool exe
fw_updater_exe = None
fw_updater_exe_regex = r'(^|/)rs-fw-update'
if platform.system() == 'Windows':
fw_updater_exe_regex += r'\.exe'
fw_updater_exe_regex += '$'
for tool in file.find( repo.build, fw_updater_exe_regex ):
fw_updater_exe = os.path.join( repo.build, tool )
if not fw_updater_exe:
log.f( "Could not find the update tool file (rs-fw-update.exe)" )
devices.query( monitor_changes = False )
sn_list = devices.all()
# acroname should ensure there is always 1 available device
if len( sn_list ) != 1:
log.f( "Expected 1 device, got", len( sn_list ) )
device = devices.get_first( sn_list ).handle
log.d( 'found:', device )
product_line = device.get_info( rs.camera_info.product_line )
product_name = device.get_info( rs.camera_info.name )
log.d( 'product line:', product_line )
###############################################################################
#
test.start( "Update FW" )
# check if recovery. If so recover
recovered = False
if device.is_update_device():
log.d( "recovering device ..." )
try:
image_file = find_image_or_exit( product_name )
cmd = [fw_updater_exe, '-r', '-f', image_file]
log.d( 'running:', cmd )
subprocess.run( cmd )
recovered = True
except Exception as e:
test.unexpected_exception()
log.f( "Unexpected error while trying to recover device:", e )
else:
devices.query( monitor_changes = False )
device = devices.get_first( devices.all() ).handle
current_fw_version = rsutils.version( device.get_info( rs.camera_info.firmware_version ))
log.d( 'FW version:', current_fw_version )
bundled_fw_version = rsutils.version( device.get_info( rs.camera_info.recommended_firmware_version ) )
log.d( 'bundled FW version:', bundled_fw_version )
if current_fw_version == bundled_fw_version:
# Current is same as bundled
if recovered or 'nightly' not in test.context:
# In nightly, we always update; otherwise we try to save time, so do not do anything!
log.d( 'versions are same; skipping FW update' )
test.finish()
test.print_results_and_exit()
else:
# It is expected that, post-recovery, the FW versions will be the same
test.check( not recovered, on_fail=test.ABORT )
update_counter = get_update_counter( device )
log.d( 'update counter:', update_counter )
if update_counter >= 19:
log.d( 'resetting update counter' )
reset_update_counter( device )
update_counter = 0
fw_version_regex = bundled_fw_version.to_string()
if not bundled_fw_version.build():
fw_version_regex += ".0" # version drops the build if 0
fw_version_regex = re.escape( fw_version_regex )
image_file = find_image_or_exit(product_name, fw_version_regex)
# finding file containing image for FW update
cmd = [fw_updater_exe, '-f', image_file]
log.d( 'running:', cmd )
sys.stdout.flush()
subprocess.run( cmd ) # may throw
# make sure update worked
time.sleep(3) # MIPI devices do not re-enumerate so we need to give them some time to restart
devices.query( monitor_changes = False )
sn_list = devices.all()
device = devices.get_first( sn_list ).handle
current_fw_version = rsutils.version( device.get_info( rs.camera_info.firmware_version ))
test.check_equal( current_fw_version, bundled_fw_version )
new_update_counter = get_update_counter( device )
# According to FW: "update counter zeros if you load newer FW than (ever) before"
if new_update_counter > 0:
test.check_equal( new_update_counter, update_counter + 1 )
test.finish()
#
###############################################################################
test.print_results_and_exit()