diff --git a/include/RealSenseID/AuthenticateStatus.h b/include/RealSenseID/AuthenticateStatus.h index 626f63f..80355f5 100644 --- a/include/RealSenseID/AuthenticateStatus.h +++ b/include/RealSenseID/AuthenticateStatus.h @@ -33,6 +33,7 @@ enum class RSID_API AuthenticateStatus Failure, TooManySpoofs, InvalidFeatures, + AmbiguiousFace, /// serial statuses Ok = 100, Error, diff --git a/include/RealSenseID/DeviceController.h b/include/RealSenseID/DeviceController.h index b827704..3543080 100644 --- a/include/RealSenseID/DeviceController.h +++ b/include/RealSenseID/DeviceController.h @@ -83,6 +83,18 @@ class RSID_API DeviceController * seconds to complete. */ Status FetchLog(std::string& log); + + /** + * Get color gains packet from device and fill the red, blue values + * @return SerialStatus::Success on success. + */ + Status GetColorGains(int &red, int &blue); + + /** + * Send color gains packet to device. Valid range: 0-511 + * @return SerialStatus::Success on success. + */ + Status SetColorGains(int red, int blue); private: RealSenseID::DeviceControllerImpl* _impl = nullptr; diff --git a/include/RealSenseID/EnrollStatus.h b/include/RealSenseID/EnrollStatus.h index 3be03f6..e0a421a 100644 --- a/include/RealSenseID/EnrollStatus.h +++ b/include/RealSenseID/EnrollStatus.h @@ -33,6 +33,7 @@ enum class RSID_API EnrollStatus EnrollWithMaskIsForbidden, // for mask-detector : we'll forbid enroll if used wears mask. Spoof, InvalidFeatures, + AmbiguiousFace, /// serial statuses Ok = 100, Error, diff --git a/include/RealSenseID/Version.h b/include/RealSenseID/Version.h index fffda8b..dc62846 100644 --- a/include/RealSenseID/Version.h +++ b/include/RealSenseID/Version.h @@ -8,12 +8,12 @@ #include #define RSID_VER_MAJOR 0 -#define RSID_VER_MINOR 38 -#define RSID_VER_PATCH 2 +#define RSID_VER_MINOR 40 +#define RSID_VER_PATCH 0 #define RSID_VERSION (RSID_VER_MAJOR * 10000 + RSID_VER_MINOR * 100 + RSID_VER_PATCH) -#define RSID_FW_VER_MAJOR 6 +#define RSID_FW_VER_MAJOR 7 #define RSID_FW_VER_MINOR 0 namespace RealSenseID diff --git a/release_info.json b/release_info.json index 0edad2d..b8816ca 100644 --- a/release_info.json +++ b/release_info.json @@ -1,8 +1,8 @@ { - "sw_version": 3802, - "sw_version_str": "0.38.2", - "fw_version": 609000301, - "fw_version_str": "6.9.0.301", - "release_url": "https://github.com/IntelRealSense/RealSenseID/releases/tag/v0.38.2", - "release_notes_url": "https://github.com/IntelRealSense/RealSenseID/blob/v0.38.2/release_notes.txt" -} + "sw_version": 4000, + "sw_version_str": "0.40.0", + "fw_version": 700000304, + "fw_version_str": "7.0.0.304", + "release_url": "https://github.com/IntelRealSense/RealSenseID/releases/tag/v0.40.0", + "release_notes_url": "https://github.com/IntelRealSense/RealSenseID/blob/v0.40.0/release_notes.txt" +} \ No newline at end of file diff --git a/release_notes.txt b/release_notes.txt index de49d8b..82ccb3b 100644 --- a/release_notes.txt +++ b/release_notes.txt @@ -1,3 +1,15 @@ +Realsense ID version 0.40.0 +----------------------------------- +* New firmware release - version 7.0.0.304 + * Improved TNR and TPR for Anti-Spoofing + * Face authentication TPR/TNR improvement (requires old database conversion) + * Face detection improvement + * Import database bug fix +* New host SW: + * CRC Optimization + * FW upgrade enhancement + * Added Set/Get color gains to API + Realsense ID version 0.38.2 ----------------------------------- * New firmware release - version 6.9.0.301 diff --git a/src/DeviceController.cc b/src/DeviceController.cc index eb1b5b3..734cc29 100644 --- a/src/DeviceController.cc +++ b/src/DeviceController.cc @@ -61,5 +61,14 @@ Status DeviceController::FetchLog(std::string& log) return _impl->FetchLog(log); } +Status DeviceController::GetColorGains(int &red, int &blue) +{ + return _impl->GetColorGains(red, blue); +} + +Status DeviceController::SetColorGains(int red, int blue) +{ + return _impl->SetColorGains(red, blue); +} } // namespace RealSenseID \ No newline at end of file diff --git a/src/DeviceControllerImpl.cc b/src/DeviceControllerImpl.cc index 38f6e01..cffd51b 100644 --- a/src/DeviceControllerImpl.cc +++ b/src/DeviceControllerImpl.cc @@ -10,7 +10,7 @@ #include #include #include - +#include #ifdef _WIN32 #include "PacketManager/WindowsSerial.h" @@ -75,7 +75,6 @@ Status DeviceControllerImpl::QueryFirmwareVersion(std::string& version) { // clear output version string to avoid returning garbage version.clear(); - try { std::string version_in_progress; @@ -109,24 +108,30 @@ Status DeviceControllerImpl::QueryFirmwareVersion(std::string& version) } } + // parse lines of module versions .e.g. + // ASDISP : 18.9.24.0 + // NNLED : 15.9.24.0 + static const std::regex module_regex {R"((\w+) : ([\d\.]+))"}; std::stringstream ss(buffer); std::string line; while (std::getline(ss, line, '\n')) - { - static const std::regex module_regex { - R"((OPFW|NNLED|DNET|RECOG|YOLO|AS2DLR|NNLAS|NNLEDR|SPOOFS|ASDISP) : ([\d\.]+))"}; + { std::smatch match; - auto match_ok = std::regex_search(line, match, module_regex); if (match_ok) { + auto version_number = match[2].str(); + if (version_number == "0.0.0.0") // ignore, unused module + { + continue; + } if (!version_in_progress.empty()) version_in_progress += '|'; version_in_progress += match[1].str(); version_in_progress += ':'; - version_in_progress += match[2].str(); + version_in_progress += version_number; } } @@ -301,7 +306,9 @@ Status DeviceControllerImpl::Ping() } // create a ping data packet with random data - char random_data[sizeof(DataMessage::data)]; + // create a ping data packet with random data + char random_data[512]; + static_assert(sizeof(random_data) <= sizeof(DataMessage::data), "Random data size exceeds max allowed"); Randomizer::Instance().GenerateRandom((unsigned char*)random_data, sizeof(random_data)); DataPacket ping_packet {MsgId::Ping, random_data, sizeof(random_data)}; @@ -388,8 +395,8 @@ Status DeviceControllerImpl::FetchLog(std::string& result) { result.erase(pos); } - - // expect the START_OF_LOG token + + // expect the START_OF_LOG token pos = result.find(start_token); if (pos != std::string::npos) { @@ -405,9 +412,9 @@ Status DeviceControllerImpl::FetchLog(std::string& result) // make sure it ends with '\n' if (!result.empty() && result.back() != '\n') { - result.push_back('\n'); + result.push_back('\n'); } - + LOG_DEBUG(LOG_TAG, "Got %zu log bytes", result.size()); return Status::Ok; } @@ -422,4 +429,84 @@ Status DeviceControllerImpl::FetchLog(std::string& result) return Status::Error; } } + +Status DeviceControllerImpl::GetColorGains(int& red, int& blue) +{ + const char* const cmd = PacketManager::Commands::get_color_gains; + auto send_status = _serial->SendBytes(cmd, ::strlen(cmd)); + if (send_status != PacketManager::SerialStatus::Ok) + { + LOG_ERROR(LOG_TAG, "Failed sending cm command"); + return ToStatus(send_status); + } + + // receive data until no more is available + constexpr size_t max_buffer_size = 128; + char buffer[max_buffer_size] = {0}; + for (size_t i = 0; i < max_buffer_size - 1; ++i) + { + auto status = _serial->RecvBytes(&buffer[i], 1); + // timeout is legal for the final byte, because we do not know the expected data size + if (status == PacketManager::SerialStatus::RecvTimeout) + break; + + // other error are still not accepted + if (status != PacketManager::SerialStatus::Ok) + { + LOG_ERROR(LOG_TAG, "Failed reading serial number data"); + return ToStatus(status); + } + } + + // extract red blue numbers e.g [123 511] + try + { + std::string input(buffer); + std::smatch matches; + static const std::regex pattern {R"(\[(\d+)\s(\d+)\])"}; + if (std::regex_search(input, matches, pattern)) + { + red = std::stoi(matches[1].str()); + blue = std::stoi(matches[2].str()); + return Status::Ok; + } + else + { + return Status::Error; + } + } + catch (const std::exception& ex) + { + LOG_EXCEPTION(LOG_TAG, ex); + return Status::Error; + } + catch (...) + { + LOG_ERROR(LOG_TAG, "Unknown exception in GetColorGains"); + return Status::Error; + } +} + +Status DeviceControllerImpl::SetColorGains(int red, int blue) +{ + constexpr int max_value = 511; + constexpr int min_value = 0; + if (red < min_value || red > max_value || blue < min_value || blue > max_value) + { + LOG_ERROR(LOG_TAG, "Invalid color gain values"); + return Status::Error; + } + + char buf[64]; + const char* const cmd = PacketManager::Commands::set_color_gains; + snprintf(buf, sizeof(buf), cmd, red, blue); + auto send_status = _serial->SendBytes(buf, ::strlen(buf)); + if (send_status != PacketManager::SerialStatus::Ok) + { + LOG_ERROR(LOG_TAG, "Failed sending cm command"); + } + return ToStatus(send_status); +} + + } // namespace RealSenseID diff --git a/src/DeviceControllerImpl.h b/src/DeviceControllerImpl.h index a900a62..bfaf983 100644 --- a/src/DeviceControllerImpl.h +++ b/src/DeviceControllerImpl.h @@ -29,6 +29,8 @@ class DeviceControllerImpl Status QueryOtpVersion(uint8_t& otpVer); Status Ping(); Status FetchLog(std::string& log); + Status GetColorGains(int& red, int& blue); + Status SetColorGains(int red, int blue); private: std::unique_ptr _serial; diff --git a/src/FaceAuthenticatorImpl.cc b/src/FaceAuthenticatorImpl.cc index 1146898..d25a72d 100644 --- a/src/FaceAuthenticatorImpl.cc +++ b/src/FaceAuthenticatorImpl.cc @@ -1703,7 +1703,39 @@ Status FaceAuthenticatorImpl::SetUsersFaceprints(UserFaceprints_t* user_features continue; } } - return all_users_set ? Status::Ok : Status::Error; + if (!all_users_set) + { + return Status::Error; + } + + // If succeeded setting all users, tell the device to save the detures DB to its storage + auto save_db_packet = std::make_unique(PacketManager::MsgId::SaveDatabase); + status = _session.SendPacket(*save_db_packet); + if (status != PacketManager::SerialStatus::Ok) + { + LOG_ERROR(LOG_TAG, "Failed sending SaveDatabase packet (status %d)", (int)status); + all_users_set = false; + } + // Wait for savedb reply + status = _session.RecvFaPacket(*save_db_packet); + if (status != PacketManager::SerialStatus::Ok) + { + LOG_ERROR(LOG_TAG, "Failed receiving savedb reply packet (status %d)", static_cast(status)); + return ToStatus(status); + } + auto msg_id = save_db_packet->header.id; + if (PacketManager::MsgId::Reply != msg_id) + { + LOG_ERROR(LOG_TAG, "Got unexpected message id %d instead of MsgId::Reply", static_cast(msg_id)); + return Status::Error; + } + auto status_code = save_db_packet->GetStatusCode(); + auto final_status = Status(status_code); + if (final_status != Status::Ok) + { + LOG_ERROR(LOG_TAG, "Failed saving DB to device. Status: %d", static_cast(status_code)); + } + return final_status; } diff --git a/src/FwUpdate/FwUpdateEngine.cc b/src/FwUpdate/FwUpdateEngine.cc index 5f24ec1..b175124 100644 --- a/src/FwUpdate/FwUpdateEngine.cc +++ b/src/FwUpdate/FwUpdateEngine.cc @@ -22,11 +22,12 @@ namespace FwUpdate static const char* LOG_TAG = "FwUpdater"; static const char* DumpFilename = "fw-update.log"; -static const std::set AllowedModules {"OPFW", "NNLED", "DNET", "RECOG", - "YOLO", "AS2DLR", "NNLAS", "NNLEDR", - "SPOOFS", "ASDISP"}; -static const char* OPFW = "OPFW"; +static const std::set AllowedModules {"OPFW", "NNLED", "DNET", "RECOG", "YOLO", + "AS2DLR", "NNLAS", "NNLEDR", "SPOOFS", "ASDISP"}; + +static const std::string OPFW = "OPFW"; // Do not change +static const std::string SCRAP = "SCRAP"; // Do not change struct FwUpdateEngine::ModuleVersionInfo { @@ -57,57 +58,15 @@ struct FwUpdateEngine::ModuleVersionInfo } }; -// search for module_name for the given input(dlver response) -// return true if found valid line for this module, and fill the result struct -bool FwUpdateEngine::ParseDlVer(const char* input, const std::string& module_name, ModuleVersionInfo& result) +// Verify module name is in the allowed list +static void VerifyAllowed(const ModuleInfo& module) { - // regex to find line of the form: OPFW : [OPFW] [0.0.0.1] (active) - // regex groups to match: module_name, module_name, version, state - static const std::regex rgx { - R"((\w+) : \[(OPFW|NNLED|DNET|RECOG|YOLO|AS2DLR|SCRAP|NNLAS|NNLEDR|SPOOFS|ASDISP)\] \[([\d\.]+)\] \(([\w-]+)\))"}; - std::smatch match; - - - - // do regex on each line in the input and construct ModuleVersionInfo from it - std::stringstream ss(input); - std::string line; - while (std::getline(ss, line, '\n')) + if (AllowedModules.find(module.name) == AllowedModules.end()) { - auto match_ok = std::regex_search(line, match, rgx); - // find the line with the required module_name - if (!match_ok || match[2] != module_name) - { - continue; - } - assert(match[1] == match[2]); // name : [name] should be same name - result.name = match[2]; - result.version = match[3]; - result.state = ModuleVersionInfo::StateFromString(match[4]); - - LOG_DEBUG(LOG_TAG, "ParseDlVer(%s) result: name=%s, version=%s, state=%d", module_name.c_str(), - result.name.c_str(), result.version.c_str(), (int)result.state); - return true; + throw std::runtime_error("Found invalid module name in file: " + module.name); } - return false; } -bool FwUpdateEngine::ConsumeDlVerResponse(const std::string& module_name, ModuleVersionInfo& module_info) -{ - char* logBuf = _comm->GetScanPtr(); - - LOG_DEBUG(LOG_TAG, "**************** ParseDlVer ********************"); - LOG_DEBUG(LOG_TAG, "%s", logBuf); - LOG_DEBUG(LOG_TAG, "**************************************************"); - - auto is_ok = ParseDlVer(logBuf, module_name, module_info); - if (!is_ok) - { - LOG_ERROR(LOG_TAG, "Error, no info for module %s", module_name.c_str()); - } - _comm->ConsumeScanned(); - return is_ok; -} /* parse dlinfo response @@ -262,15 +221,8 @@ bool FwUpdateEngine::ParseDlBlockResult() void FwUpdateEngine::BurnModule(ProgressTick tick, const ModuleInfo& module, const Buffer& buffer, bool is_first, bool is_last, bool force_full) { - // send dlver command to get the module's state - _comm->WriteCmd(Cmds::dlver()); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - ModuleVersionInfo version_info; - bool success = ConsumeDlVerResponse(module.name, version_info); - if (!success) - { - throw std::runtime_error("Failed parsing verinfo response"); - } + // Get module info from the device + auto version_info = ModuleFromDevice(module.name); // send dlinfo command to get the module's block info _comm->WriteCmd(Cmds::dlinfo(module.name)); _comm->WaitForStr("dlinfo end", std::chrono::milliseconds {1000}); @@ -320,9 +272,9 @@ void FwUpdateEngine::BurnModule(ProgressTick tick, const ModuleInfo& module, con std::this_thread::sleep_for(std::chrono::milliseconds(50)); char* logBuf = _comm->GetScanPtr(); _comm->ConsumeScanned(); - LOG_INFO(LOG_TAG, "*************** dlinit response ***************"); - LOG_INFO(LOG_TAG, "%s", logBuf); - LOG_INFO(LOG_TAG, "**************************************************"); + LOG_DEBUG(LOG_TAG, "*************** dlinit response ***************"); + LOG_DEBUG(LOG_TAG, "%s", logBuf); + LOG_DEBUG(LOG_TAG, "**************************************************"); if (strstr(logBuf, "err ") != nullptr) { @@ -408,18 +360,52 @@ void FwUpdateEngine::BurnModule(ProgressTick tick, const ModuleInfo& module, con LOG_DEBUG(LOG_TAG, "update finished"); } -// clean obsolete modules from FW by shrinking the size 1 block (minimum allowed) -void FwUpdateEngine::CleanObsoleteModules() +// Clean unused modules from the FW. +// For each module in the device, zero it's size if: +// 1. It doesn't exist in the newly installed fw file +// 2. and is not OPFW ! +// 3. and is not already empty +void FwUpdateEngine::CleanObsoleteModules(const std::vector& file_modules, + const std::vector& device_modules) { - const std::vector obsolete_modules = {"NNLAS", "NNLEDR", "SPOOFS"}; - // Note: NEVER add "OPFW" to the "obsolete_modules" list above ! + for (const auto& device_module : device_modules) + { + if (device_module.state == ModuleVersionInfo::State::Empty || device_module.name == OPFW) + { + continue; + } + bool exists_in_file = + std::any_of(file_modules.begin(), file_modules.end(), [&device_module](const ModuleInfo& file_module) { + return file_module.name == device_module.name; + }); - for (const std::string &obsolete_name : obsolete_modules) + if (!exists_in_file) + { + LOG_INFO(LOG_TAG, "Clean obsolete module %s", device_module.name.c_str()); + // don't wait for ack response since this doesn't work if in fw is in Loader state + _comm->WriteCmd(Cmds::dlsize(device_module.name, 0), /* wait_response */ false); + _comm->WaitForIdle(); + } + } +} +// Initialize new modules in the device. +// For each file modules that doesn't exist in the fw, send the dlnew command. +void FwUpdateEngine::InitNewModules(const std::vector& file_modules, + const std::vector& device_modules) +{ + for (const auto& file_module : file_modules) { - assert(OPFW != obsolete_name); - // don't wait for ack response since this doesn't work if in fw is in Loader state - _comm->WriteCmd(Cmds::dlsize(obsolete_name, 0), /* wait_response */ false); - _comm->WaitForIdle(); + bool exists_in_device = std::any_of( + device_modules.begin(), device_modules.end(), + [&file_module](const ModuleVersionInfo& device_module) { return device_module.name == file_module.name; }); + + if (!exists_in_device) + { + VerifyAllowed(file_module); + LOG_INFO(LOG_TAG, "Init new module %s", file_module.name.c_str()); + _comm->WriteCmd(Cmds::dlnew(file_module.name, file_module.size)); + _comm->WaitForIdle(); + } } } @@ -437,15 +423,7 @@ void FwUpdateEngine::BurnSelectModules(const ModuleVector& modules, ProgressTick } auto is_last_module = module_count == modules.size(); bool is_first_module = module_count == 1; - - if (module.name == "SPOOFS" || module.name == "ASDISP") // NNLEDR/SPOOFS are new modules and need to be declared - { - _comm->WriteCmd(Cmds::dlnew(module.name, module.size)); - _comm->WaitForIdle(); - } - BurnModule(tick, module, buffer, is_first_module, is_last_module, force_full); - LOG_INFO(LOG_TAG, "Module %s done", module.name.c_str()); } } @@ -457,15 +435,72 @@ ModuleVector FwUpdateEngine::ModulesFromFile(const std::string& path) // validate that we get known module names for (const auto& module : modules) { - if (AllowedModules.find(module.name) == AllowedModules.end()) - throw std::runtime_error("Found invalid module name in file: " + module.name); + VerifyAllowed(module); } - LOG_INFO(LOG_TAG, "Extracted %zu modules", modules.size()); LOG_DEBUG(LOG_TAG, ""); return modules; } +// return list of modules are returned by the device with dlver +std::vector FwUpdateEngine::ModulesFromDevice() +{ + // regex to find line of the form: OPFW : [OPFW] [0.0.0.1] (active) + // regex groups to match: module_name, module_name, version, state + std::vector results; + static const std::regex rgx {R"((\w+) : \[(\w+)\] \[([\d\.]+)\] \(([\w-]+)\))"}; + std::smatch match; + std::vector modules; + _comm->WriteCmd(Cmds::dlver(), true); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + char* response = _comm->GetScanPtr(); + // do regex on each line in the input and construct ModuleVersionInfo from it + std::stringstream ss(response); + std::string line; + while (std::getline(ss, line, '\n')) + { + auto match_ok = std::regex_search(line, match, rgx); + // find the line with the required module_name + if (!match_ok) + { + continue; + } + assert(match[1] == match[2]); // name : [name] should be same name + ModuleVersionInfo result; + result.name = match[2]; + result.version = match[3]; + result.state = ModuleVersionInfo::StateFromString(match[4]); + + LOG_DEBUG(LOG_TAG, "ParseDlVer result: name=%s, version=%s, state=%d", result.name.c_str(), + result.version.c_str(), (int)result.state); + if (result.name != SCRAP) + { + results.push_back(std::move(result)); + } + } + _comm->ConsumeScanned(); + if (results.empty()) + { + throw std::runtime_error("Could not extract module list from dlver response"); + } + return results; +} + +// return module info from device with dlver. Throw if module not found +FwUpdateEngine::ModuleVersionInfo FwUpdateEngine::ModuleFromDevice(const std::string& module_name) +{ + auto modules = ModulesFromDevice(); + for (const auto& module : modules) + { + if (module.name == module_name) + { + return module; + } + } + throw std::runtime_error("Module not found in device: " + module_name); +} + + void FwUpdateEngine::BurnModules(const Settings& settings, const ModuleVector& modules, ProgressCallback on_progress) { if (modules.empty()) @@ -495,14 +530,15 @@ void FwUpdateEngine::BurnModules(const Settings& settings, const ModuleVector& m on_progress(overall_progress); }; - _comm = std::make_unique(settings.port); + _comm = std::make_unique(settings.port); try { _comm->WaitForIdle(); _comm->WriteCmd(Cmds::dlspd(settings.baud_rate), true); - _comm->WriteCmd(Cmds::dlver(), true); + auto device_modules = ModulesFromDevice(); on_progress(0.0f); - CleanObsoleteModules(); + CleanObsoleteModules(modules, device_modules); + InitNewModules(modules, device_modules); BurnSelectModules(modules, progress_tick, settings.force_full); _comm->DumpSession(DumpFilename); on_progress(1.0f); diff --git a/src/FwUpdate/FwUpdateEngine.h b/src/FwUpdate/FwUpdateEngine.h index 002ac2c..c402684 100644 --- a/src/FwUpdate/FwUpdateEngine.h +++ b/src/FwUpdate/FwUpdateEngine.h @@ -31,31 +31,26 @@ class FwUpdateEngine FwUpdateEngine() = default; ~FwUpdateEngine() = default; - ModuleVector ModulesFromFile(const std::string& filename); void BurnModules(const Settings& settings, const ModuleVector& modules, ProgressCallback on_progress); private: static constexpr const uint32_t BlockSize = 512 * 1024; + std::unique_ptr _comm; struct ModuleVersionInfo; - - void CleanObsoleteModules(); - + std::vector ModulesFromDevice(); + ModuleVersionInfo ModuleFromDevice(const std::string& module_name); + void CleanObsoleteModules(const std::vector& file_modules, + const std::vector& device_modules); + void InitNewModules(const std::vector& file_modules, + const std::vector& device_modules); void BurnSelectModules(const ModuleVector& modules, ProgressTick tick, bool force_full); - - // update single module void BurnModule(ProgressTick tick, const ModuleInfo& module, const Buffer& buffer, bool is_first, bool is_last, bool force_full); - - std::vector GetBlockUpdateList(const ModuleInfo& module, bool force_full); - - bool ConsumeDlVerResponse(const std::string& module_name, ModuleVersionInfo& module_info); - bool ParseDlResponse(const std::string& name, size_t blkNo, size_t sz); - bool ParseDlVer(const char* input, const std::string& module_name, ModuleVersionInfo& result); + std::vector GetBlockUpdateList(const ModuleInfo& module, bool force_full); + bool ParseDlResponse(const std::string& name, size_t blkNo, size_t sz); bool ParseDlBlockResult(); - - std::unique_ptr _comm; }; } // namespace FwUpdate } // namespace RealSenseID diff --git a/src/FwUpdater.cc b/src/FwUpdater.cc index 21feaa4..5670f6d 100644 --- a/src/FwUpdater.cc +++ b/src/FwUpdater.cc @@ -252,7 +252,7 @@ static std::string ParseFirmwareVersion(const std::string& full_version) static FirmwareVersion StringToFirmwareVersion(std::string outFwVersion) { - const std::regex r("(\\d+)\\.(\\d+)\\.\\d+\\.\\d+"); + static const std::regex r("(\\d+)\\.(\\d+)\\.\\d+\\.\\d+"); std::smatch base_match; if (std::regex_match(outFwVersion, base_match, r)) { diff --git a/src/PacketManager/PacketSender.cc b/src/PacketManager/PacketSender.cc index 3009305..9f0f226 100644 --- a/src/PacketManager/PacketSender.cc +++ b/src/PacketManager/PacketSender.cc @@ -183,9 +183,15 @@ SerialStatus PacketSender::WaitSyncBytes(SerialPacket& target, Timer* timer) uint16_t PacketSender::CalcCrc(const SerialPacket& packet) { auto* packet_ptr = reinterpret_cast(&packet); - auto crc = Crc16(packet_ptr, sizeof(packet) - sizeof(packet.crc)); + auto size = sizeof(packet.header) + packet.header.payload_size + sizeof(packet.hmac); + if (size > sizeof(packet) - sizeof(packet.crc)) + { + throw std::runtime_error("CalcCrc: Packet size is bigger than packet struct size"); + } + auto crc = Crc16(packet_ptr, size); static_assert(sizeof(packet.crc) == sizeof(crc), "packet.crc and crc size mismatch"); return crc; } + } // namespace PacketManager } // namespace RealSenseID diff --git a/src/PacketManager/SerialPacket.h b/src/PacketManager/SerialPacket.h index 072e03c..6d04627 100644 --- a/src/PacketManager/SerialPacket.h +++ b/src/PacketManager/SerialPacket.h @@ -17,7 +17,7 @@ namespace RealSenseID { namespace PacketManager { - static const unsigned char ProtocolVer = 2; + static const unsigned char ProtocolVer = 3; static const size_t MaxUserIdSize = 30; struct FaMessage @@ -83,7 +83,8 @@ enum class MsgId : char LicenseVerificationStart = '$', LicenseVerificationRequest = 'v', LicenseVerificationResponse = 'h', - Status = 'z' + Status = 'z', + SaveDatabase = 'S' }; struct SerialPacket @@ -149,7 +150,9 @@ enum class MsgId : char static const char* device_info = "\r\nbspver -device\r\n"; static const char* reset = "\r\nreset\r\n"; static const char* otp_ver = "\r\ngetOtpVer\r\n"; - static const char* getlogs= "\r\ngetLogs\r\n"; + static const char* getlogs = "\r\ngetLogs\r\n"; + static const char* get_color_gains = "\r\ncm\r\n"; + static const char* set_color_gains = "\r\ncm %d %d\r\n"; } // namespace Commands } // namespace PacketManager } // namespace RealSenseID diff --git a/src/StatusHelper.cc b/src/StatusHelper.cc index f8c6e01..657976c 100644 --- a/src/StatusHelper.cc +++ b/src/StatusHelper.cc @@ -102,6 +102,8 @@ const char* Description(EnrollStatus status) return "Invalid_Features"; case RealSenseID::EnrollStatus::Spoof_Plane_Disparity: return "Spoof_Plane_Disparity"; + case RealSenseID::EnrollStatus::AmbiguiousFace: + return "Ambiguious_Face"; default: return "Unknown Status"; } @@ -200,6 +202,8 @@ const char* Description(AuthenticateStatus status) return "Invalid_Features"; case RealSenseID::AuthenticateStatus::Spoof_Plane_Disparity: return "Spoof_Plane_Disparity"; + case RealSenseID::AuthenticateStatus::AmbiguiousFace: + return "Ambiguious_Face"; default: return "Unknown Status"; } diff --git a/tools/rsid-cli/main.cc b/tools/rsid-cli/main.cc index 2ed21ee..59ce7e8 100644 --- a/tools/rsid-cli/main.cc +++ b/tools/rsid-cli/main.cc @@ -538,9 +538,9 @@ void query_log(const RealSenseID::SerialConfig& serial_config) } deviceController.Disconnect(); - + // create dumps dir if not exist and save the log in it - std::string dumps_dir = "dumps"; + std::string dumps_dir = "dumps"; std::string logfile = dumps_dir + "/f450.log"; #ifdef _WIN32 int rv = _mkdir(dumps_dir.c_str()); @@ -553,12 +553,12 @@ void query_log(const RealSenseID::SerialConfig& serial_config) std::perror(msg.c_str()); return; } - + std::ofstream ofs(logfile); ofs << log; if (ofs) { - std::cout << "\n*** Saved to " << logfile << " (" << log.size() << " bytes) ***" << std::endl << std::endl; + std::cout << "\n*** Saved to " << logfile << " (" << log.size() << " bytes) ***" << std::endl << std::endl; } else { @@ -567,6 +567,61 @@ void query_log(const RealSenseID::SerialConfig& serial_config) } } +// get/set color gains +void color_gains(const RealSenseID::SerialConfig& serial_config) +{ + RealSenseID::DeviceController deviceController; + auto connect_status = deviceController.Connect(serial_config); + if (connect_status != RealSenseID::Status::Ok) + { + std::cout << "Failed connecting to port " << serial_config.port << " status:" << connect_status << std::endl; + return; + } + int red = -1, blue = -1; + std::cout << "GetColorGains..\n"; + auto status = deviceController.GetColorGains(red, blue); + if (status != RealSenseID::Status::Ok) + { + std::cout << "Failed getting color gains!\n"; + return; + } + + std::cout << "Current Red-Blue: " << red << " " << blue; + // Get blue red and blue from user + std::stringstream ss; // Used to convert string to int + + int intput_red = 1, intput_blue = -1; + while (true) + { + std::string input; + intput_red, intput_blue = -1; + std::cout << std::endl << "Set New Red-Blue (e.g. \"200 300\"): "; + std::getline(std::cin, input); + if (input.empty()) + break; + std::istringstream iss(input); + if (iss >> intput_red && iss >> intput_blue && iss.eof()) + break; + } + status = deviceController.SetColorGains(intput_red, intput_blue); + if (status != RealSenseID::Status::Ok) + { + std::cout << "Failed setting color gains!\n"; + return; + } + std::cout << "SetColorGains Success\n"; + + std::cout << "GetColorGains..\n"; + status = deviceController.GetColorGains(red, blue); + if (status != RealSenseID::Status::Ok) + { + std::cout << "Failed getting color gains!\n"; + return; + } + + std::cout << "Got values: " << red << " " << blue << "\n"; +} + // extract faceprints for new enrolled user class MyEnrollServerClbk : public RealSenseID::EnrollFaceprintsExtractionCallback { @@ -834,6 +889,7 @@ void print_menu() print_menu_opt("'l' to provide license."); print_menu_opt("'L' to unlock."); print_menu_opt("'o' to fetch device log."); + print_menu_opt("'w' to set/get color gains."); print_menu_opt("'q' to quit."); // server mode opts @@ -1117,6 +1173,10 @@ void sample_loop(const RealSenseID::SerialConfig& serial_config) case 'o': query_log(serial_config); break; + + case 'w': + color_gains(serial_config); + break; } } } diff --git a/tools/rsid-viewer/MainWindow.xaml.cs b/tools/rsid-viewer/MainWindow.xaml.cs index 047fa90..c9d79a5 100644 --- a/tools/rsid-viewer/MainWindow.xaml.cs +++ b/tools/rsid-viewer/MainWindow.xaml.cs @@ -407,7 +407,7 @@ private void OpenConsoleToggle_Click(object sender, RoutedEventArgs e) } private async void FetchDeviceLog_Click(object sender, RoutedEventArgs e) - { + { var sfd = new SaveFileDialog { Title = "Save As", @@ -1730,7 +1730,12 @@ private void RefreshUserListServer() var sn = controller.QuerySerialNumber(); device.SerialNumber = sn; ShowLog($"S/N: {device.SerialNumber}\n"); - BackgroundDispatch(() => SNText.Text = $"S/N: {device.SerialNumber}"); + BackgroundDispatch(() => + { + if (!string.IsNullOrEmpty(device.FirmwareVersion)) + Title += $" (firmware {device.FirmwareVersion})"; + SNText.Text = $"S/N: {device.SerialNumber}"; + }); try { diff --git a/wrappers/c/include/rsid_c/rsid_client.h b/wrappers/c/include/rsid_c/rsid_client.h index 2de20c8..65002f6 100644 --- a/wrappers/c/include/rsid_c/rsid_client.h +++ b/wrappers/c/include/rsid_c/rsid_client.h @@ -326,7 +326,11 @@ RSID_C_API rsid_authenticator* rsid_create_authenticator(); RSID_C_API rsid_status rsid_fetch_log(rsid_device_controller* device_controller, char* output, size_t output_length); + /* get color gains value from fw*/ + RSID_C_API rsid_status rsid_get_color_gains(rsid_device_controller* device_controller, int* red, int* blue); + /* send color adjust message */ + RSID_C_API rsid_status rsid_set_color_gains(rsid_device_controller* device_controller, int red, int blue); /*******************************/ /***** server mode methods *****/ diff --git a/wrappers/c/include/rsid_c/rsid_status.h b/wrappers/c/include/rsid_c/rsid_status.h index 8214bfb..755ad1d 100644 --- a/wrappers/c/include/rsid_c/rsid_status.h +++ b/wrappers/c/include/rsid_c/rsid_status.h @@ -97,6 +97,7 @@ extern "C" RSID_Auth_Failure, RSID_Auth_TooManySpoofs, RSID_Auth_InvalidFeatures, + RSID_Auth_AmbiguiousFace, RSID_Auth_Serial_Ok = RSID_Ok, RSID_Auth_Serial_Error, RSID_Auth_Serial_SerialError, @@ -109,6 +110,7 @@ extern "C" RSID_Auth_Spoof_3D, RSID_Auth_Spoof_LR, RSID_Auth_Spoof_Disparity, + RSID_Auth_Spoof_Surface, RSID_Auth_Spoof_Plane_Disparity } rsid_auth_status; @@ -135,6 +137,7 @@ extern "C" RSID_EnrollWithMaskIsForbidden, RSID_Enroll_Spoof, RSID_Enroll_InvalidFeatures, + RSID_Enroll_AmbiguiousFace, RSID_Enroll_Serial_Ok = RSID_Ok, RSID_Enroll_Serial_Error, RSID_Enroll_Serial_SerialError, @@ -147,6 +150,7 @@ extern "C" RSID_Enroll_Spoof_3D, RSID_Enroll_Spoof_LR, RSID_Enroll_Spoof_Disparity, + RSID_Enroll_Spoof_Surface, RSID_Enroll_Spoof_Plane_Disparity } rsid_enroll_status; diff --git a/wrappers/c/src/rsid_c_device_controller.cc b/wrappers/c/src/rsid_c_device_controller.cc index a445934..d79e009 100644 --- a/wrappers/c/src/rsid_c_device_controller.cc +++ b/wrappers/c/src/rsid_c_device_controller.cc @@ -150,3 +150,20 @@ RSID_C_API rsid_status rsid_fetch_log(rsid_device_controller* device_controller, output[output_length - 1] = '\0'; return rsid_status::RSID_Ok; } + +RSID_C_API rsid_status rsid_get_color_gains(rsid_device_controller* device_controller, int* red, int* blue) +{ + if(red == nullptr || blue == nullptr) + return rsid_status::RSID_Error; + + auto* controller_impl = get_controller_impl(device_controller); + auto status = controller_impl->GetColorGains(*red, *blue); + return static_cast(status); +} + +RSID_C_API rsid_status rsid_set_color_gains(rsid_device_controller* device_controller, int red, int blue) +{ + auto* controller_impl = get_controller_impl(device_controller); + auto status = controller_impl->SetColorGains(red, blue); + return static_cast(status); +} diff --git a/wrappers/c/src/rsid_c_fw_updater.cc b/wrappers/c/src/rsid_c_fw_updater.cc index db72240..cfa30e4 100644 --- a/wrappers/c/src/rsid_c_fw_updater.cc +++ b/wrappers/c/src/rsid_c_fw_updater.cc @@ -176,8 +176,8 @@ void rsid_decide_update_policy(rsid_fw_updater* handle, rsid_fw_update_settings if (resultUpdatePolicyInfo.policy == RealSenseID::FwUpdater::UpdatePolicyInfo::UpdatePolicy::REQUIRE_INTERMEDIATE_FW) { + // we want to make sure the last char is \0, so we make sure to not overwrite it. ::strncpy(updatePolicyInfo->intermediate_version, resultUpdatePolicyInfo.intermediate.c_str(), - sizeof(updatePolicyInfo->intermediate_version) - - 1); // we want to make sure the last char is \0, so we make sure to not overwrite it. + sizeof(updatePolicyInfo->intermediate_version) - 1); } } diff --git a/wrappers/csharp/Authenticator.cs b/wrappers/csharp/Authenticator.cs index e2b36cb..64bc49e 100644 --- a/wrappers/csharp/Authenticator.cs +++ b/wrappers/csharp/Authenticator.cs @@ -320,6 +320,7 @@ public enum AuthStatus Failure, TooManySpoofs, InvalidFeatures, + AmbiguiousFace, Serial_Ok = 100, Serial_Error, Serial_SerialError, diff --git a/wrappers/csharp/DeviceController.cs b/wrappers/csharp/DeviceController.cs index cb2e9a6..554678c 100644 --- a/wrappers/csharp/DeviceController.cs +++ b/wrappers/csharp/DeviceController.cs @@ -58,6 +58,30 @@ public string FetchLog() return Encoding.ASCII.GetString(output).TrimEnd('\0'); } + public Status GetColorGains(out int red, out int blue) + { + IntPtr outRedPtr = Marshal.AllocHGlobal(sizeof(int)); + IntPtr outBluePtr = Marshal.AllocHGlobal(sizeof(int)); + + var status = rsid_get_color_gains(_handle, outRedPtr, outBluePtr); + if (status == Status.Ok) + { + red = Marshal.ReadInt32(outRedPtr); + blue = Marshal.ReadInt32(outBluePtr); + } + else + { + red = blue = 0; + + } + return status; + } + + public Status SetColorGains(int red, int blue) + { + return rsid_set_color_gains(_handle, red, blue); + } + public void Disconnect() { rsid_disconnect_controller(_handle); @@ -106,5 +130,11 @@ protected virtual void Dispose(bool disposing) [DllImport(Shared.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] static extern Status rsid_fetch_log(IntPtr rsid_device_controller, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] output, int len); + + [DllImport(Shared.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + static extern Status rsid_set_color_gains(IntPtr rsid_device_controller, int red, int blue); + + [DllImport(Shared.DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] + static extern Status rsid_get_color_gains(IntPtr rsid_device_controller, IntPtr red, IntPtr blue); } }