blob: 8a30bfdc2807a778ee1607f5bffe826b72fc5116 [file] [log] [blame]
// Copyright 2019 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 "target_device.h"
#include <iostream>
#include <memory>
#include <base/files/file.h>
#include <base/files/file_util.h>
#include "utilities.h"
#include "model_one_device.h"
#include "model_two_device.h"
namespace {
const char kVideoImagePath[] = "/lib/firmware/aver/";
const char kDefaultHidDeviceMountPoint[] = "../../sys/class/hidraw/";
const char kDevPath[] = "/dev/";
const char kVendorIdPath[] = "/device/../../idVendor";
const char kProductIdPath[] = "/device/../../idProduct";
const char kAverCAM520Name[] = "CAM520";
const char kAverCAM540Name[] = "CAM540";
const char kCAM520FwMidName[] = "";
const char kNewCAM540FwMidName[] = "videoh.dat";
constexpr unsigned int kDeviceVideo = 0;
constexpr unsigned int kAVerVendorID = 0x2574;
constexpr unsigned int kAVerCAM520ProductID = 0x0910;
constexpr unsigned int kAVerCAM340PlusProductID = 0x0980;
constexpr unsigned int kAVerCAM540ProductID = 0x0970;
constexpr unsigned int kAVerNewCAM540ProductID = 0x09A0;
} // namespace
TargetDevice::TargetDevice()
: is_untar_file_necessary_(true) {}
TargetDevice::~TargetDevice() {}
bool TargetDevice::AddDevice() {
for (auto it = product_info_.begin(); it != product_info_.end(); it++) {
int hid_type;
std::string device_name;
std::string fw_mid_name;
switch (it->first) {
case kAVerCAM520ProductID:
hid_type = kModelOneDevice;
device_name = kAverCAM520Name;
fw_mid_name = kCAM520FwMidName;
is_untar_file_necessary_ = false;
break;
case kAVerNewCAM540ProductID:
hid_type = kModelOneDevice;
device_name = kAverCAM540Name;
fw_mid_name = kNewCAM540FwMidName;
break;
case kAVerCAM340PlusProductID:
case kAVerCAM540ProductID:
hid_type = kModelTwoDevice;
break;
default:
hid_type = kModelUndefine;
break;
}
switch (hid_type) {
case kModelOneDevice:
devices_.push_back(std::make_unique<ModelOneDevice>(
device_name, it->second, fw_mid_name));
break;
case kModelTwoDevice:
devices_.push_back(std::make_unique<ModelTwoDevice>(it->second));
break;
default:
break;
}
}
if (devices_.empty())
return false;
return true;
}
AverStatus TargetDevice::OpenDevice() {
AverStatus status;
for (const auto& device : devices_) {
status = device->OpenDevice();
if (status != AverStatus::NO_ERROR)
return status;
}
return status;
}
AverStatus TargetDevice::GetDeviceVersion(std::string* device_version) {
AverStatus status;
status = devices_[kDeviceVideo]->GetDeviceVersion(device_version);
return status;
}
AverStatus TargetDevice::GetImageVersion(std::string* image_version) {
AverStatus status;
std::string device_version;
status = devices_[kDeviceVideo]->GetDeviceVersion(&device_version);
if (status != AverStatus::NO_ERROR)
return status;
status = devices_[kDeviceVideo]->GetImageVersion(device_version,
image_version);
return status;
}
AverStatus TargetDevice::IsDeviceUpToDate(bool force) {
AverStatus status = devices_[kDeviceVideo]->IsDeviceUpToDate(force);
return status;
}
AverStatus TargetDevice::PerformUpdate() {
AverStatus status = AverStatus::NO_ERROR;
if (is_untar_file_necessary_) {
status = UntarFirmware();
if (status != AverStatus::NO_ERROR)
return status;
}
for (const auto& device : devices_) {
status = device->PerformUpdate(temp_path_);
if (status != AverStatus::NO_ERROR)
break;
}
if (is_untar_file_necessary_) {
if (!base::DeleteFile(temp_path_, true))
LOG(ERROR) << "Failed to delete untar firmware.";
}
return status;
}
bool TargetDevice::FindHidDevicesByPid(uint64_t which_device) {
std::vector<std::string> contents;
bool get_ok = GetDirectoryContents(kDefaultHidDeviceMountPoint, &contents);
if (!get_ok)
return false;
base::FilePath hid_dir(kDefaultHidDeviceMountPoint);
for (auto const& content : contents) {
if (content.compare(".") == 0 || content.compare("..") == 0)
continue;
std::string vid;
std::string pid;
base::FilePath vid_path = hid_dir.Append(content + kVendorIdPath);
base::FilePath pid_path = hid_dir.Append(content + kProductIdPath);
if (!ReadFileContent(vid_path, &vid))
continue;
int vidnum = 0;
int pidnum = 0;
if (!ConvertHexStringToInt(vid, &vidnum))
continue;
if (!ReadFileContent(pid_path, &pid))
continue;
if (!ConvertHexStringToInt(pid, &pidnum))
continue;
if (vidnum == kAVerVendorID) {
// Target device may be a composite device with video and audio
if (pidnum == which_device || pidnum == (which_device + 1))
product_info_[pidnum] = kDevPath + content;
}
}
if (product_info_.empty())
return false;
return true;
}
AverStatus TargetDevice::UntarFirmware() {
std::string file_path = kVideoImagePath;
std::string firmware_version;
GetImageVersion(&firmware_version);
file_path.append(firmware_version);
if (!base::CreateNewTempDirectory("aver_updater_tmp_dir", &temp_path_)) {
LOG(ERROR) << "Failed to create temp directory.";
return AverStatus::FAILED_CREATE_TMP_PATH;
}
bool ok = false;
ok = ExtractTarFile(temp_path_, file_path);
if (!ok)
return AverStatus::FAILED_EXTRACT_COMPRESSED_FW;
return AverStatus::NO_ERROR;
}