blob: 2f0688d1aa2500109a48a3ce62dac270ba949ab7 [file] [log] [blame]
// Copyright 2017 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 "composite_device.h"
#include <unistd.h>
#include "eeprom_device.h"
#include "mcu2_device.h"
#include "utilities.h"
#include "video_device.h"
constexpr unsigned int kLogiRebootingWaitTime = 10;
CompositeDevice::CompositeDevice(std::string videoPid,
std::string eepromPid,
std::string mcu2Pid) {
devices.push_back(std::make_shared<VideoDevice>(videoPid));
devices.push_back(std::make_shared<EepromDevice>(eepromPid));
devices.push_back(std::make_shared<Mcu2Device>(mcu2Pid));
openDevices();
}
CompositeDevice::~CompositeDevice() {
closeDevices();
}
int CompositeDevice::openDevices() {
int error = kLogiErrorUnknown;
for (auto device : devices) {
// open each device
error = device->openDevice();
if (error)
break;
}
return error;
}
void CompositeDevice::closeDevices() {
for (auto device : devices)
device->closeDevice();
}
int CompositeDevice::getDevicesVersion(std::map<int, std::string>* versionMap) {
std::map<int, std::string> output;
int error = kLogiErrorUnknown;
for (auto device : devices) {
std::string version;
if ((error = device->getDeviceVersion(&version)))
break; // error getting version, break out and return
(*versionMap)[device->deviceType] = version;
}
return error;
}
int CompositeDevice::getDevicesName(std::map<int, std::string>* nameMap) {
int error = kLogiErrorUnknown;
for (auto device : devices) {
std::string name;
if ((error = device->getDeviceName(&name)))
break; // error getting name, break out and return
(*nameMap)[device->deviceType] = name;
}
return error;
}
int CompositeDevice::getImagesVersion(std::map<int, std::string>* versionMap) {
int error = kLogiErrorUnknown;
std::string version;
for (auto device : devices) {
std::string version;
std::vector<char> buffer = getImageBuffer(device->deviceType);
error = device->verifyImage(buffer);
if (error)
return error; // failed to verify image
if ((error = device->getImageVersion(buffer, &version)))
return error; // failed to get image version
(*versionMap)[device->deviceType] = version;
}
return error;
}
bool CompositeDevice::isDeviceUpToDate() {
for (auto device : devices) {
std::vector<char> buffer = getImageBuffer(device->deviceType);
std::string imageVersion;
std::string deviceVersion;
device->getDeviceVersion(&deviceVersion);
device->getImageVersion(buffer, &imageVersion);
if (CompareVersions(deviceVersion, imageVersion) < 0)
return false;
}
return true;
}
bool CompositeDevice::isDevicePresent() {
for (auto device : devices) {
std::vector<std::string> devicepath = device->findDevices();
if (devicepath.size() > 0)
return true;
}
return false;
}
int CompositeDevice::performUpdate() {
int error = kLogiErrorUnknown;
std::shared_ptr<USBDevice> videoDevice;
if (!isDeviceUpToDate()) {
for (auto device : devices) {
std::vector<char> buffer = getImageBuffer(device->deviceType);
error = device->performUpdate(buffer);
if (error)
return error; // failed to update
if (device->deviceType == kLogiDeviceVideo)
videoDevice = device; // get a hold of video device to do reboot later
}
// updated ok, reboot devices
for (auto device : devices) {
if (device->deviceType != kLogiDeviceVideo)
device->closeDevice(); // close all other device before rebooting
}
videoDevice->rebootDevice();
sleep(kLogiRebootingWaitTime); // wait for device to reboot
openDevices(); // make sure to reopen devices
}
return kLogiErrorNoError;
}
std::vector<char> CompositeDevice::getImageBuffer(int deviceType) {
std::vector<char> buffer;
switch (deviceType) {
case kLogiDeviceVideo:
buffer = videoImageBuffer;
break;
case kLogiDeviceEeprom:
buffer = eepromImageBuffer;
break;
case kLogiDeviceMcu2:
buffer = mcu2ImageBuffer;
break;
default:
break;
}
return buffer;
}