/* * Copyright (C) 2026 oxmc / PawletOS * SPDX-License-Identifier: Apache-2.0 */ #include "manifest.h" #include #include #include namespace pawlet::hwupdate { namespace { std::vector StrArray(const Json::Value& v) { std::vector out; if (v.isArray()) { for (const auto& e : v) { if (e.isString()) out.push_back(e.asString()); } } return out; } void ReadIdentifiers(const Json::Value& ids, std::string& usbVid, std::string& usbPid, std::vector& dtCompat) { if (!ids.isObject()) return; usbVid = ids.get("usb_vendor_id", "").asString(); usbPid = ids.get("usb_product_id", "").asString(); dtCompat = StrArray(ids["device_tree_compatible"]); } } // namespace std::optional LoadManifest(const std::string& path) { std::ifstream in(path, std::ios::binary); if (!in) { LOG(ERROR) << "hwupdate: cannot open manifest " << path; return std::nullopt; } Json::Value root; Json::CharReaderBuilder b; std::string errs; if (!Json::parseFromStream(b, in, &root, &errs)) { LOG(ERROR) << "hwupdate: manifest parse error: " << errs; return std::nullopt; } Manifest m; m.schemaVersion = root.get("schema_version", 0).asInt(); if (m.schemaVersion != 1) { LOG(ERROR) << "hwupdate: unsupported manifest schema_version " << m.schemaVersion; return std::nullopt; } m.device = root.get("device", "").asString(); m.buildVersion = root.get("build_version", "").asString(); for (const auto& p : root["supported_hardware"]) { ManifestProduct prod; prod.id = p.get("id", "").asString(); prod.manufacturer = p.get("manufacturer", "").asString(); prod.cls = p.get("class", "").asString(); prod.support = p.get("support", "full").asString(); prod.supportedRevisions = StrArray(p["supported_revisions"]); ReadIdentifiers(p["identifiers"], prod.usbVendorId, prod.usbProductId, prod.dtCompatible); for (const auto& c : p["components"]) { ManifestComponent comp; comp.id = c.get("id", "").asString(); comp.cls = c.get("class", "").asString(); comp.role = c.get("role", "").asString(); comp.support = c.get("support", "full").asString(); comp.supportedRevisions = StrArray(c["supported_revisions"]); comp.installerHandlers = StrArray(c["installer_handlers"]); ReadIdentifiers(c["identifiers"], comp.usbVendorId, comp.usbProductId, comp.dtCompatible); // Fall back to the product's identifiers if the component omits them. if (comp.usbVendorId.empty()) comp.usbVendorId = prod.usbVendorId; if (comp.usbProductId.empty()) comp.usbProductId = prod.usbProductId; if (comp.dtCompatible.empty()) comp.dtCompatible = prod.dtCompatible; prod.components.push_back(std::move(comp)); } m.products.push_back(std::move(prod)); } LOG(INFO) << "hwupdate: loaded manifest device=" << m.device << " products=" << m.products.size(); return m; } } // namespace pawlet::hwupdate