| // Copyright 2021 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "rmad/utils/calibration_utils.h" |
| |
| #include <string> |
| |
| #include <base/logging.h> |
| |
| namespace rmad { |
| |
| bool IsValidCalibrationComponent(RmadComponent component) { |
| for (auto [grouped_component, instruction] : kCalibrationSetupInstruction) { |
| if (component == grouped_component) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| CalibrationSetupInstruction GetCalibrationSetupInstruction( |
| RmadComponent component) { |
| CalibrationSetupInstruction setup_instruction = |
| RMAD_CALIBRATION_INSTRUCTION_UNKNOWN; |
| for (auto [grouped_component, instruction] : kCalibrationSetupInstruction) { |
| if (grouped_component == component) { |
| setup_instruction = instruction; |
| break; |
| } |
| } |
| |
| if (setup_instruction == RMAD_CALIBRATION_INSTRUCTION_UNKNOWN) { |
| LOG(ERROR) << "Unknown setup instruction for the device " |
| << RmadComponent_Name(component); |
| } |
| |
| return setup_instruction; |
| } |
| |
| bool IsWaitingForCalibration( |
| CalibrationComponentStatus::CalibrationStatus status) { |
| return status == CalibrationComponentStatus::RMAD_CALIBRATION_WAITING; |
| } |
| |
| bool IsCompleteStatus(CalibrationComponentStatus::CalibrationStatus status) { |
| return status == CalibrationComponentStatus::RMAD_CALIBRATION_COMPLETE || |
| status == CalibrationComponentStatus::RMAD_CALIBRATION_SKIP; |
| } |
| |
| bool IsInProgressStatus(CalibrationComponentStatus::CalibrationStatus status) { |
| return status == CalibrationComponentStatus::RMAD_CALIBRATION_IN_PROGRESS; |
| } |
| |
| bool IsUnknownStatus(CalibrationComponentStatus::CalibrationStatus status) { |
| return status == CalibrationComponentStatus::RMAD_CALIBRATION_UNKNOWN; |
| } |
| |
| bool GetCalibrationMap(scoped_refptr<JsonStore> json_store, |
| InstructionCalibrationStatusMap* calibration_map) { |
| if (!calibration_map) { |
| LOG(ERROR) << "Missing output field of the calibration map"; |
| return false; |
| } |
| |
| std::map<std::string, std::map<std::string, std::string>> json_value_map; |
| if (!json_store->GetValue(kCalibrationMap, &json_value_map)) { |
| LOG(ERROR) << "Cannot get variables from the json store"; |
| return false; |
| } |
| |
| for (auto [instruction_name, components] : json_value_map) { |
| CalibrationSetupInstruction instruction; |
| if (!CalibrationSetupInstruction_Parse(instruction_name, &instruction)) { |
| LOG(ERROR) << "Failed to parse setup instruction from variables"; |
| continue; |
| } |
| |
| for (auto [component_name, status_name] : components) { |
| RmadComponent component; |
| if (!RmadComponent_Parse(component_name, &component)) { |
| LOG(ERROR) << "Failed to parse component name from variables"; |
| continue; |
| } |
| CalibrationComponentStatus::CalibrationStatus status; |
| if (!CalibrationComponentStatus::CalibrationStatus_Parse(status_name, |
| &status)) { |
| LOG(ERROR) << "Failed to parse status name from variables"; |
| continue; |
| } |
| if (component == RmadComponent::RMAD_COMPONENT_UNKNOWN) { |
| LOG(ERROR) << "Rmad: Calibration component is missing."; |
| continue; |
| } |
| if (status == CalibrationComponentStatus::RMAD_CALIBRATION_UNKNOWN) { |
| LOG(ERROR) << "Rmad: Calibration status for " << component_name |
| << " is missing."; |
| continue; |
| } |
| if (!IsValidCalibrationComponent(component)) { |
| LOG(ERROR) << "Dictionary contains unsupported component " |
| << RmadComponent_Name(component) |
| << ", we should rewrite it again."; |
| continue; |
| } |
| (*calibration_map)[instruction][component] = status; |
| } |
| } |
| |
| return true; |
| } |
| |
| bool SetCalibrationMap(scoped_refptr<JsonStore> json_store, |
| const InstructionCalibrationStatusMap& calibration_map) { |
| // In order to save dictionary style variables to json, currently only |
| // variables whose keys are strings are supported. This is why we converted |
| // it to a string. In addition, in order to ensure that the file is still |
| // readable after the enum sequence is updated, we also convert its value |
| // into a readable string to deal with possible updates. |
| std::map<std::string, std::map<std::string, std::string>> json_value_map; |
| for (auto [instruction, components] : calibration_map) { |
| std::string instruction_name = |
| CalibrationSetupInstruction_Name(instruction); |
| for (auto [component, status] : components) { |
| if (!IsValidCalibrationComponent(component)) { |
| LOG(WARNING) << "Rmad: " << RmadComponent_Name(component) |
| << " cannot be calibrated, just ignore it."; |
| continue; |
| } |
| std::string component_name = RmadComponent_Name(component); |
| std::string status_name = |
| CalibrationComponentStatus::CalibrationStatus_Name(status); |
| json_value_map[instruction_name][component_name] = status_name; |
| } |
| } |
| |
| return json_store->SetValue(kCalibrationMap, json_value_map); |
| } |
| |
| CalibrationSetupInstruction GetCurrentSetupInstruction( |
| const InstructionCalibrationStatusMap& calibration_map) { |
| // If we don't find anything that needs calibration and there are no errors, |
| // we don't need to check or calibrate. |
| CalibrationSetupInstruction setup_instruction = |
| RMAD_CALIBRATION_INSTRUCTION_NO_NEED_CALIBRATION; |
| CalibrationSetupInstruction running_instruction = |
| RMAD_CALIBRATION_INSTRUCTION_NO_NEED_CALIBRATION; |
| |
| // There are different priority situations: |
| // 0. Unsupported component error (need to check) |
| // 1. Instruction of calibration in progress (already started) |
| // 2. Instruction of waiting for calibration components (not started yet) |
| // 3. Everything is done, but some failed (need to check) |
| // 4. All complete (no need to check) |
| for (auto [instruction, components] : calibration_map) { |
| for (auto [component, status] : components) { |
| // We do not allow unsupported components in the dictionary. |
| if (!IsValidCalibrationComponent(component)) { |
| LOG(ERROR) << "Dictionary contains unsupported component " |
| << RmadComponent_Name(component) |
| << ", we should rewrite it again."; |
| return RMAD_CALIBRATION_INSTRUCTION_NEED_TO_CHECK; |
| } |
| if (status == CalibrationComponentStatus::RMAD_CALIBRATION_IN_PROGRESS && |
| running_instruction >= instruction) { |
| running_instruction = instruction; |
| } else if (IsWaitingForCalibration(status) && |
| setup_instruction >= instruction) { |
| setup_instruction = instruction; |
| } else if (!IsWaitingForCalibration(status) && |
| !IsCompleteStatus(status) && |
| setup_instruction == |
| RMAD_CALIBRATION_INSTRUCTION_NO_NEED_CALIBRATION) { |
| setup_instruction = RMAD_CALIBRATION_INSTRUCTION_NEED_TO_CHECK; |
| } |
| } |
| } |
| |
| // If we are already running calibration, then this is the first priority. |
| if (running_instruction != RMAD_CALIBRATION_INSTRUCTION_NO_NEED_CALIBRATION) { |
| return running_instruction; |
| } |
| return setup_instruction; |
| } |
| |
| } // namespace rmad |