Removed using namespace directive for class member function definitions in source files
This commit is contained in:
@@ -11,11 +11,11 @@
|
||||
#include "src/Helpers/Paths.hpp"
|
||||
#include "Exceptions/InvalidConfig.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
using namespace Bloom::Events;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom
|
||||
{
|
||||
using namespace Exceptions;
|
||||
|
||||
int Application::run(const std::vector<std::string>& arguments) {
|
||||
int Application::run(const std::vector<std::string>& arguments) {
|
||||
try {
|
||||
this->setName("Bloom");
|
||||
|
||||
@@ -70,22 +70,24 @@ int Application::run(const std::vector<std::string>& arguments) {
|
||||
this->applicationEventListener->waitAndDispatch();
|
||||
}
|
||||
|
||||
} catch (const InvalidConfig& exception) {
|
||||
}
|
||||
catch (const InvalidConfig& exception) {
|
||||
Logger::error(exception.getMessage());
|
||||
|
||||
} catch (const Exception& exception) {
|
||||
}
|
||||
catch (const Exception& exception) {
|
||||
Logger::error(exception.getMessage());
|
||||
}
|
||||
|
||||
this->shutdown();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
bool Application::isRunningAsRoot() {
|
||||
bool Application::isRunningAsRoot() {
|
||||
return geteuid() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::startup() {
|
||||
void Application::startup() {
|
||||
auto applicationEventListener = this->applicationEventListener;
|
||||
this->eventManager.registerListener(applicationEventListener);
|
||||
applicationEventListener->registerCallbackForEventType<Events::ShutdownApplication>(
|
||||
@@ -117,9 +119,9 @@ void Application::startup() {
|
||||
this->startDebugServer();
|
||||
|
||||
Thread::setThreadState(ThreadState::READY);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::shutdown() {
|
||||
void Application::shutdown() {
|
||||
auto appState = Thread::getThreadState();
|
||||
if (appState == ThreadState::STOPPED || appState == ThreadState::SHUTDOWN_INITIATED) {
|
||||
return;
|
||||
@@ -134,9 +136,9 @@ void Application::shutdown() {
|
||||
|
||||
this->saveProjectSettings();
|
||||
Thread::setThreadState(ThreadState::STOPPED);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::loadProjectSettings() {
|
||||
void Application::loadProjectSettings() {
|
||||
const auto projectSettingsPath = Paths::projectSettingsPath();
|
||||
auto jsonSettingsFile = QFile(QString::fromStdString(projectSettingsPath));
|
||||
|
||||
@@ -152,7 +154,8 @@ void Application::loadProjectSettings() {
|
||||
this->projectSettings = ProjectSettings(jsonObject);
|
||||
return;
|
||||
|
||||
} catch (const std::exception& exception) {
|
||||
}
|
||||
catch (const std::exception& exception) {
|
||||
Logger::error(
|
||||
"Failed to load project settings from " + projectSettingsPath + " - " + exception.what()
|
||||
);
|
||||
@@ -160,9 +163,9 @@ void Application::loadProjectSettings() {
|
||||
}
|
||||
|
||||
this->projectSettings = ProjectSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::saveProjectSettings() {
|
||||
void Application::saveProjectSettings() {
|
||||
if (!this->projectSettings.has_value()) {
|
||||
return;
|
||||
}
|
||||
@@ -186,14 +189,15 @@ void Application::saveProjectSettings() {
|
||||
jsonSettingsFile.write(jsonDocument.toJson());
|
||||
jsonSettingsFile.close();
|
||||
|
||||
} catch (const Exception& exception) {
|
||||
}
|
||||
catch (const Exception& exception) {
|
||||
Logger::error(
|
||||
"Failed to save project settings - " + exception.getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::loadProjectConfiguration() {
|
||||
void Application::loadProjectConfiguration() {
|
||||
auto jsonConfigFile = QFile(QString::fromStdString(Paths::projectConfigPath()));
|
||||
|
||||
if (!jsonConfigFile.exists()) {
|
||||
@@ -223,25 +227,29 @@ void Application::loadProjectConfiguration() {
|
||||
if (this->environmentConfig->insightConfig.has_value()) {
|
||||
this->insightConfig = this->environmentConfig->insightConfig.value();
|
||||
|
||||
} else if (this->projectConfig->insightConfig.has_value()) {
|
||||
}
|
||||
else if (this->projectConfig->insightConfig.has_value()) {
|
||||
this->insightConfig = this->projectConfig->insightConfig.value();
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
throw InvalidConfig("Insight configuration missing.");
|
||||
}
|
||||
|
||||
if (this->environmentConfig->debugServerConfig.has_value()) {
|
||||
this->debugServerConfig = this->environmentConfig->debugServerConfig.value();
|
||||
|
||||
} else if (this->projectConfig->debugServerConfig.has_value()) {
|
||||
}
|
||||
else if (this->projectConfig->debugServerConfig.has_value()) {
|
||||
this->debugServerConfig = this->projectConfig->debugServerConfig.value();
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
throw InvalidConfig("Debug server configuration missing.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Application::presentHelpText() {
|
||||
int Application::presentHelpText() {
|
||||
/*
|
||||
* Silence all logging here, as we're just to display the help text and then exit the application. Any
|
||||
* further logging will just be noise.
|
||||
@@ -258,16 +266,17 @@ int Application::presentHelpText() {
|
||||
if (!helpFile.open(QIODevice::ReadOnly)) {
|
||||
// This should never happen - if it does, something has gone very wrong
|
||||
throw Exception(
|
||||
"Failed to open help file - please report this issue at " + Paths::homeDomainName() + "/report-issue"
|
||||
"Failed to open help file - please report this issue at " + Paths::homeDomainName()
|
||||
+ "/report-issue"
|
||||
);
|
||||
}
|
||||
|
||||
std::cout << "Bloom v" << Application::VERSION.toString() << "\n";
|
||||
std::cout << QTextStream(&helpFile).readAll().toUtf8().constData() << "\n";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int Application::presentVersionText() {
|
||||
int Application::presentVersionText() {
|
||||
Logger::silence();
|
||||
|
||||
std::cout << "Bloom v" << Application::VERSION.toString() << "\n";
|
||||
@@ -279,10 +288,12 @@ int Application::presentVersionText() {
|
||||
std::cout << Paths::homeDomainName() + "/\n";
|
||||
std::cout << "Nav Mohammed\n";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int Application::initProject() {
|
||||
auto configFile = QFile(QString::fromStdString(std::filesystem::current_path().string() + "/bloom.json"));
|
||||
int Application::initProject() {
|
||||
auto configFile = QFile(
|
||||
QString::fromStdString(std::filesystem::current_path().string() + "/bloom.json")
|
||||
);
|
||||
|
||||
if (configFile.exists()) {
|
||||
throw Exception("Bloom configuration file (bloom.json) already exists in working directory.");
|
||||
@@ -294,10 +305,8 @@ int Application::initProject() {
|
||||
*
|
||||
* We simply copy the template file into the user's working directory.
|
||||
*/
|
||||
auto templateConfigFile = QFile(QString::fromStdString(
|
||||
Paths::compiledResourcesPath()
|
||||
+ "/resources/bloom.template.json"
|
||||
)
|
||||
auto templateConfigFile = QFile(
|
||||
QString::fromStdString(Paths::compiledResourcesPath()+ "/resources/bloom.template.json")
|
||||
);
|
||||
|
||||
if (!templateConfigFile.open(QIODevice::ReadOnly)) {
|
||||
@@ -318,21 +327,21 @@ int Application::initProject() {
|
||||
|
||||
Logger::info("Bloom configuration file (bloom.json) created in working directory.");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::startSignalHandler() {
|
||||
void Application::startSignalHandler() {
|
||||
this->signalHandlerThread = std::thread(&SignalHandler::run, std::ref(this->signalHandler));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::stopSignalHandler() {
|
||||
void Application::stopSignalHandler() {
|
||||
if (this->signalHandler.getThreadState() != ThreadState::STOPPED
|
||||
&& this->signalHandler.getThreadState() != ThreadState::UNINITIALISED
|
||||
) {
|
||||
this->signalHandler.triggerShutdown();
|
||||
|
||||
/*
|
||||
* Send meaningless signal to the SignalHandler thread to have it shutdown. The signal will pull it out of a
|
||||
* blocking state and allow it to action the shutdown. See SignalHandler::run() for more.
|
||||
* Send meaningless signal to the SignalHandler thread to have it shutdown. The signal will pull it out of
|
||||
* a blocking state and allow it to action the shutdown. See SignalHandler::run() for more.
|
||||
*/
|
||||
pthread_kill(this->signalHandlerThread.native_handle(), SIGUSR1);
|
||||
}
|
||||
@@ -342,9 +351,9 @@ void Application::stopSignalHandler() {
|
||||
this->signalHandlerThread.join();
|
||||
Logger::debug("SignalHandler thread joined");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::startTargetController() {
|
||||
void Application::startTargetController() {
|
||||
this->targetController = std::make_unique<TargetController>(
|
||||
this->eventManager,
|
||||
this->projectConfig.value(),
|
||||
@@ -356,14 +365,15 @@ void Application::startTargetController() {
|
||||
this->targetController.get()
|
||||
);
|
||||
|
||||
auto tcStateChangeEvent = this->applicationEventListener->waitForEvent<Events::TargetControllerThreadStateChanged>();
|
||||
auto tcStateChangeEvent =
|
||||
this->applicationEventListener->waitForEvent<Events::TargetControllerThreadStateChanged>();
|
||||
|
||||
if (!tcStateChangeEvent.has_value() || tcStateChangeEvent->get()->getState() != ThreadState::READY) {
|
||||
throw Exception("TargetController failed to startup.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::stopTargetController() {
|
||||
void Application::stopTargetController() {
|
||||
if (this->targetController == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -381,12 +391,14 @@ void Application::stopTargetController() {
|
||||
this->targetControllerThread.join();
|
||||
Logger::debug("TargetController thread joined");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::startDebugServer() {
|
||||
void Application::startDebugServer() {
|
||||
auto supportedDebugServers = this->getSupportedDebugServers();
|
||||
if (!supportedDebugServers.contains(this->debugServerConfig->name)) {
|
||||
throw Exceptions::InvalidConfig("DebugServer \"" + this->debugServerConfig->name + "\" not found.");
|
||||
throw Exceptions::InvalidConfig(
|
||||
"DebugServer \"" + this->debugServerConfig->name + "\" not found."
|
||||
);
|
||||
}
|
||||
|
||||
this->debugServer = supportedDebugServers.at(this->debugServerConfig->name)();
|
||||
@@ -402,9 +414,9 @@ void Application::startDebugServer() {
|
||||
if (!dsStateChangeEvent.has_value() || dsStateChangeEvent->get()->getState() != ThreadState::READY) {
|
||||
throw Exception("DebugServer failed to startup.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::stopDebugServer() {
|
||||
void Application::stopDebugServer() {
|
||||
if (this->debugServer == nullptr) {
|
||||
// DebugServer hasn't been resolved yet.
|
||||
return;
|
||||
@@ -423,23 +435,24 @@ void Application::stopDebugServer() {
|
||||
this->debugServerThread.join();
|
||||
Logger::debug("DebugServer thread joined");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::onTargetControllerThreadStateChanged(const Events::TargetControllerThreadStateChanged& event) {
|
||||
void Application::onTargetControllerThreadStateChanged(const Events::TargetControllerThreadStateChanged& event) {
|
||||
if (event.getState() == ThreadState::STOPPED || event.getState() == ThreadState::SHUTDOWN_INITIATED) {
|
||||
// TargetController has unexpectedly shutdown - it must have encountered a fatal error.
|
||||
this->shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::onShutdownApplicationRequest(const Events::ShutdownApplication&) {
|
||||
void Application::onShutdownApplicationRequest(const Events::ShutdownApplication&) {
|
||||
Logger::debug("ShutdownApplication event received.");
|
||||
this->shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::onDebugServerThreadStateChanged(const Events::DebugServerThreadStateChanged& event) {
|
||||
void Application::onDebugServerThreadStateChanged(const Events::DebugServerThreadStateChanged& event) {
|
||||
if (event.getState() == ThreadState::STOPPED || event.getState() == ThreadState::SHUTDOWN_INITIATED) {
|
||||
// DebugServer has unexpectedly shutdown - it must have encountered a fatal error.
|
||||
this->shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
#include "src/Exceptions/InvalidConfig.hpp"
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers;
|
||||
using namespace Bloom::Events;
|
||||
namespace Bloom::DebugServers
|
||||
{
|
||||
using namespace Bloom::Events;
|
||||
|
||||
void DebugServer::run() {
|
||||
void DebugServer::run() {
|
||||
try {
|
||||
this->startup();
|
||||
|
||||
@@ -23,9 +24,9 @@ void DebugServer::run() {
|
||||
}
|
||||
|
||||
this->shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void DebugServer::startup() {
|
||||
void DebugServer::startup() {
|
||||
this->setName("DS");
|
||||
Logger::info("Starting DebugServer");
|
||||
|
||||
@@ -43,10 +44,12 @@ void DebugServer::startup() {
|
||||
|
||||
this->init();
|
||||
this->setThreadStateAndEmitEvent(ThreadState::READY);
|
||||
}
|
||||
}
|
||||
|
||||
void DebugServer::shutdown() {
|
||||
if (this->getThreadState() == ThreadState::STOPPED || this->getThreadState() == ThreadState::SHUTDOWN_INITIATED) {
|
||||
void DebugServer::shutdown() {
|
||||
if (this->getThreadState() == ThreadState::STOPPED
|
||||
|| this->getThreadState() == ThreadState::SHUTDOWN_INITIATED
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -55,8 +58,9 @@ void DebugServer::shutdown() {
|
||||
this->close();
|
||||
this->setThreadStateAndEmitEvent(ThreadState::STOPPED);
|
||||
this->eventManager.deregisterListener(this->eventListener->getId());
|
||||
}
|
||||
}
|
||||
|
||||
void DebugServer::onShutdownDebugServerEvent(const Events::ShutdownDebugServer& event) {
|
||||
void DebugServer::onShutdownDebugServerEvent(const Events::ShutdownDebugServer& event) {
|
||||
this->shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,19 +2,20 @@
|
||||
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugServers::Gdb
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterType;
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterType;
|
||||
|
||||
void AvrGdbRsp::init() {
|
||||
void AvrGdbRsp::init() {
|
||||
this->loadRegisterMappings();
|
||||
|
||||
GdbRspDebugServer::init();
|
||||
}
|
||||
}
|
||||
|
||||
void AvrGdbRsp::loadRegisterMappings() {
|
||||
void AvrGdbRsp::loadRegisterMappings() {
|
||||
auto& registerDescriptorsByType = this->targetDescriptor.registerDescriptorsByType;
|
||||
if (!registerDescriptorsByType.contains(TargetRegisterType::STATUS_REGISTER)) {
|
||||
throw Exception("Missing status register descriptor");
|
||||
@@ -41,7 +42,9 @@ void AvrGdbRsp::loadRegisterMappings() {
|
||||
* we're assuming that the registers will be laid out in the correct order, in memory. I think this assumption is
|
||||
* fair.
|
||||
*/
|
||||
const auto& gpRegisterDescriptors = registerDescriptorsByType.at(TargetRegisterType::GENERAL_PURPOSE_REGISTER);
|
||||
const auto& gpRegisterDescriptors = registerDescriptorsByType.at(
|
||||
TargetRegisterType::GENERAL_PURPOSE_REGISTER
|
||||
);
|
||||
|
||||
// General purpose CPU registers
|
||||
GdbRegisterNumberType regNumber = 0;
|
||||
@@ -81,7 +84,9 @@ void AvrGdbRsp::loadRegisterMappings() {
|
||||
"Stack Pointer Register"
|
||||
);
|
||||
|
||||
this->registerDescriptorsByGdbNumber.insert(std::pair(stackPointerDescriptor.number, stackPointerDescriptor));
|
||||
this->registerDescriptorsByGdbNumber.insert(
|
||||
std::pair(stackPointerDescriptor.number, stackPointerDescriptor)
|
||||
);
|
||||
this->targetRegisterDescriptorsByGdbNumber.insert(std::pair(
|
||||
stackPointerDescriptor.number,
|
||||
*(registerDescriptorsByType.at(TargetRegisterType::STACK_POINTER).begin())
|
||||
@@ -110,31 +115,34 @@ void AvrGdbRsp::loadRegisterMappings() {
|
||||
throw Exception("AVR8 stack pointer target register size exceeds the GDB register size.");
|
||||
}
|
||||
|
||||
if (registerDescriptorsByType.at(TargetRegisterType::PROGRAM_COUNTER).size() > programCounterDescriptor.size) {
|
||||
if (
|
||||
registerDescriptorsByType.at(TargetRegisterType::PROGRAM_COUNTER).size() > programCounterDescriptor.size
|
||||
) {
|
||||
throw Exception("AVR8 program counter size exceeds the GDB register size.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<GdbRegisterNumberType> AvrGdbRsp::getRegisterNumberFromTargetRegisterDescriptor(
|
||||
std::optional<GdbRegisterNumberType> AvrGdbRsp::getRegisterNumberFromTargetRegisterDescriptor(
|
||||
const Targets::TargetRegisterDescriptor& registerDescriptor
|
||||
) {
|
||||
) {
|
||||
return this->targetRegisterDescriptorsByGdbNumber.valueAt(registerDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
const RegisterDescriptor& AvrGdbRsp::getRegisterDescriptorFromNumber(GdbRegisterNumberType number) {
|
||||
const RegisterDescriptor& AvrGdbRsp::getRegisterDescriptorFromNumber(GdbRegisterNumberType number) {
|
||||
if (this->registerDescriptorsByGdbNumber.contains(number)) {
|
||||
return this->registerDescriptorsByGdbNumber.at(number);
|
||||
}
|
||||
|
||||
throw Exception("Unknown register from GDB - register number (" + std::to_string(number)
|
||||
+ ") not mapped to any GDB register descriptor.");
|
||||
}
|
||||
}
|
||||
|
||||
const TargetRegisterDescriptor& AvrGdbRsp::getTargetRegisterDescriptorFromNumber(GdbRegisterNumberType number) {
|
||||
const TargetRegisterDescriptor& AvrGdbRsp::getTargetRegisterDescriptorFromNumber(GdbRegisterNumberType number) {
|
||||
if (this->targetRegisterDescriptorsByGdbNumber.contains(number)) {
|
||||
return this->targetRegisterDescriptorsByGdbNumber.at(number);
|
||||
}
|
||||
|
||||
throw Exception("Unknown register from GDB - register number (" + std::to_string(number)
|
||||
+ ") not mapped to any target register descriptor.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
#include "src/DebugServers/GdbRsp/GdbRspDebugServer.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
|
||||
void CommandPacket::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
namespace Bloom::DebugServers::Gdb::CommandPackets
|
||||
{
|
||||
void CommandPacket::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
gdbRspDebugServer.handleGdbPacket(*this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,13 @@
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb;
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
namespace Bloom::DebugServers::Gdb
|
||||
{
|
||||
using CommandPackets::CommandPacket;
|
||||
|
||||
std::vector<std::vector<unsigned char>> CommandPacketFactory::extractRawPackets(std::vector<unsigned char> buffer) {
|
||||
std::vector<std::vector<unsigned char>> CommandPacketFactory::extractRawPackets(
|
||||
std::vector<unsigned char> buffer
|
||||
) {
|
||||
std::vector<std::vector<unsigned char>> output;
|
||||
|
||||
std::size_t bufferIndex;
|
||||
@@ -81,9 +84,9 @@ std::vector<std::vector<unsigned char>> CommandPacketFactory::extractRawPackets(
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<CommandPacket> CommandPacketFactory::create(std::vector<unsigned char> rawPacket) {
|
||||
std::unique_ptr<CommandPacket> CommandPacketFactory::create(std::vector<unsigned char> rawPacket) {
|
||||
if (rawPacket.size() == 5 && rawPacket[1] == 0x03) {
|
||||
// This is an interrupt request - create a fake packet for it
|
||||
return std::make_unique<CommandPackets::InterruptExecution>(rawPacket);
|
||||
@@ -98,32 +101,41 @@ std::unique_ptr<CommandPacket> CommandPacketFactory::create(std::vector<unsigned
|
||||
*/
|
||||
if (rawPacketString.find("qSupported") == 1) {
|
||||
return std::make_unique<CommandPackets::SupportedFeaturesQuery>(rawPacket);
|
||||
}
|
||||
|
||||
} else if (rawPacketString[1] == 'g' || rawPacketString[1] == 'p') {
|
||||
if (rawPacketString[1] == 'g' || rawPacketString[1] == 'p') {
|
||||
return std::make_unique<CommandPackets::ReadRegisters>(rawPacket);
|
||||
}
|
||||
|
||||
} else if (rawPacketString[1] == 'P') {
|
||||
if (rawPacketString[1] == 'P') {
|
||||
return std::make_unique<CommandPackets::WriteRegister>(rawPacket);
|
||||
}
|
||||
|
||||
} else if (rawPacketString[1] == 'c') {
|
||||
if (rawPacketString[1] == 'c') {
|
||||
return std::make_unique<CommandPackets::ContinueExecution>(rawPacket);
|
||||
}
|
||||
|
||||
} else if (rawPacketString[1] == 's') {
|
||||
if (rawPacketString[1] == 's') {
|
||||
return std::make_unique<CommandPackets::StepExecution>(rawPacket);
|
||||
}
|
||||
|
||||
} else if (rawPacketString[1] == 'm') {
|
||||
if (rawPacketString[1] == 'm') {
|
||||
return std::make_unique<CommandPackets::ReadMemory>(rawPacket);
|
||||
}
|
||||
|
||||
} else if (rawPacketString[1] == 'M') {
|
||||
if (rawPacketString[1] == 'M') {
|
||||
return std::make_unique<CommandPackets::WriteMemory>(rawPacket);
|
||||
}
|
||||
|
||||
} else if (rawPacketString[1] == 'Z') {
|
||||
if (rawPacketString[1] == 'Z') {
|
||||
return std::make_unique<CommandPackets::SetBreakpoint>(rawPacket);
|
||||
}
|
||||
|
||||
} else if (rawPacketString[1] == 'z') {
|
||||
if (rawPacketString[1] == 'z') {
|
||||
return std::make_unique<CommandPackets::RemoveBreakpoint>(rawPacket);
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_unique<CommandPacket>(rawPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,17 @@
|
||||
|
||||
#include "src/DebugServers/GdbRsp/GdbRspDebugServer.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
|
||||
void ContinueExecution::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
namespace Bloom::DebugServers::Gdb::CommandPackets
|
||||
{
|
||||
void ContinueExecution::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
gdbRspDebugServer.handleGdbPacket(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void ContinueExecution::init() {
|
||||
void ContinueExecution::init() {
|
||||
if (this->data.size() > 1) {
|
||||
this->fromProgramCounter = static_cast<std::uint32_t>(
|
||||
std::stoi(std::string(this->data.begin(), this->data.end()), nullptr, 16)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
#include "src/DebugServers/GdbRsp/GdbRspDebugServer.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
|
||||
void InterruptExecution::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
namespace Bloom::DebugServers::Gdb::CommandPackets
|
||||
{
|
||||
void InterruptExecution::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
gdbRspDebugServer.handleGdbPacket(*this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
|
||||
#include "src/DebugServers/GdbRsp/GdbRspDebugServer.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugServers::Gdb::CommandPackets
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void ReadMemory::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
void ReadMemory::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
gdbRspDebugServer.handleGdbPacket(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadMemory::init() {
|
||||
void ReadMemory::init() {
|
||||
if (this->data.size() < 4) {
|
||||
throw Exception("Invalid packet length");
|
||||
}
|
||||
@@ -26,7 +27,9 @@ void ReadMemory::init() {
|
||||
auto packetSegments = packetString.split(",");
|
||||
|
||||
if (packetSegments.size() != 2) {
|
||||
throw Exception("Unexpected number of segments in packet data: " + std::to_string(packetSegments.size()));
|
||||
throw Exception(
|
||||
"Unexpected number of segments in packet data: " + std::to_string(packetSegments.size())
|
||||
);
|
||||
}
|
||||
|
||||
bool conversionStatus = false;
|
||||
@@ -41,4 +44,5 @@ void ReadMemory::init() {
|
||||
if (!conversionStatus) {
|
||||
throw Exception("Failed to parse read length from read memory packet data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
|
||||
#include "src/DebugServers/GdbRsp/GdbRspDebugServer.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
|
||||
void ReadRegisters::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
namespace Bloom::DebugServers::Gdb::CommandPackets
|
||||
{
|
||||
void ReadRegisters::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
gdbRspDebugServer.handleGdbPacket(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadRegisters::init() {
|
||||
void ReadRegisters::init() {
|
||||
if (this->data.size() >= 2 && this->data.front() == 'p') {
|
||||
// This command packet is requesting a specific register
|
||||
this->registerNumber = static_cast<size_t>(std::stoi(std::string(this->data.begin() + 1, this->data.end())));
|
||||
this->registerNumber = static_cast<size_t>(
|
||||
std::stoi(std::string(this->data.begin() + 1, this->data.end()))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,15 @@
|
||||
|
||||
#include "src/DebugServers/GdbRsp/GdbRspDebugServer.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugServers::Gdb::CommandPackets
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void RemoveBreakpoint::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
void RemoveBreakpoint::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
gdbRspDebugServer.handleGdbPacket(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveBreakpoint::init() {
|
||||
void RemoveBreakpoint::init() {
|
||||
if (data.size() < 6) {
|
||||
throw Exception("Unexpected RemoveBreakpoint packet size");
|
||||
}
|
||||
@@ -36,4 +37,5 @@ void RemoveBreakpoint::init() {
|
||||
if (!conversionStatus) {
|
||||
throw Exception("Failed to convert address hex value from RemoveBreakpoint packet.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#include "SetBreakpoint.hpp"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
#include "src/DebugServers/GdbRsp/GdbRspDebugServer.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugServers::Gdb::CommandPackets
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void SetBreakpoint::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
void SetBreakpoint::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
gdbRspDebugServer.handleGdbPacket(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void SetBreakpoint::init() {
|
||||
void SetBreakpoint::init() {
|
||||
if (data.size() < 6) {
|
||||
throw Exception("Unexpected SetBreakpoint packet size");
|
||||
}
|
||||
@@ -37,4 +37,5 @@ void SetBreakpoint::init() {
|
||||
if (!conversionStatus) {
|
||||
throw Exception("Failed to convert address hex value from SetBreakpoint packet.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
#include "StepExecution.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/DebugServers/GdbRsp/GdbRspDebugServer.hpp"
|
||||
#include "StepExecution.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
|
||||
void StepExecution::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
namespace Bloom::DebugServers::Gdb::CommandPackets
|
||||
{
|
||||
void StepExecution::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
gdbRspDebugServer.handleGdbPacket(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void StepExecution::init() {
|
||||
void StepExecution::init() {
|
||||
if (this->data.size() > 1) {
|
||||
this->fromProgramCounter = static_cast<std::uint32_t>(
|
||||
std::stoi(std::string(this->data.begin(), this->data.end()), nullptr, 16)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Bloom::DebugServers::Gdb::CommandPackets
|
||||
/**
|
||||
* The address from which to begin the step.
|
||||
*/
|
||||
std::optional<size_t> fromProgramCounter;
|
||||
std::optional<std::size_t> fromProgramCounter;
|
||||
|
||||
explicit StepExecution(const std::vector<unsigned char>& rawPacket): CommandPacket(rawPacket) {
|
||||
init();
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
|
||||
#include "src/DebugServers/GdbRsp/GdbRspDebugServer.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
|
||||
void SupportedFeaturesQuery::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
namespace Bloom::DebugServers::Gdb::CommandPackets
|
||||
{
|
||||
void SupportedFeaturesQuery::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
gdbRspDebugServer.handleGdbPacket(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void SupportedFeaturesQuery::init() {
|
||||
void SupportedFeaturesQuery::init() {
|
||||
/*
|
||||
* For qSupported packets, supported and unsupported GDB features are reported in the packet
|
||||
* data, where each GDB feature is separated by a semicolon.
|
||||
@@ -40,4 +40,5 @@ void SupportedFeaturesQuery::init() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
|
||||
#include "src/DebugServers/GdbRsp/GdbRspDebugServer.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugServers::Gdb::CommandPackets
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void WriteMemory::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
void WriteMemory::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
gdbRspDebugServer.handleGdbPacket(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteMemory::init() {
|
||||
void WriteMemory::init() {
|
||||
if (this->data.size() < 4) {
|
||||
throw Exception("Invalid packet length");
|
||||
}
|
||||
@@ -25,7 +26,9 @@ void WriteMemory::init() {
|
||||
*/
|
||||
auto packetSegments = packetString.split(",");
|
||||
if (packetSegments.size() != 2) {
|
||||
throw Exception("Unexpected number of segments in packet data: " + std::to_string(packetSegments.size()));
|
||||
throw Exception(
|
||||
"Unexpected number of segments in packet data: " + std::to_string(packetSegments.size())
|
||||
);
|
||||
}
|
||||
|
||||
bool conversionStatus = false;
|
||||
@@ -37,7 +40,10 @@ void WriteMemory::init() {
|
||||
|
||||
auto lengthAndBufferSegments = packetSegments.at(1).split(":");
|
||||
if (lengthAndBufferSegments.size() != 2) {
|
||||
throw Exception("Unexpected number of segments in packet data: " + std::to_string(lengthAndBufferSegments.size()));
|
||||
throw Exception(
|
||||
"Unexpected number of segments in packet data: "
|
||||
+ std::to_string(lengthAndBufferSegments.size())
|
||||
);
|
||||
}
|
||||
|
||||
auto bufferSize = lengthAndBufferSegments.at(0).toUInt(&conversionStatus, 16);
|
||||
@@ -50,4 +56,5 @@ void WriteMemory::init() {
|
||||
if (this->buffer.size() != bufferSize) {
|
||||
throw Exception("Buffer size does not match length value given in write memory packet");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,15 @@
|
||||
#include "src/DebugServers/GdbRsp/GdbRspDebugServer.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugServers::Gdb::CommandPackets
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void WriteRegister::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
void WriteRegister::dispatchToHandler(Gdb::GdbRspDebugServer& gdbRspDebugServer) {
|
||||
gdbRspDebugServer.handleGdbPacket(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteRegister::init() {
|
||||
void WriteRegister::init() {
|
||||
// The P packet updates a single register
|
||||
auto packet = std::string(this->data.begin(), this->data.end());
|
||||
|
||||
@@ -26,4 +27,5 @@ void WriteRegister::init() {
|
||||
this->registerNumber = static_cast<int>(packetSegments.front().mid(1).toUInt(nullptr, 16));
|
||||
this->registerValue = Packet::hexToData(packetSegments.back().toStdString());
|
||||
std::reverse(this->registerValue.begin(), this->registerValue.end());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,19 +14,20 @@
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb;
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
using namespace Bloom::DebugServers::Gdb::ResponsePackets;
|
||||
using namespace Bloom::DebugServers::Gdb::Exceptions;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugServers::Gdb
|
||||
{
|
||||
using namespace CommandPackets;
|
||||
using namespace ResponsePackets;
|
||||
using namespace Exceptions;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void Connection::accept(int serverSocketFileDescriptor) {
|
||||
void Connection::accept(int serverSocketFileDescriptor) {
|
||||
int socketAddressLength = sizeof(this->socketAddress);
|
||||
|
||||
this->socketFileDescriptor = ::accept(
|
||||
serverSocketFileDescriptor,
|
||||
(sockaddr*)& (this->socketAddress),
|
||||
(socklen_t*)& socketAddressLength
|
||||
(sockaddr*) &(this->socketAddress),
|
||||
(socklen_t*) &socketAddressLength
|
||||
);
|
||||
|
||||
if (this->socketFileDescriptor == -1) {
|
||||
@@ -46,23 +47,26 @@ void Connection::accept(int serverSocketFileDescriptor) {
|
||||
event.data.fd = this->socketFileDescriptor;
|
||||
|
||||
if (::epoll_ctl(this->eventFileDescriptor, EPOLL_CTL_ADD, this->socketFileDescriptor, &event) != 0) {
|
||||
throw Exception("Failed to create event FD for GDB client connection - could not add client connection "
|
||||
"socket FD to epoll FD");
|
||||
throw Exception(
|
||||
"Failed to create event FD for GDB client connection - could not add client connection "
|
||||
"socket FD to epoll FD"
|
||||
);
|
||||
}
|
||||
|
||||
this->enableReadInterrupts();
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::close() noexcept {
|
||||
void Connection::close() noexcept {
|
||||
if (this->socketFileDescriptor > 0) {
|
||||
::close(this->socketFileDescriptor);
|
||||
this->socketFileDescriptor = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<CommandPacket>> Connection::readPackets() {
|
||||
std::vector<std::unique_ptr<CommandPacket>> Connection::readPackets() {
|
||||
auto buffer = this->read();
|
||||
Logger::debug("GDB client data received (" + std::to_string(buffer.size()) + " bytes): " + std::string(buffer.begin(), buffer.end()));
|
||||
Logger::debug("GDB client data received (" + std::to_string(buffer.size()) + " bytes): "
|
||||
+ std::string(buffer.begin(), buffer.end()));
|
||||
|
||||
auto rawPackets = CommandPacketFactory::extractRawPackets(buffer);
|
||||
std::vector<std::unique_ptr<CommandPacket>> output;
|
||||
@@ -82,9 +86,9 @@ std::vector<std::unique_ptr<CommandPacket>> Connection::readPackets() {
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::writePacket(const ResponsePacket& packet) {
|
||||
void Connection::writePacket(const ResponsePacket& packet) {
|
||||
// Write the packet repeatedly until the GDB client acknowledges it.
|
||||
int attempts = 0;
|
||||
auto rawPacket = packet.toRawPacket();
|
||||
@@ -97,11 +101,10 @@ void Connection::writePacket(const ResponsePacket& packet) {
|
||||
|
||||
this->write(rawPacket);
|
||||
attempts++;
|
||||
} while (this->readSingleByte(false).value_or(0) != '+');
|
||||
}
|
||||
|
||||
} while(this->readSingleByte(false).value_or(0) != '+');
|
||||
}
|
||||
|
||||
std::vector<unsigned char> Connection::read(size_t bytes, bool interruptible, std::optional<int> msTimeout) {
|
||||
std::vector<unsigned char> Connection::read(size_t bytes, bool interruptible, std::optional<int> msTimeout) {
|
||||
auto output = std::vector<unsigned char>();
|
||||
constexpr size_t bufferSize = 1024;
|
||||
std::array<unsigned char, bufferSize> buffer = {};
|
||||
@@ -110,6 +113,7 @@ std::vector<unsigned char> Connection::read(size_t bytes, bool interruptible, st
|
||||
if (interruptible) {
|
||||
if (this->readInterruptEnabled != interruptible) {
|
||||
this->enableReadInterrupts();
|
||||
|
||||
} else {
|
||||
// Clear any previous interrupts that are still hanging around
|
||||
this->interruptEventNotifier->clear();
|
||||
@@ -141,7 +145,8 @@ std::vector<unsigned char> Connection::read(size_t bytes, bool interruptible, st
|
||||
}
|
||||
|
||||
size_t bytesToRead = (bytes > bufferSize || bytes == 0) ? bufferSize : bytes;
|
||||
while (bytesToRead > 0 && (bytesRead = ::read(this->socketFileDescriptor, buffer.data(), bytesToRead)) > 0) {
|
||||
while (bytesToRead > 0
|
||||
&& (bytesRead = ::read(this->socketFileDescriptor, buffer.data(), bytesToRead)) > 0) {
|
||||
output.insert(output.end(), buffer.begin(), buffer.begin() + bytesRead);
|
||||
|
||||
if (bytesRead < bytesToRead) {
|
||||
@@ -149,7 +154,8 @@ std::vector<unsigned char> Connection::read(size_t bytes, bool interruptible, st
|
||||
break;
|
||||
}
|
||||
|
||||
bytesToRead = ((bytes - output.size()) > bufferSize || bytes == 0) ? bufferSize : (bytes - output.size());
|
||||
bytesToRead =
|
||||
((bytes - output.size()) > bufferSize || bytes == 0) ? bufferSize : (bytes - output.size());
|
||||
}
|
||||
|
||||
if (output.empty()) {
|
||||
@@ -159,9 +165,9 @@ std::vector<unsigned char> Connection::read(size_t bytes, bool interruptible, st
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<unsigned char> Connection::readSingleByte(bool interruptible) {
|
||||
std::optional<unsigned char> Connection::readSingleByte(bool interruptible) {
|
||||
auto bytes = this->read(1, interruptible, 300);
|
||||
|
||||
if (!bytes.empty()) {
|
||||
@@ -169,23 +175,23 @@ std::optional<unsigned char> Connection::readSingleByte(bool interruptible) {
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::write(const std::vector<unsigned char>& buffer) {
|
||||
void Connection::write(const std::vector<unsigned char>& buffer) {
|
||||
Logger::debug("Writing packet: " + std::string(buffer.begin(), buffer.end()));
|
||||
if (::write(this->socketFileDescriptor, buffer.data(), buffer.size()) == -1) {
|
||||
if (errno == EPIPE || errno == ECONNRESET) {
|
||||
// Connection was closed
|
||||
throw ClientDisconnected();
|
||||
}
|
||||
|
||||
} else {
|
||||
throw ClientCommunicationError("Failed to write " + std::to_string(buffer.size())
|
||||
+ " bytes to GDP client socket - error no: " + std::to_string(errno));
|
||||
+ " bytes to GDP client socket - error no: "
|
||||
+ std::to_string(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::disableReadInterrupts() {
|
||||
void Connection::disableReadInterrupts() {
|
||||
if (::epoll_ctl(
|
||||
this->eventFileDescriptor,
|
||||
EPOLL_CTL_DEL,
|
||||
@@ -196,9 +202,9 @@ void Connection::disableReadInterrupts() {
|
||||
}
|
||||
|
||||
this->readInterruptEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::enableReadInterrupts() {
|
||||
void Connection::enableReadInterrupts() {
|
||||
auto interruptFileDescriptor = this->interruptEventNotifier->getFileDescriptor();
|
||||
struct epoll_event event = {};
|
||||
event.events = EPOLLIN;
|
||||
@@ -209,4 +215,5 @@ void Connection::enableReadInterrupts() {
|
||||
}
|
||||
|
||||
this->readInterruptEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,20 +12,21 @@
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
#include "src/Exceptions/InvalidConfig.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb;
|
||||
using namespace Bloom::DebugServers::Gdb::CommandPackets;
|
||||
using namespace Bloom::DebugServers::Gdb::ResponsePackets;
|
||||
using namespace Bloom::DebugServers::Gdb::Exceptions;
|
||||
using namespace Bloom::Events;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugServers::Gdb
|
||||
{
|
||||
using namespace CommandPackets;
|
||||
using namespace ResponsePackets;
|
||||
using namespace Exceptions;
|
||||
using namespace Bloom::Events;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
using Bloom::Targets::TargetRegister;
|
||||
using Bloom::Targets::TargetRegisterType;
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptors;
|
||||
using Bloom::Targets::TargetBreakpoint;
|
||||
using Bloom::Targets::TargetRegister;
|
||||
using Bloom::Targets::TargetRegisterType;
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptors;
|
||||
using Bloom::Targets::TargetBreakpoint;
|
||||
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPacket& packet) {
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPacket& packet) {
|
||||
auto packetData = packet.getData();
|
||||
auto packetString = std::string(packetData.begin(), packetData.end());
|
||||
|
||||
@@ -47,9 +48,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPacket& packet) {
|
||||
// Respond with an empty packet
|
||||
this->clientConnection->writePacket(ResponsePacket({0}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::SupportedFeaturesQuery& packet) {
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::SupportedFeaturesQuery& packet) {
|
||||
Logger::debug("Handling QuerySupport packet");
|
||||
|
||||
if (!packet.isFeatureSupported(Feature::HARDWARE_BREAKPOINTS)
|
||||
@@ -66,9 +67,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::SupportedFeaturesQuery&
|
||||
});
|
||||
|
||||
this->clientConnection->writePacket(response);
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::ReadRegisters& packet) {
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::ReadRegisters& packet) {
|
||||
Logger::debug("Handling ReadRegisters packet");
|
||||
|
||||
try {
|
||||
@@ -94,7 +95,7 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::ReadRegisters& packet) {
|
||||
std::sort(
|
||||
registerSet.begin(),
|
||||
registerSet.end(),
|
||||
[this] (const TargetRegister& registerA, const TargetRegister& registerB) {
|
||||
[this](const TargetRegister& registerA, const TargetRegister& registerB) {
|
||||
return this->getRegisterNumberFromTargetRegisterDescriptor(registerA.descriptor) <
|
||||
this->getRegisterNumberFromTargetRegisterDescriptor(registerB.descriptor);
|
||||
}
|
||||
@@ -109,7 +110,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::ReadRegisters& packet) {
|
||||
for (auto& reg : registerSet) {
|
||||
std::reverse(reg.value.begin(), reg.value.end());
|
||||
|
||||
const auto gdbRegisterNumber = this->getRegisterNumberFromTargetRegisterDescriptor(reg.descriptor).value();
|
||||
const auto gdbRegisterNumber = this->getRegisterNumberFromTargetRegisterDescriptor(
|
||||
reg.descriptor
|
||||
).value();
|
||||
const auto& gdbRegisterDescriptor = this->getRegisterDescriptorFromNumber(gdbRegisterNumber);
|
||||
|
||||
if (reg.value.size() < gdbRegisterDescriptor.size) {
|
||||
@@ -128,9 +131,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::ReadRegisters& packet) {
|
||||
Logger::error("Failed to read general registers - " + exception.getMessage());
|
||||
this->clientConnection->writePacket(ResponsePacket({'E', '0', '1'}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::WriteRegister& packet) {
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::WriteRegister& packet) {
|
||||
Logger::debug("Handling WriteRegister packet");
|
||||
|
||||
try {
|
||||
@@ -165,9 +168,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::WriteRegister& packet) {
|
||||
Logger::error("Failed to write registers - " + exception.getMessage());
|
||||
this->clientConnection->writePacket(ResponsePacket({'E', '0', '1'}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::ContinueExecution& packet) {
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::ContinueExecution& packet) {
|
||||
Logger::debug("Handling ContinueExecution packet");
|
||||
|
||||
try {
|
||||
@@ -178,9 +181,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::ContinueExecution& packe
|
||||
Logger::error("Failed to continue execution on target - " + exception.getMessage());
|
||||
this->clientConnection->writePacket(ResponsePacket({'E', '0', '1'}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::StepExecution& packet) {
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::StepExecution& packet) {
|
||||
Logger::debug("Handling StepExecution packet");
|
||||
|
||||
try {
|
||||
@@ -191,9 +194,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::StepExecution& packet) {
|
||||
Logger::error("Failed to step execution on target - " + exception.getMessage());
|
||||
this->clientConnection->writePacket(ResponsePacket({'E', '0', '1'}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::ReadMemory& packet) {
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::ReadMemory& packet) {
|
||||
Logger::debug("Handling ReadMemory packet");
|
||||
|
||||
try {
|
||||
@@ -210,9 +213,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::ReadMemory& packet) {
|
||||
Logger::error("Failed to read memory from target - " + exception.getMessage());
|
||||
this->clientConnection->writePacket(ResponsePacket({'E', '0', '1'}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::WriteMemory& packet) {
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::WriteMemory& packet) {
|
||||
Logger::debug("Handling WriteMemory packet");
|
||||
|
||||
try {
|
||||
@@ -226,9 +229,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::WriteMemory& packet) {
|
||||
Logger::error("Failed to write memory two target - " + exception.getMessage());
|
||||
this->clientConnection->writePacket(ResponsePacket({'E', '0', '1'}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::SetBreakpoint& packet) {
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::SetBreakpoint& packet) {
|
||||
Logger::debug("Handling SetBreakpoint packet");
|
||||
|
||||
try {
|
||||
@@ -242,9 +245,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::SetBreakpoint& packet) {
|
||||
Logger::error("Failed to set breakpoint on target - " + exception.getMessage());
|
||||
this->clientConnection->writePacket(ResponsePacket({'E', '0', '1'}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::RemoveBreakpoint& packet) {
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::RemoveBreakpoint& packet) {
|
||||
Logger::debug("Removing breakpoint at address " + std::to_string(packet.address));
|
||||
|
||||
try {
|
||||
@@ -258,9 +261,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::RemoveBreakpoint& packet
|
||||
Logger::error("Failed to remove breakpoint on target - " + exception.getMessage());
|
||||
this->clientConnection->writePacket(ResponsePacket({'E', '0', '1'}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::InterruptExecution& packet) {
|
||||
void GdbRspDebugServer::handleGdbPacket(CommandPackets::InterruptExecution& packet) {
|
||||
Logger::debug("Handling InterruptExecution packet");
|
||||
|
||||
try {
|
||||
@@ -272,9 +275,9 @@ void GdbRspDebugServer::handleGdbPacket(CommandPackets::InterruptExecution& pack
|
||||
Logger::error("Failed to interrupt execution - " + exception.getMessage());
|
||||
this->clientConnection->writePacket(ResponsePacket({'E', '0', '1'}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::init() {
|
||||
void GdbRspDebugServer::init() {
|
||||
auto ipAddress = this->debugServerConfig.jsonObject.find("ipAddress")->toString().toStdString();
|
||||
auto configPortJsonValue = this->debugServerConfig.jsonObject.find("port");
|
||||
auto configPortValue = configPortJsonValue->isString()
|
||||
@@ -294,7 +297,9 @@ void GdbRspDebugServer::init() {
|
||||
|
||||
if (::inet_pton(AF_INET, this->listeningAddress.c_str(), &(this->socketAddress.sin_addr)) == 0) {
|
||||
// Invalid IP address
|
||||
throw InvalidConfig("Invalid IP address provided in config file: (\"" + this->listeningAddress + "\")");
|
||||
throw InvalidConfig(
|
||||
"Invalid IP address provided in config file: (\"" + this->listeningAddress + "\")"
|
||||
);
|
||||
}
|
||||
|
||||
int socketFileDescriptor;
|
||||
@@ -355,17 +360,17 @@ void GdbRspDebugServer::init() {
|
||||
this->eventListener->registerCallbackForEventType<Events::TargetExecutionStopped>(
|
||||
std::bind(&GdbRspDebugServer::onTargetExecutionStopped, this, std::placeholders::_1)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::close() {
|
||||
void GdbRspDebugServer::close() {
|
||||
this->closeClientConnection();
|
||||
|
||||
if (this->serverSocketFileDescriptor > 0) {
|
||||
::close(this->serverSocketFileDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::serve() {
|
||||
void GdbRspDebugServer::serve() {
|
||||
try {
|
||||
if (!this->clientConnection.has_value()) {
|
||||
Logger::info("Waiting for GDB RSP connection");
|
||||
@@ -403,7 +408,9 @@ void GdbRspDebugServer::serve() {
|
||||
return;
|
||||
|
||||
} catch (const ClientCommunicationError& exception) {
|
||||
Logger::error("GDB RSP client communication error - " + exception.getMessage() + " - closing connection");
|
||||
Logger::error(
|
||||
"GDB RSP client communication error - " + exception.getMessage() + " - closing connection"
|
||||
);
|
||||
this->closeClientConnection();
|
||||
return;
|
||||
|
||||
@@ -422,9 +429,9 @@ void GdbRspDebugServer::serve() {
|
||||
Logger::debug("GDB RSP interrupted");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::waitForConnection() {
|
||||
void GdbRspDebugServer::waitForConnection() {
|
||||
if (::listen(this->serverSocketFileDescriptor, 3) != 0) {
|
||||
throw Exception("Failed to listen on server socket");
|
||||
}
|
||||
@@ -451,18 +458,19 @@ void GdbRspDebugServer::waitForConnection() {
|
||||
|
||||
this->clientConnection = Connection(this->interruptEventNotifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::onTargetControllerStateReported(const Events::TargetControllerStateReported& event) {
|
||||
void GdbRspDebugServer::onTargetControllerStateReported(const Events::TargetControllerStateReported& event) {
|
||||
if (event.state == TargetControllerState::SUSPENDED && this->clientConnection.has_value()) {
|
||||
Logger::warning("Terminating debug session - TargetController suspended unexpectedly");
|
||||
this->closeClientConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbRspDebugServer::onTargetExecutionStopped(const Events::TargetExecutionStopped&) {
|
||||
void GdbRspDebugServer::onTargetExecutionStopped(const Events::TargetExecutionStopped&) {
|
||||
if (this->clientConnection.has_value() && this->clientConnection->waitingForBreak) {
|
||||
this->clientConnection->writePacket(TargetStopped(Signal::TRAP));
|
||||
this->clientConnection->waitingForBreak = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "SupportedFeaturesResponse.hpp"
|
||||
|
||||
using namespace Bloom::DebugServers::Gdb::ResponsePackets;
|
||||
|
||||
std::vector<unsigned char> SupportedFeaturesResponse::getData() const {
|
||||
namespace Bloom::DebugServers::Gdb::ResponsePackets
|
||||
{
|
||||
std::vector<unsigned char> SupportedFeaturesResponse::getData() const {
|
||||
std::string output = "qSupported:";
|
||||
auto gdbFeatureMapping = getGdbFeatureToNameMapping();
|
||||
|
||||
@@ -12,6 +12,7 @@ std::vector<unsigned char> SupportedFeaturesResponse::getData() const {
|
||||
if (featureString.has_value()) {
|
||||
if (supportedFeature.second.has_value()) {
|
||||
output.append(featureString.value() + "=" + supportedFeature.second.value() + ";");
|
||||
|
||||
} else {
|
||||
output.append(featureString.value() + "+;");
|
||||
}
|
||||
@@ -20,4 +21,5 @@ std::vector<unsigned char> SupportedFeaturesResponse::getData() const {
|
||||
}
|
||||
|
||||
return std::vector<unsigned char>(output.begin(), output.end());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
#include "src/TargetController/Exceptions/DeviceFailure.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers;
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers
|
||||
{
|
||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void AtmelIce::init() {
|
||||
void AtmelIce::init() {
|
||||
UsbDevice::init();
|
||||
|
||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||
@@ -39,23 +40,25 @@ void AtmelIce::init() {
|
||||
|
||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
||||
this->setInitialised(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AtmelIce::close() {
|
||||
void AtmelIce::close() {
|
||||
if (this->sessionStarted) {
|
||||
this->endSession();
|
||||
}
|
||||
|
||||
this->getEdbgInterface().getUsbHidInterface().close();
|
||||
UsbDevice::close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string AtmelIce::getSerialNumber() {
|
||||
using namespace CommandFrames::Discovery;
|
||||
|
||||
std::string AtmelIce::getSerialNumber() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
|
||||
Query(QueryContext::SERIAL_NUMBER)
|
||||
);
|
||||
|
||||
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
|
||||
if (response.getResponseId() != ResponseId::OK) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
|
||||
);
|
||||
@@ -63,30 +66,35 @@ std::string AtmelIce::getSerialNumber() {
|
||||
|
||||
auto data = response.getPayloadData();
|
||||
return std::string(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
|
||||
void AtmelIce::startSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void AtmelIce::startSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::StartSession()
|
||||
StartSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceInitializationFailure("Failed to start session with Atmel-ICE!");
|
||||
}
|
||||
|
||||
this->sessionStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void AtmelIce::endSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void AtmelIce::endSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::EndSession()
|
||||
EndSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceFailure("Failed to end session with Atmel-ICE!");
|
||||
}
|
||||
|
||||
this->sessionStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
#include "src/TargetController/Exceptions/DeviceFailure.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers;
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers
|
||||
{
|
||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void CuriosityNano::init() {
|
||||
void CuriosityNano::init() {
|
||||
UsbDevice::init();
|
||||
|
||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||
@@ -31,23 +32,25 @@ void CuriosityNano::init() {
|
||||
|
||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
||||
this->setInitialised(true);
|
||||
}
|
||||
}
|
||||
|
||||
void CuriosityNano::close() {
|
||||
void CuriosityNano::close() {
|
||||
if (this->sessionStarted) {
|
||||
this->endSession();
|
||||
}
|
||||
|
||||
this->getEdbgInterface().getUsbHidInterface().close();
|
||||
UsbDevice::close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string CuriosityNano::getSerialNumber() {
|
||||
using namespace CommandFrames::Discovery;
|
||||
|
||||
std::string CuriosityNano::getSerialNumber() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
|
||||
Query(QueryContext::SERIAL_NUMBER)
|
||||
);
|
||||
|
||||
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
|
||||
if (response.getResponseId() != ResponseId::OK) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
|
||||
);
|
||||
@@ -55,30 +58,35 @@ std::string CuriosityNano::getSerialNumber() {
|
||||
|
||||
auto data = response.getPayloadData();
|
||||
return std::string(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
|
||||
void CuriosityNano::startSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void CuriosityNano::startSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::StartSession()
|
||||
StartSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceInitializationFailure("Failed to start session with Curiosity Nano!");
|
||||
}
|
||||
|
||||
this->sessionStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CuriosityNano::endSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void CuriosityNano::endSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::EndSession()
|
||||
EndSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceFailure("Failed to end session with Curiosity Nano!");
|
||||
}
|
||||
|
||||
this->sessionStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
#include "src/TargetController/Exceptions/DeviceFailure.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers;
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers
|
||||
{
|
||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void MplabPickit4::init() {
|
||||
void MplabPickit4::init() {
|
||||
UsbDevice::init();
|
||||
|
||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||
@@ -32,23 +33,25 @@ void MplabPickit4::init() {
|
||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
||||
|
||||
this->setInitialised(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MplabPickit4::close() {
|
||||
void MplabPickit4::close() {
|
||||
if (this->sessionStarted) {
|
||||
this->endSession();
|
||||
}
|
||||
|
||||
this->getEdbgInterface().getUsbHidInterface().close();
|
||||
UsbDevice::close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string MplabPickit4::getSerialNumber() {
|
||||
using namespace CommandFrames::Discovery;
|
||||
|
||||
std::string MplabPickit4::getSerialNumber() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
|
||||
Query(QueryContext::SERIAL_NUMBER)
|
||||
);
|
||||
|
||||
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
|
||||
if (response.getResponseId() != ResponseId::OK) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
|
||||
);
|
||||
@@ -56,30 +59,35 @@ std::string MplabPickit4::getSerialNumber() {
|
||||
|
||||
auto data = response.getPayloadData();
|
||||
return std::string(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
|
||||
void MplabPickit4::startSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void MplabPickit4::startSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::StartSession()
|
||||
StartSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceInitializationFailure("Failed to start session with MPLAB PICkit 4!");
|
||||
}
|
||||
|
||||
this->sessionStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MplabPickit4::endSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void MplabPickit4::endSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::EndSession()
|
||||
EndSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceFailure("Failed to end session with MPLAB PICkit 4!");
|
||||
}
|
||||
|
||||
this->sessionStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
#include "src/TargetController/Exceptions/DeviceFailure.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers;
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers
|
||||
{
|
||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void MplabSnap::init() {
|
||||
void MplabSnap::init() {
|
||||
UsbDevice::init();
|
||||
|
||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||
@@ -31,23 +32,25 @@ void MplabSnap::init() {
|
||||
|
||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
||||
this->setInitialised(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MplabSnap::close() {
|
||||
void MplabSnap::close() {
|
||||
if (this->sessionStarted) {
|
||||
this->endSession();
|
||||
}
|
||||
|
||||
this->getEdbgInterface().getUsbHidInterface().close();
|
||||
UsbDevice::close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string MplabSnap::getSerialNumber() {
|
||||
using namespace CommandFrames::Discovery;
|
||||
|
||||
std::string MplabSnap::getSerialNumber() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
|
||||
Query(QueryContext::SERIAL_NUMBER)
|
||||
);
|
||||
|
||||
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
|
||||
if (response.getResponseId() != ResponseId::OK) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
|
||||
);
|
||||
@@ -55,30 +58,35 @@ std::string MplabSnap::getSerialNumber() {
|
||||
|
||||
auto data = response.getPayloadData();
|
||||
return std::string(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
|
||||
void MplabSnap::startSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void MplabSnap::startSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::StartSession()
|
||||
StartSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceInitializationFailure("Failed to start session with MPLAB Snap!");
|
||||
}
|
||||
|
||||
this->sessionStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MplabSnap::endSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void MplabSnap::endSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::EndSession()
|
||||
EndSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceFailure("Failed to end session with MPLAB Snap!");
|
||||
}
|
||||
|
||||
this->sessionStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
#include "src/TargetController/Exceptions/DeviceFailure.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers;
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers
|
||||
{
|
||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
using Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface;
|
||||
|
||||
void PowerDebugger::init() {
|
||||
void PowerDebugger::init() {
|
||||
UsbDevice::init();
|
||||
|
||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||
@@ -39,23 +38,25 @@ void PowerDebugger::init() {
|
||||
|
||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
||||
this->setInitialised(true);
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDebugger::close() {
|
||||
void PowerDebugger::close() {
|
||||
if (this->sessionStarted) {
|
||||
this->endSession();
|
||||
}
|
||||
|
||||
this->getEdbgInterface().getUsbHidInterface().close();
|
||||
UsbDevice::close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string PowerDebugger::getSerialNumber() {
|
||||
using namespace CommandFrames::Discovery;
|
||||
|
||||
std::string PowerDebugger::getSerialNumber() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
|
||||
Query(QueryContext::SERIAL_NUMBER)
|
||||
);
|
||||
|
||||
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
|
||||
if (response.getResponseId() != ResponseId::OK) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
|
||||
);
|
||||
@@ -63,14 +64,16 @@ std::string PowerDebugger::getSerialNumber() {
|
||||
|
||||
auto data = response.getPayloadData();
|
||||
return std::string(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDebugger::startSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void PowerDebugger::startSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::StartSession()
|
||||
StartSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to start session with the Power Debugger - device returned failed response ID"
|
||||
@@ -78,17 +81,22 @@ void PowerDebugger::startSession() {
|
||||
}
|
||||
|
||||
this->sessionStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PowerDebugger::endSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void PowerDebugger::endSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::EndSession()
|
||||
EndSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceFailure("Failed to end session with the Power Debugger - device returned failed response ID");
|
||||
throw DeviceFailure(
|
||||
"Failed to end session with the Power Debugger - device returned failed response ID"
|
||||
);
|
||||
}
|
||||
|
||||
this->sessionStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
#include "src/TargetController/Exceptions/DeviceFailure.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers;
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers
|
||||
{
|
||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void XplainedMini::init() {
|
||||
void XplainedMini::init() {
|
||||
UsbDevice::init();
|
||||
|
||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||
@@ -31,23 +32,25 @@ void XplainedMini::init() {
|
||||
|
||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
||||
this->setInitialised(true);
|
||||
}
|
||||
}
|
||||
|
||||
void XplainedMini::close() {
|
||||
void XplainedMini::close() {
|
||||
if (this->sessionStarted) {
|
||||
this->endSession();
|
||||
}
|
||||
|
||||
this->getEdbgInterface().getUsbHidInterface().close();
|
||||
UsbDevice::close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string XplainedMini::getSerialNumber() {
|
||||
using namespace CommandFrames::Discovery;
|
||||
|
||||
std::string XplainedMini::getSerialNumber() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
|
||||
Query(QueryContext::SERIAL_NUMBER)
|
||||
);
|
||||
|
||||
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
|
||||
if (response.getResponseId() != ResponseId::OK) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
|
||||
);
|
||||
@@ -55,30 +58,35 @@ std::string XplainedMini::getSerialNumber() {
|
||||
|
||||
auto data = response.getPayloadData();
|
||||
return std::string(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
|
||||
void XplainedMini::startSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void XplainedMini::startSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::StartSession()
|
||||
StartSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceInitializationFailure("Failed to start session with Xplained Mini!");
|
||||
}
|
||||
|
||||
this->sessionStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void XplainedMini::endSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void XplainedMini::endSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::EndSession()
|
||||
EndSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceFailure("Failed to end session with Xplained Mini!");
|
||||
}
|
||||
|
||||
this->sessionStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
#include "src/TargetController/Exceptions/DeviceFailure.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers;
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers
|
||||
{
|
||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void XplainedNano::init() {
|
||||
void XplainedNano::init() {
|
||||
UsbDevice::init();
|
||||
|
||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||
@@ -31,23 +32,25 @@ void XplainedNano::init() {
|
||||
|
||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
||||
this->setInitialised(true);
|
||||
}
|
||||
}
|
||||
|
||||
void XplainedNano::close() {
|
||||
void XplainedNano::close() {
|
||||
if (this->sessionStarted) {
|
||||
this->endSession();
|
||||
}
|
||||
|
||||
this->getEdbgInterface().getUsbHidInterface().close();
|
||||
UsbDevice::close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string XplainedNano::getSerialNumber() {
|
||||
using namespace CommandFrames::Discovery;
|
||||
|
||||
std::string XplainedNano::getSerialNumber() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
|
||||
Query(QueryContext::SERIAL_NUMBER)
|
||||
);
|
||||
|
||||
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
|
||||
if (response.getResponseId() != ResponseId::OK) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
|
||||
);
|
||||
@@ -55,30 +58,35 @@ std::string XplainedNano::getSerialNumber() {
|
||||
|
||||
auto data = response.getPayloadData();
|
||||
return std::string(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
|
||||
void XplainedNano::startSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void XplainedNano::startSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::StartSession()
|
||||
StartSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceInitializationFailure("Failed to start session with Xplained Nano!");
|
||||
}
|
||||
|
||||
this->sessionStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void XplainedNano::endSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void XplainedNano::endSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::EndSession()
|
||||
EndSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceFailure("Failed to end session with Xplained Nano!");
|
||||
}
|
||||
|
||||
this->sessionStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
#include "src/TargetController/Exceptions/DeviceFailure.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers;
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers
|
||||
{
|
||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void XplainedPro::init() {
|
||||
void XplainedPro::init() {
|
||||
UsbDevice::init();
|
||||
|
||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||
@@ -40,23 +41,25 @@ void XplainedPro::init() {
|
||||
*/
|
||||
this->edbgAvr8Interface->setMaximumMemoryAccessSizePerRequest(256);
|
||||
this->setInitialised(true);
|
||||
}
|
||||
}
|
||||
|
||||
void XplainedPro::close() {
|
||||
void XplainedPro::close() {
|
||||
if (this->sessionStarted) {
|
||||
this->endSession();
|
||||
}
|
||||
|
||||
this->getEdbgInterface().getUsbHidInterface().close();
|
||||
UsbDevice::close();
|
||||
}
|
||||
}
|
||||
|
||||
std::string XplainedPro::getSerialNumber() {
|
||||
using namespace CommandFrames::Discovery;
|
||||
|
||||
std::string XplainedPro::getSerialNumber() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
|
||||
Query(QueryContext::SERIAL_NUMBER)
|
||||
);
|
||||
|
||||
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
|
||||
if (response.getResponseId() != ResponseId::OK) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
|
||||
);
|
||||
@@ -64,30 +67,35 @@ std::string XplainedPro::getSerialNumber() {
|
||||
|
||||
auto data = response.getPayloadData();
|
||||
return std::string(data.begin(), data.end());
|
||||
}
|
||||
}
|
||||
|
||||
void XplainedPro::startSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void XplainedPro::startSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::StartSession()
|
||||
StartSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceInitializationFailure("Failed to start session with Xplained Pro!");
|
||||
}
|
||||
|
||||
this->sessionStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
void XplainedPro::endSession() {
|
||||
using namespace CommandFrames::HouseKeeping;
|
||||
|
||||
void XplainedPro::endSession() {
|
||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
||||
CommandFrames::HouseKeeping::EndSession()
|
||||
EndSession()
|
||||
);
|
||||
|
||||
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
|
||||
if (response.getResponseId() == ResponseId::FAILED) {
|
||||
// Failed response returned!
|
||||
throw DeviceFailure("Failed to end session with Xplained Pro!");
|
||||
}
|
||||
|
||||
this->sessionStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/Response.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceCommunicationFailure.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void CmsisDapInterface::sendCommand(const Command& cmsisDapCommand) {
|
||||
void CmsisDapInterface::sendCommand(const Command& cmsisDapCommand) {
|
||||
if (this->msSendCommandDelay.count() > 0) {
|
||||
using namespace std::chrono;
|
||||
std::int64_t now = duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();
|
||||
@@ -23,9 +24,9 @@ void CmsisDapInterface::sendCommand(const Command& cmsisDapCommand) {
|
||||
}
|
||||
|
||||
this->getUsbHidInterface().write(static_cast<std::vector<unsigned char>>(cmsisDapCommand));
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Response> CmsisDapInterface::getResponse() {
|
||||
std::unique_ptr<Response> CmsisDapInterface::getResponse() {
|
||||
auto rawResponse = this->getUsbHidInterface().read(10000);
|
||||
|
||||
if (rawResponse.empty()) {
|
||||
@@ -35,9 +36,9 @@ std::unique_ptr<Response> CmsisDapInterface::getResponse() {
|
||||
auto response = std::make_unique<Response>(Response());
|
||||
response->init(rawResponse);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Response> CmsisDapInterface::sendCommandAndWaitForResponse(const Command& cmsisDapCommand) {
|
||||
std::unique_ptr<Response> CmsisDapInterface::sendCommandAndWaitForResponse(const Command& cmsisDapCommand) {
|
||||
this->sendCommand(cmsisDapCommand);
|
||||
auto response = this->getResponse();
|
||||
|
||||
@@ -47,4 +48,5 @@ std::unique_ptr<Response> CmsisDapInterface::sendCommandAndWaitForResponse(const
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#include "Command.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap;
|
||||
|
||||
Command::operator std::vector<unsigned char> () const {
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
||||
{
|
||||
Command::operator std::vector<unsigned char>() const {
|
||||
auto rawCommand = std::vector<unsigned char>(1, this->getCommandId());
|
||||
auto commandData = this->getData();
|
||||
rawCommand.insert(rawCommand.end(), commandData.begin(), commandData.end());
|
||||
|
||||
return rawCommand;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap;
|
||||
|
||||
void Response::init(const std::vector<unsigned char>& rawResponse) {
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
||||
{
|
||||
void Response::init(const std::vector<unsigned char>& rawResponse) {
|
||||
if (rawResponse.empty()) {
|
||||
throw Exceptions::Exception("Failed to process CMSIS-DAP response - invalid response");
|
||||
}
|
||||
|
||||
this->setResponseId(rawResponse[0]);
|
||||
this->setData(std::vector<unsigned char>(rawResponse.begin() + 1, rawResponse.end()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "AvrCommand.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
|
||||
std::vector<unsigned char> AvrCommand::getData() const {
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
{
|
||||
std::vector<unsigned char> AvrCommand::getData() const {
|
||||
std::vector<unsigned char> data;
|
||||
auto commandPacket = this->getCommandPacket();
|
||||
std::size_t commandPacketSize = commandPacket.size();
|
||||
@@ -11,12 +11,13 @@ std::vector<unsigned char> AvrCommand::getData() const {
|
||||
data[0] = static_cast<unsigned char>((this->getFragmentNumber() << 4) | this->getFragmentCount());
|
||||
|
||||
// Size byte
|
||||
data[1] = (unsigned char) (commandPacketSize >> 8);
|
||||
data[2] = (unsigned char) (commandPacketSize & 0xFF);
|
||||
data[1] = static_cast<unsigned char>(commandPacketSize >> 8);
|
||||
data[2] = static_cast<unsigned char>(commandPacketSize & 0xFF);
|
||||
|
||||
if (commandPacketSize > 0) {
|
||||
data.insert(data.begin() + 3, commandPacket.begin(), commandPacket.end());
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void AvrEvent::init(const std::vector<unsigned char>& rawResponse) {
|
||||
void AvrEvent::init(const std::vector<unsigned char>& rawResponse) {
|
||||
Response::init(rawResponse);
|
||||
|
||||
if (this->getResponseId() != 0x82) {
|
||||
throw Exception("Failed to construct AvrEvent object - invalid response ID.");
|
||||
}
|
||||
|
||||
auto& responseData = this->getData();
|
||||
const auto& responseData = this->getData();
|
||||
|
||||
if (responseData.size() < 2) {
|
||||
// All AVR_EVT responses should consist of at least two bytes (excluding the AVR_EVT ID)
|
||||
@@ -46,4 +47,5 @@ void AvrEvent::init(const std::vector<unsigned char>& rawResponse) {
|
||||
if (!eventData.empty()) {
|
||||
this->eventId = eventData[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void AvrResponse::init(const std::vector<unsigned char>& rawResponse) {
|
||||
void AvrResponse::init(const std::vector<unsigned char>& rawResponse) {
|
||||
Response::init(rawResponse);
|
||||
|
||||
if (this->getResponseId() != 0x81) {
|
||||
throw Exception("Failed to construct AvrResponse object - invalid response ID.");
|
||||
}
|
||||
|
||||
auto& responseData = this->getData();
|
||||
const auto& responseData = this->getData();
|
||||
|
||||
if (responseData.empty()) {
|
||||
// All AVR responses should contain at least one byte (the fragment info byte)
|
||||
@@ -25,11 +26,11 @@ void AvrResponse::init(const std::vector<unsigned char>& rawResponse) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->setFragmentCount(static_cast<std::uint8_t>(responseData[0] & 0x0Fu));
|
||||
this->setFragmentCount(static_cast<std::uint8_t>(responseData[0] & 0x0FU));
|
||||
this->setFragmentNumber(static_cast<std::uint8_t>(responseData[0] >> 4));
|
||||
|
||||
// Response size is two bytes, MSB
|
||||
std::size_t responsePacketSize = static_cast<std::size_t>((responseData[1] << 8u) + responseData[2]);
|
||||
const auto responsePacketSize = static_cast<std::size_t>((responseData[1] << 8U) + responseData[2]);
|
||||
std::vector<unsigned char> responsePacket;
|
||||
responsePacket.resize(responsePacketSize);
|
||||
|
||||
@@ -38,4 +39,5 @@ void AvrResponse::init(const std::vector<unsigned char>& rawResponse) {
|
||||
}
|
||||
|
||||
this->setResponsePacket(responsePacket);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
#include <bitset>
|
||||
#include <cmath>
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic;
|
||||
|
||||
std::vector<unsigned char> ReadMemory::getPayload() const {
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic
|
||||
{
|
||||
std::vector<unsigned char> ReadMemory::getPayload() const {
|
||||
/*
|
||||
* The read memory command consists of 11/11 + (this->bytes / 8) bytes:
|
||||
* 1. Command ID (0x21 for the general read memory command, 0x22 for reading with a mask)
|
||||
@@ -53,4 +53,5 @@ std::vector<unsigned char> ReadMemory::getPayload() const {
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
|
||||
std::vector<AvrCommand> AvrCommandFrame::generateAvrCommands(std::size_t maximumCommandPacketSize) const {
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
{
|
||||
std::vector<AvrCommand> AvrCommandFrame::generateAvrCommands(std::size_t maximumCommandPacketSize) const {
|
||||
auto rawCommandFrame = static_cast<std::vector<unsigned char>>(*this);
|
||||
std::size_t commandFrameSize = rawCommandFrame.size();
|
||||
auto commandsRequired = static_cast<std::size_t>(
|
||||
@@ -35,9 +35,9 @@ std::vector<AvrCommand> AvrCommandFrame::generateAvrCommands(std::size_t maximum
|
||||
}
|
||||
|
||||
return avrCommands;
|
||||
}
|
||||
}
|
||||
|
||||
AvrCommandFrame::operator std::vector<unsigned char> () const {
|
||||
AvrCommandFrame::operator std::vector<unsigned char>() const {
|
||||
auto data = this->getPayload();
|
||||
auto dataSize = data.size();
|
||||
|
||||
@@ -60,4 +60,5 @@ AvrCommandFrame::operator std::vector<unsigned char> () const {
|
||||
}
|
||||
|
||||
return rawCommand;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,21 +36,22 @@
|
||||
// AVR events
|
||||
#include "src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/Events/AVR8Generic/BreakEvent.hpp"
|
||||
|
||||
using namespace Bloom::Targets::Microchip::Avr;
|
||||
using namespace Bloom::Targets::Microchip::Avr::Avr8Bit;
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
{
|
||||
using namespace Bloom::Targets::Microchip::Avr;
|
||||
using namespace Avr8Bit;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
using Bloom::Targets::TargetState;
|
||||
using Bloom::Targets::TargetMemoryType;
|
||||
using Bloom::Targets::TargetMemoryBuffer;
|
||||
using Bloom::Targets::TargetRegister;
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptors;
|
||||
using Bloom::Targets::TargetRegisterType;
|
||||
using Bloom::Targets::TargetRegisters;
|
||||
using Bloom::Targets::TargetState;
|
||||
using Bloom::Targets::TargetMemoryType;
|
||||
using Bloom::Targets::TargetMemoryBuffer;
|
||||
using Bloom::Targets::TargetRegister;
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptors;
|
||||
using Bloom::Targets::TargetRegisterType;
|
||||
using Bloom::Targets::TargetRegisters;
|
||||
|
||||
void EdbgAvr8Interface::configure(const TargetConfig& targetConfig) {
|
||||
void EdbgAvr8Interface::configure(const TargetConfig& targetConfig) {
|
||||
auto physicalInterface = targetConfig.jsonObject.find("physicalInterface")->toString().toLower().toStdString();
|
||||
|
||||
auto availablePhysicalInterfaces = this->getPhysicalInterfacesByName();
|
||||
@@ -91,9 +92,9 @@ void EdbgAvr8Interface::configure(const TargetConfig& targetConfig) {
|
||||
"disableDebugWirePreDisconnect"
|
||||
)->toBool();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::setTargetParameters(const Avr8Bit::TargetParameters& config) {
|
||||
void EdbgAvr8Interface::setTargetParameters(const Avr8Bit::TargetParameters& config) {
|
||||
this->targetParameters = config;
|
||||
|
||||
if (!config.stackPointerRegisterLowAddress.has_value()) {
|
||||
@@ -118,7 +119,8 @@ void EdbgAvr8Interface::setTargetParameters(const Avr8Bit::TargetParameters& con
|
||||
throw DeviceInitializationFailure("Flash page size for target ("
|
||||
+ std::to_string(config.flashPageSize.value())
|
||||
+ " bytes) exceeds maximum memory access size for EdbgAvr8Interface ("
|
||||
+ std::to_string(this->maximumMemoryAccessSizePerRequest.value()) + " bytes)."
|
||||
+ std::to_string(this->maximumMemoryAccessSizePerRequest.value())
|
||||
+ " bytes)."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -153,9 +155,9 @@ void EdbgAvr8Interface::setTargetParameters(const Avr8Bit::TargetParameters& con
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::init() {
|
||||
void EdbgAvr8Interface::init() {
|
||||
if (this->configVariant == Avr8ConfigVariant::XMEGA) {
|
||||
// Default PDI clock to 4MHz
|
||||
// TODO: Make this adjustable via a target config parameter
|
||||
@@ -189,9 +191,9 @@ void EdbgAvr8Interface::init() {
|
||||
Avr8EdbgParameters::PHYSICAL_INTERFACE,
|
||||
getAvr8PhysicalInterfaceToIdMapping().at(this->physicalInterface)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::stop() {
|
||||
void EdbgAvr8Interface::stop() {
|
||||
auto commandFrame = CommandFrames::Avr8Generic::Stop();
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
@@ -202,9 +204,9 @@ void EdbgAvr8Interface::stop() {
|
||||
if (this->getTargetState() == TargetState::RUNNING) {
|
||||
this->waitForStoppedEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::run() {
|
||||
void EdbgAvr8Interface::run() {
|
||||
this->clearEvents();
|
||||
auto commandFrame = CommandFrames::Avr8Generic::Run();
|
||||
|
||||
@@ -214,11 +216,10 @@ void EdbgAvr8Interface::run() {
|
||||
}
|
||||
|
||||
this->targetState = TargetState::RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::runTo(std::uint32_t address) {
|
||||
void EdbgAvr8Interface::runTo(std::uint32_t address) {
|
||||
this->clearEvents();
|
||||
Logger::debug("Running to address: " + std::to_string(address));
|
||||
auto commandFrame = CommandFrames::Avr8Generic::RunTo(address);
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
@@ -227,9 +228,9 @@ void EdbgAvr8Interface::runTo(std::uint32_t address) {
|
||||
}
|
||||
|
||||
this->targetState = TargetState::RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::step() {
|
||||
void EdbgAvr8Interface::step() {
|
||||
auto commandFrame = CommandFrames::Avr8Generic::Step();
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
@@ -238,18 +239,18 @@ void EdbgAvr8Interface::step() {
|
||||
}
|
||||
|
||||
this->targetState = TargetState::RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::reset() {
|
||||
void EdbgAvr8Interface::reset() {
|
||||
auto commandFrame = CommandFrames::Avr8Generic::Reset();
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
||||
throw Avr8CommandFailure("AVR8 Reset target command failed", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::activate() {
|
||||
void EdbgAvr8Interface::activate() {
|
||||
if (!this->physicalInterfaceActivated) {
|
||||
this->activatePhysical();
|
||||
}
|
||||
@@ -257,16 +258,18 @@ void EdbgAvr8Interface::activate() {
|
||||
if (!this->targetAttached) {
|
||||
this->attach();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::deactivate() {
|
||||
void EdbgAvr8Interface::deactivate() {
|
||||
if (this->targetAttached) {
|
||||
if (this->physicalInterface == PhysicalInterface::DEBUG_WIRE && this->disableDebugWireOnDeactivate) {
|
||||
try {
|
||||
this->disableDebugWire();
|
||||
Logger::warning("Successfully disabled debugWire on the AVR8 target - this is only temporary - "
|
||||
"the debugWire module has lost control of the RESET pin. Bloom will no longer be able to interface "
|
||||
"with the target until the next power cycle.");
|
||||
Logger::warning(
|
||||
"Successfully disabled debugWire on the AVR8 target - this is only temporary - "
|
||||
"the debugWire module has lost control of the RESET pin. Bloom will no longer be able to "
|
||||
"interface with the target until the next power cycle."
|
||||
);
|
||||
|
||||
} catch (const Exception& exception) {
|
||||
// Failing to disable debugWire should never prevent us from proceeding with target deactivation.
|
||||
@@ -284,9 +287,9 @@ void EdbgAvr8Interface::deactivate() {
|
||||
if (this->physicalInterfaceActivated) {
|
||||
this->deactivatePhysical();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::uint32_t EdbgAvr8Interface::getProgramCounter() {
|
||||
std::uint32_t EdbgAvr8Interface::getProgramCounter() {
|
||||
if (this->targetState != TargetState::STOPPED) {
|
||||
this->stop();
|
||||
}
|
||||
@@ -298,9 +301,9 @@ std::uint32_t EdbgAvr8Interface::getProgramCounter() {
|
||||
}
|
||||
|
||||
return response.extractProgramCounter();
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::setProgramCounter(std::uint32_t programCounter) {
|
||||
void EdbgAvr8Interface::setProgramCounter(std::uint32_t programCounter) {
|
||||
if (this->targetState != TargetState::STOPPED) {
|
||||
this->stop();
|
||||
}
|
||||
@@ -314,9 +317,9 @@ void EdbgAvr8Interface::setProgramCounter(std::uint32_t programCounter) {
|
||||
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
||||
throw Avr8CommandFailure("AVR8 Set program counter command failed", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TargetSignature EdbgAvr8Interface::getDeviceId() {
|
||||
TargetSignature EdbgAvr8Interface::getDeviceId() {
|
||||
if (this->configVariant == Avr8ConfigVariant::UPDI) {
|
||||
/*
|
||||
* When using the UPDI physical interface, the 'Get device ID' command behaves in an odd manner, where it
|
||||
@@ -350,46 +353,47 @@ TargetSignature EdbgAvr8Interface::getDeviceId() {
|
||||
}
|
||||
|
||||
return response.extractSignature(this->physicalInterface);
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::setBreakpoint(std::uint32_t address) {
|
||||
void EdbgAvr8Interface::setBreakpoint(std::uint32_t address) {
|
||||
auto commandFrame = CommandFrames::Avr8Generic::SetSoftwareBreakpoints({address});
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
||||
throw Avr8CommandFailure("AVR8 Set software breakpoint command failed", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::clearBreakpoint(std::uint32_t address) {
|
||||
void EdbgAvr8Interface::clearBreakpoint(std::uint32_t address) {
|
||||
auto commandFrame = CommandFrames::Avr8Generic::ClearSoftwareBreakpoints({address});
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
||||
throw Avr8CommandFailure("AVR8 Clear software breakpoint command failed", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::clearAllBreakpoints() {
|
||||
void EdbgAvr8Interface::clearAllBreakpoints() {
|
||||
auto commandFrame = CommandFrames::Avr8Generic::ClearAllSoftwareBreakpoints();
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
||||
throw Avr8CommandFailure("AVR8 Clear all software breakpoints command failed", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TargetRegisters EdbgAvr8Interface::readRegisters(const TargetRegisterDescriptors& descriptors) {
|
||||
TargetRegisters EdbgAvr8Interface::readRegisters(const TargetRegisterDescriptors& descriptors) {
|
||||
/*
|
||||
* This function needs to be fast. Insight eagerly requests the values of all known registers that it can present
|
||||
* to the user. It does this on numerous occasions (target stopped, user clicked refresh, etc). This means we will
|
||||
* be frequently loading over 100 register values in a single instance.
|
||||
* This function needs to be fast. Insight eagerly requests the values of all known registers that it can
|
||||
* present to the user. It does this on numerous occasions (target stopped, user clicked refresh, etc). This
|
||||
* means we will be frequently loading over 100 register values in a single instance.
|
||||
*
|
||||
* For the above reason, we do not read each register value individually. That would take far too long if we have
|
||||
* over 100 registers to read. Instead, we group the register descriptors into collections by register type, and
|
||||
* resolve the address range for each collection. We then perform a single read operation for each collection
|
||||
* and hold the memory buffer in a random access container (std::vector). Finally, we extract the data for
|
||||
* each register descriptor, from the memory buffer, and construct the relevant TargetRegister object.
|
||||
* For the above reason, we do not read each register value individually. That would take far too long if we
|
||||
* have over 100 registers to read. Instead, we group the register descriptors into collections by register
|
||||
* type, and resolve the address range for each collection. We then perform a single read operation for
|
||||
* each collection and hold the memory buffer in a random access container (std::vector). Finally, we extract
|
||||
* the data for each register descriptor, from the memory buffer, and construct the relevant TargetRegister
|
||||
* object.
|
||||
*
|
||||
* TODO: We should be grouping the register descriptors by memory type, as opposed to register type. This
|
||||
* isn't much of a problem ATM, as currently, we only work with registers that are stored in the data
|
||||
@@ -445,24 +449,24 @@ TargetRegisters EdbgAvr8Interface::readRegisters(const TargetRegisterDescriptors
|
||||
* Now that we have our address ranges and grouped descriptors, we can perform a single read call for each
|
||||
* register type.
|
||||
*/
|
||||
for (const auto& [registerType, descriptors] : descriptorsByType) {
|
||||
for (const auto&[registerType, descriptors] : descriptorsByType) {
|
||||
const auto& addressRange = addressRangeByType[registerType];
|
||||
const auto startAddress = addressRange.first;
|
||||
const auto endAddress = addressRange.second;
|
||||
const auto bufferSize = (endAddress - startAddress) + 1;
|
||||
|
||||
const auto memoryType = (registerType != TargetRegisterType::GENERAL_PURPOSE_REGISTER) ? Avr8MemoryType::SRAM : (
|
||||
this->configVariant == Avr8ConfigVariant::XMEGA || this->configVariant == Avr8ConfigVariant::UPDI
|
||||
? Avr8MemoryType::REGISTER_FILE : Avr8MemoryType::SRAM
|
||||
);
|
||||
const auto memoryType = (registerType != TargetRegisterType::GENERAL_PURPOSE_REGISTER) ?
|
||||
Avr8MemoryType::SRAM
|
||||
: (this->configVariant == Avr8ConfigVariant::XMEGA || this->configVariant == Avr8ConfigVariant::UPDI
|
||||
? Avr8MemoryType::REGISTER_FILE : Avr8MemoryType::SRAM);
|
||||
|
||||
/*
|
||||
* When reading the entire range, we must avoid any attempts to access the OCD data register (OCDDR), as the
|
||||
* debug tool will reject the command and respond with a 0x36 error code (invalid address error).
|
||||
* When reading the entire range, we must avoid any attempts to access the OCD data register (OCDDR), as
|
||||
* the debug tool will reject the command and respond with a 0x36 error code (invalid address error).
|
||||
*
|
||||
* For this reason, we specify the OCDDR address as an excluded address. This will mean
|
||||
* the EdbgAvr8Interface::readMemory() function will employ the masked read memory command, as opposed to the
|
||||
* general read memory command. The masked read memory command allows us to specify which addresses to
|
||||
* the EdbgAvr8Interface::readMemory() function will employ the masked read memory command, as opposed to
|
||||
* the general read memory command. The masked read memory command allows us to specify which addresses to
|
||||
* read and which ones to ignore. For ignored addresses, the debug tool will just return a 0x00 byte.
|
||||
* For more info, see section 7.1.22 titled 'Memory Read Masked', in the EDBG protocol document.
|
||||
*
|
||||
@@ -495,7 +499,7 @@ TargetRegisters EdbgAvr8Interface::readRegisters(const TargetRegisterDescriptors
|
||||
if (flatMemoryBuffer.size() != bufferSize) {
|
||||
throw Exception(
|
||||
"Failed to read memory within register type address range (" + std::to_string(startAddress)
|
||||
+ " - " + std::to_string(endAddress) +"). Expected " + std::to_string(bufferSize)
|
||||
+ " - " + std::to_string(endAddress) + "). Expected " + std::to_string(bufferSize)
|
||||
+ " bytes, got " + std::to_string(flatMemoryBuffer.size())
|
||||
);
|
||||
}
|
||||
@@ -522,9 +526,9 @@ TargetRegisters EdbgAvr8Interface::readRegisters(const TargetRegisterDescriptors
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::writeRegisters(const Targets::TargetRegisters& registers) {
|
||||
void EdbgAvr8Interface::writeRegisters(const Targets::TargetRegisters& registers) {
|
||||
for (const auto& reg : registers) {
|
||||
const auto& registerDescriptor = reg.descriptor;
|
||||
auto registerValue = reg.value;
|
||||
@@ -561,14 +565,14 @@ void EdbgAvr8Interface::writeRegisters(const Targets::TargetRegisters& registers
|
||||
registerValue
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TargetMemoryBuffer EdbgAvr8Interface::readMemory(
|
||||
TargetMemoryBuffer EdbgAvr8Interface::readMemory(
|
||||
TargetMemoryType memoryType,
|
||||
std::uint32_t startAddress,
|
||||
std::uint32_t bytes,
|
||||
const std::set<Targets::TargetMemoryAddressRange>& excludedAddressRanges
|
||||
) {
|
||||
) {
|
||||
auto avr8MemoryType = Avr8MemoryType::SRAM;
|
||||
|
||||
switch (memoryType) {
|
||||
@@ -580,7 +584,8 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
|
||||
if (this->configVariant == Avr8ConfigVariant::DEBUG_WIRE) {
|
||||
avr8MemoryType = Avr8MemoryType::FLASH_PAGE;
|
||||
|
||||
} else if (this->configVariant == Avr8ConfigVariant::XMEGA || this->configVariant == Avr8ConfigVariant::UPDI) {
|
||||
} else if (this->configVariant == Avr8ConfigVariant::XMEGA
|
||||
|| this->configVariant == Avr8ConfigVariant::UPDI) {
|
||||
avr8MemoryType = Avr8MemoryType::APPL_FLASH;
|
||||
|
||||
} else {
|
||||
@@ -617,9 +622,13 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
|
||||
}
|
||||
|
||||
return this->readMemory(avr8MemoryType, startAddress, bytes, excludedAddresses);
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::writeMemory(TargetMemoryType memoryType, std::uint32_t startAddress, const TargetMemoryBuffer& buffer) {
|
||||
void EdbgAvr8Interface::writeMemory(
|
||||
TargetMemoryType memoryType,
|
||||
std::uint32_t startAddress,
|
||||
const TargetMemoryBuffer& buffer
|
||||
) {
|
||||
auto avr8MemoryType = Avr8MemoryType::SRAM;
|
||||
|
||||
switch (memoryType) {
|
||||
@@ -635,7 +644,8 @@ void EdbgAvr8Interface::writeMemory(TargetMemoryType memoryType, std::uint32_t s
|
||||
avr8MemoryType = Avr8MemoryType::FLASH_PAGE;
|
||||
// TODO: Enable programming mode
|
||||
|
||||
} else if (this->configVariant == Avr8ConfigVariant::XMEGA || this->configVariant == Avr8ConfigVariant::UPDI) {
|
||||
} else if (this->configVariant == Avr8ConfigVariant::XMEGA
|
||||
|| this->configVariant == Avr8ConfigVariant::UPDI) {
|
||||
avr8MemoryType = Avr8MemoryType::APPL_FLASH;
|
||||
|
||||
} else {
|
||||
@@ -652,9 +662,9 @@ void EdbgAvr8Interface::writeMemory(TargetMemoryType memoryType, std::uint32_t s
|
||||
}
|
||||
|
||||
return this->writeMemory(avr8MemoryType, startAddress, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
TargetState EdbgAvr8Interface::getTargetState() {
|
||||
TargetState EdbgAvr8Interface::getTargetState() {
|
||||
/*
|
||||
* We are not informed when a target goes from a stopped state to a running state, so there is no need
|
||||
* to query the tool when we already know the target has stopped.
|
||||
@@ -667,18 +677,18 @@ TargetState EdbgAvr8Interface::getTargetState() {
|
||||
}
|
||||
|
||||
return this->targetState;
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::setParameter(const Avr8EdbgParameter& parameter, const std::vector<unsigned char>& value) {
|
||||
void EdbgAvr8Interface::setParameter(const Avr8EdbgParameter& parameter, const std::vector<unsigned char>& value) {
|
||||
auto commandFrame = CommandFrames::Avr8Generic::SetParameter(parameter, value);
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
||||
throw Avr8CommandFailure("Failed to set parameter on device!", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned char> EdbgAvr8Interface::getParameter(const Avr8EdbgParameter& parameter, std::uint8_t size) {
|
||||
std::vector<unsigned char> EdbgAvr8Interface::getParameter(const Avr8EdbgParameter& parameter, std::uint8_t size) {
|
||||
auto commandFrame = CommandFrames::Avr8Generic::GetParameter(parameter, size);
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
@@ -687,9 +697,9 @@ std::vector<unsigned char> EdbgAvr8Interface::getParameter(const Avr8EdbgParamet
|
||||
}
|
||||
|
||||
return response.getPayloadData();
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::setDebugWireAndJtagParameters() {
|
||||
void EdbgAvr8Interface::setDebugWireAndJtagParameters() {
|
||||
if (this->targetParameters.flashPageSize.has_value()) {
|
||||
Logger::debug("Setting DEVICE_FLASH_PAGE_SIZE AVR8 parameter");
|
||||
this->setParameter(
|
||||
@@ -772,8 +782,8 @@ void EdbgAvr8Interface::setDebugWireAndJtagParameters() {
|
||||
|
||||
/*
|
||||
* All addresses for registers that reside in the mapped IO memory segment include the mapped IO segment offset
|
||||
* (start address). But the EDBG protocol requires *some* of these addresses to be stripped of this offset before
|
||||
* sending them as target parameters.
|
||||
* (start address). But the EDBG protocol requires *some* of these addresses to be stripped of this offset
|
||||
* before sending them as target parameters.
|
||||
*
|
||||
* This applies to the following addresses:
|
||||
*
|
||||
@@ -836,9 +846,9 @@ void EdbgAvr8Interface::setDebugWireAndJtagParameters() {
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::setPdiParameters() {
|
||||
void EdbgAvr8Interface::setPdiParameters() {
|
||||
if (!this->targetParameters.appSectionPdiOffset.has_value()) {
|
||||
throw DeviceInitializationFailure("Missing required parameter: APPL_BASE_ADDR");
|
||||
}
|
||||
@@ -978,26 +988,27 @@ void EdbgAvr8Interface::setPdiParameters() {
|
||||
Avr8EdbgParameters::DEVICE_XMEGA_NVM_BASE,
|
||||
this->targetParameters.nvmBaseAddress.value()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::setUpdiParameters() {
|
||||
void EdbgAvr8Interface::setUpdiParameters() {
|
||||
if (!this->targetParameters.signatureSegmentStartAddress.has_value()) {
|
||||
throw DeviceInitializationFailure("Missing required parameter: SIGNATURE BASE ADDRESS");
|
||||
}
|
||||
|
||||
if (this->targetParameters.programMemoryUpdiStartAddress.has_value()) {
|
||||
/*
|
||||
* The program memory base address field for UPDI sessions (DEVICE_UPDI_PROGMEM_BASE_ADDR) seems to be limited
|
||||
* to two bytes in size, as opposed to the four byte size for the debugWire, JTAG and PDI equivalent fields.
|
||||
* This is why, I suspect, another field was required for the most significant byte of the program memory base
|
||||
* address (DEVICE_UPDI_PROGMEM_BASE_ADDR_MSB).
|
||||
* The program memory base address field for UPDI sessions (DEVICE_UPDI_PROGMEM_BASE_ADDR) seems to be
|
||||
* limited to two bytes in size, as opposed to the four byte size for the debugWire, JTAG and PDI
|
||||
* equivalent fields. This is why, I suspect, another field was required for the most significant byte of
|
||||
* the program memory base address (DEVICE_UPDI_PROGMEM_BASE_ADDR_MSB).
|
||||
*
|
||||
* The additional DEVICE_UPDI_PROGMEM_BASE_ADDR_MSB field is only one byte in size, so it brings the total
|
||||
* capacity for the program memory base address to three bytes. Because of this, we ensure that all TDFs, for
|
||||
* targets that support UPDI, specify an address that does not exceed the maximum value of a 24 bit unsigned
|
||||
* integer. This is done in our TDF validation script (see src/Targets/TargetDescription/README.md for more).
|
||||
* capacity for the program memory base address to three bytes. Because of this, we ensure that all TDFs,
|
||||
* for targets that support UPDI, specify an address that does not exceed the maximum value of a 24 bit
|
||||
* unsigned integer. This is done in our TDF validation script (see src/Targets/TargetDescription/README.md
|
||||
* for more).
|
||||
*/
|
||||
auto programMemBaseAddress = this->targetParameters.programMemoryUpdiStartAddress.value();
|
||||
const auto programMemBaseAddress = this->targetParameters.programMemoryUpdiStartAddress.value();
|
||||
Logger::debug("Setting DEVICE_UPDI_PROGMEM_BASE_ADDR AVR8 parameter");
|
||||
this->setParameter(
|
||||
Avr8EdbgParameters::DEVICE_UPDI_PROGMEM_BASE_ADDR,
|
||||
@@ -1116,9 +1127,9 @@ void EdbgAvr8Interface::setUpdiParameters() {
|
||||
this->targetParameters.programMemoryUpdiStartAddress.value_or(0) > 0xFFFF ?
|
||||
static_cast<std::uint8_t>(1) : static_cast<std::uint8_t>(0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::activatePhysical(bool applyExternalReset) {
|
||||
void EdbgAvr8Interface::activatePhysical(bool applyExternalReset) {
|
||||
auto commandFrame = CommandFrames::Avr8Generic::ActivatePhysical(applyExternalReset);
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
@@ -1134,9 +1145,9 @@ void EdbgAvr8Interface::activatePhysical(bool applyExternalReset) {
|
||||
}
|
||||
|
||||
this->physicalInterfaceActivated = true;
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::deactivatePhysical() {
|
||||
void EdbgAvr8Interface::deactivatePhysical() {
|
||||
auto commandFrame = CommandFrames::Avr8Generic::DeactivatePhysical();
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
@@ -1145,12 +1156,12 @@ void EdbgAvr8Interface::deactivatePhysical() {
|
||||
}
|
||||
|
||||
this->physicalInterfaceActivated = false;
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::attach() {
|
||||
void EdbgAvr8Interface::attach() {
|
||||
/*
|
||||
* When attaching an ATmega target that is connected via JTAG, we must not set the breakAfterAttach flag, as this
|
||||
* results in a timeout.
|
||||
* When attaching an ATmega target that is connected via JTAG, we must not set the breakAfterAttach flag, as
|
||||
* this results in a timeout.
|
||||
*
|
||||
* However, in this case the attach command seems to _sometimes_ halt the target anyway, regardless of the
|
||||
* value of the breakAfterAttach flag. So we still expect a stop event to be received shortly after issuing
|
||||
@@ -1172,11 +1183,13 @@ void EdbgAvr8Interface::attach() {
|
||||
this->waitForStoppedEvent();
|
||||
|
||||
} catch (const Exception& exception) {
|
||||
Logger::error("Execution on AVR8 target could not be halted post attach - " + exception.getMessage());
|
||||
Logger::error(
|
||||
"Execution on AVR8 target could not be halted post attach - " + exception.getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::detach() {
|
||||
void EdbgAvr8Interface::detach() {
|
||||
auto commandFrame = CommandFrames::Avr8Generic::Detach();
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
@@ -1185,9 +1198,9 @@ void EdbgAvr8Interface::detach() {
|
||||
}
|
||||
|
||||
this->targetAttached = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<AvrEvent> EdbgAvr8Interface::getAvrEvent() {
|
||||
std::unique_ptr<AvrEvent> EdbgAvr8Interface::getAvrEvent() {
|
||||
auto event = this->edbgInterface.requestAvrEvent();
|
||||
|
||||
if (!event.has_value()) {
|
||||
@@ -1207,18 +1220,18 @@ std::unique_ptr<AvrEvent> EdbgAvr8Interface::getAvrEvent() {
|
||||
return std::make_unique<AvrEvent>(event.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::clearEvents() {
|
||||
void EdbgAvr8Interface::clearEvents() {
|
||||
while (this->getAvrEvent() != nullptr) {}
|
||||
}
|
||||
}
|
||||
|
||||
TargetMemoryBuffer EdbgAvr8Interface::readMemory(
|
||||
TargetMemoryBuffer EdbgAvr8Interface::readMemory(
|
||||
Avr8MemoryType type,
|
||||
std::uint32_t startAddress,
|
||||
std::uint32_t bytes,
|
||||
const std::set<std::uint32_t>& excludedAddresses
|
||||
) {
|
||||
) {
|
||||
if (!excludedAddresses.empty() && (this->avoidMaskedMemoryRead || type != Avr8MemoryType::SRAM)) {
|
||||
/*
|
||||
* Driver-side masked memory read.
|
||||
@@ -1330,10 +1343,11 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
|
||||
* aaaabbbbccccdddd
|
||||
* ^
|
||||
* But now we'll only be reading 4 bytes from start address 0x04, meaning we won't be reading
|
||||
* that 4th byte (0x08). So we need to account for this by adding the difference of the requested start
|
||||
* address and the aligned start address to the number of bytes to read, to ensure that we're reading
|
||||
* all of the bytes that we're interested in. But this will throw off the aligned bytes!! So we need
|
||||
* to also account for this by aligning the additional bytes before adding them to alignedBytesToRead.
|
||||
* that 4th byte (0x08). So we need to account for this by adding the difference of the requested
|
||||
* start address and the aligned start address to the number of bytes to read, to ensure that we're
|
||||
* reading all of the bytes that we're interested in. But this will throw off the aligned bytes!!
|
||||
* So we need to also account for this by aligning the additional bytes before adding them to
|
||||
* alignedBytesToRead.
|
||||
*
|
||||
* However, we could simply get away with just adding the bytes without aligning
|
||||
* them (alignedBytesToRead += (address - alignedAddress);), as the subsequent recursive call will
|
||||
@@ -1404,7 +1418,8 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
|
||||
if (type != Avr8MemoryType::FLASH_PAGE) {
|
||||
/*
|
||||
* EDBG AVR8 debug tools behave in a really weird way when responding with more than two packets
|
||||
* for a single read (non-flash) memory command. The data they return in this case appears to be of little use.
|
||||
* for a single read (non-flash) memory command. The data they return in this case appears to be of little
|
||||
* use.
|
||||
*
|
||||
* To address this, we make sure we only issue read memory commands that will result in no more than two
|
||||
* response packets. For calls that require more than this, we simply split them into numerous calls.
|
||||
@@ -1421,14 +1436,16 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
|
||||
|
||||
if (totalResponsePackets > 2) {
|
||||
/*
|
||||
* This call to readMemory() will result in more than two response packets, so split it into multiple calls
|
||||
* that will result in no more than two response packets per call.
|
||||
* This call to readMemory() will result in more than two response packets, so split it into multiple
|
||||
* calls that will result in no more than two response packets per call.
|
||||
*/
|
||||
auto output = std::vector<unsigned char>();
|
||||
|
||||
for (float i = 1; i <= totalReadsRequired; i++) {
|
||||
auto bytesToRead = static_cast<std::uint32_t>((bytes - output.size()) > (singlePacketSize * 2) ?
|
||||
(singlePacketSize * 2) : bytes - output.size());
|
||||
auto bytesToRead = static_cast<std::uint32_t>(
|
||||
(bytes - output.size()) > (singlePacketSize * 2) ? (singlePacketSize * 2)
|
||||
: bytes - output.size()
|
||||
);
|
||||
auto data = this->readMemory(
|
||||
type,
|
||||
static_cast<std::uint32_t>(startAddress + output.size()),
|
||||
@@ -1454,9 +1471,9 @@ TargetMemoryBuffer EdbgAvr8Interface::readMemory(
|
||||
}
|
||||
|
||||
return response.getMemoryBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::writeMemory(Avr8MemoryType type, std::uint32_t address, const TargetMemoryBuffer& buffer) {
|
||||
void EdbgAvr8Interface::writeMemory(Avr8MemoryType type, std::uint32_t address, const TargetMemoryBuffer& buffer) {
|
||||
if (type == Avr8MemoryType::FLASH_PAGE) {
|
||||
// TODO: Implement support for writing to flash
|
||||
throw Exception("Writing to flash memory is not supported.");
|
||||
@@ -1471,9 +1488,9 @@ void EdbgAvr8Interface::writeMemory(Avr8MemoryType type, std::uint32_t address,
|
||||
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
||||
throw Avr8CommandFailure("AVR8 Write memory command failed", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::refreshTargetState() {
|
||||
void EdbgAvr8Interface::refreshTargetState() {
|
||||
auto avrEvent = this->getAvrEvent();
|
||||
|
||||
if (avrEvent != nullptr && avrEvent->getEventId() == AvrEventId::AVR8_BREAK_EVENT) {
|
||||
@@ -1488,18 +1505,18 @@ void EdbgAvr8Interface::refreshTargetState() {
|
||||
}
|
||||
|
||||
this->targetState = TargetState::RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::disableDebugWire() {
|
||||
void EdbgAvr8Interface::disableDebugWire() {
|
||||
auto commandFrame = CommandFrames::Avr8Generic::DisableDebugWire();
|
||||
|
||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(commandFrame);
|
||||
if (response.getResponseId() == Avr8ResponseId::FAILED) {
|
||||
throw Avr8CommandFailure("AVR8 Disable debugWire command failed", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdbgAvr8Interface::waitForStoppedEvent() {
|
||||
void EdbgAvr8Interface::waitForStoppedEvent() {
|
||||
auto breakEvent = this->waitForAvrEvent<BreakEvent>();
|
||||
|
||||
if (breakEvent == nullptr) {
|
||||
@@ -1507,4 +1524,5 @@ void EdbgAvr8Interface::waitForStoppedEvent() {
|
||||
}
|
||||
|
||||
this->targetState = TargetState::STOPPED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Targets;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void BreakEvent::init(const AvrEvent& event) {
|
||||
using Bloom::Targets::TargetBreakCause;
|
||||
|
||||
void BreakEvent::init(const AvrEvent& event) {
|
||||
AvrEvent::init(event);
|
||||
auto& data = this->getEventData();
|
||||
const auto& data = this->getEventData();
|
||||
|
||||
if (data.size() < 8) {
|
||||
/*
|
||||
@@ -22,8 +24,11 @@ void BreakEvent::init(const AvrEvent& event) {
|
||||
}
|
||||
|
||||
// Program counter consists of 4 bytes
|
||||
this->programCounter = static_cast<std::uint32_t>((data[4] << 24) | (data[3] << 16) | (data[2] << 8) | data[1]) * 2;
|
||||
this->programCounter = static_cast<std::uint32_t>(
|
||||
(data[4] << 24) | (data[3] << 16) | (data[2] << 8) | data[1]
|
||||
) * 2;
|
||||
|
||||
// Break cause is 1 byte, where 0x01 is 'program breakpoint' and 0x00 'unspecified'
|
||||
this->breakCause = data[7] == 0x01 ? TargetBreakCause::BREAKPOINT : TargetBreakCause::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,22 +2,23 @@
|
||||
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void AvrResponseFrame::initFromAvrResponses(const std::vector<AvrResponse>& avrResponses) {
|
||||
void AvrResponseFrame::initFromAvrResponses(const std::vector<AvrResponse>& avrResponses) {
|
||||
// Build a raw frame buffer from the AVRResponse objects and just call initFromRawFrame()
|
||||
std::vector<unsigned char> rawFrame;
|
||||
|
||||
for (auto& avrResponse : avrResponses) {
|
||||
for (const auto& avrResponse : avrResponses) {
|
||||
auto responsePacket = avrResponse.getResponsePacket();
|
||||
rawFrame.insert(rawFrame.end(), responsePacket.begin(), responsePacket.end());
|
||||
}
|
||||
|
||||
return this->initFromRawFrame(rawFrame);
|
||||
}
|
||||
}
|
||||
|
||||
void AvrResponseFrame::initFromRawFrame(const std::vector<unsigned char>& rawFrame) {
|
||||
void AvrResponseFrame::initFromRawFrame(const std::vector<unsigned char>& rawFrame) {
|
||||
if (rawFrame.size() < 4) {
|
||||
// All AVR response frames must consist of at least four bytes (SOF, sequence ID (two bytes) and
|
||||
// a protocol handler ID)
|
||||
@@ -34,4 +35,5 @@ void AvrResponseFrame::initFromRawFrame(const std::vector<unsigned char>& rawFra
|
||||
|
||||
auto& payload = this->getPayload();
|
||||
payload.insert(payload.begin(), rawFrame.begin() + 4, rawFrame.end());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,15 +4,13 @@
|
||||
|
||||
#include "src/TargetController/Exceptions/DeviceCommunicationFailure.hpp"
|
||||
|
||||
using namespace Bloom::DebugToolDrivers;
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg;
|
||||
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
Protocols::CmsisDap::Response EdbgInterface::sendAvrCommandFrameAndWaitForResponse(
|
||||
Protocols::CmsisDap::Response EdbgInterface::sendAvrCommandFrameAndWaitForResponse(
|
||||
const Protocols::CmsisDap::Edbg::Avr::AvrCommandFrame& avrCommandFrame
|
||||
) {
|
||||
) {
|
||||
// An AVR command frame can be split into multiple CMSIS-DAP commands. Each command
|
||||
// containing a fragment of the AvrCommandFrame.
|
||||
|
||||
@@ -25,8 +23,8 @@ Protocols::CmsisDap::Response EdbgInterface::sendAvrCommandFrameAndWaitForRespon
|
||||
// Send command to device
|
||||
auto response = this->sendCommandAndWaitForResponse(avrCommand);
|
||||
|
||||
if (&avrCommand ==& avrCommands.back()) {
|
||||
return* response;
|
||||
if (&avrCommand == &avrCommands.back()) {
|
||||
return *response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,9 +32,9 @@ Protocols::CmsisDap::Response EdbgInterface::sendAvrCommandFrameAndWaitForRespon
|
||||
throw DeviceCommunicationFailure(
|
||||
"Cannot send AVR command frame - failed to generate CMSIS-DAP Vendor (AVR) commands"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Protocols::CmsisDap::Edbg::Avr::AvrResponse EdbgInterface::getAvrResponse() {
|
||||
Protocols::CmsisDap::Edbg::Avr::AvrResponse EdbgInterface::getAvrResponse() {
|
||||
auto cmsisResponse = this->getResponse();
|
||||
|
||||
if (cmsisResponse->getResponseId() == 0x81) {
|
||||
@@ -44,12 +42,12 @@ Protocols::CmsisDap::Edbg::Avr::AvrResponse EdbgInterface::getAvrResponse() {
|
||||
auto avrResponse = Protocols::CmsisDap::Edbg::Avr::AvrResponse();
|
||||
avrResponse.init(*cmsisResponse);
|
||||
return avrResponse;
|
||||
} else {
|
||||
}
|
||||
|
||||
throw DeviceCommunicationFailure("Unexpected response to AvrResponseCommand from device");
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Protocols::CmsisDap::Edbg::Avr::AvrEvent> EdbgInterface::requestAvrEvent() {
|
||||
std::optional<Protocols::CmsisDap::Edbg::Avr::AvrEvent> EdbgInterface::requestAvrEvent() {
|
||||
this->sendCommand(AvrEventCommand());
|
||||
auto cmsisResponse = this->getResponse();
|
||||
|
||||
@@ -57,13 +55,15 @@ std::optional<Protocols::CmsisDap::Edbg::Avr::AvrEvent> EdbgInterface::requestAv
|
||||
// This is an AVR_EVT response
|
||||
auto avrEvent = Protocols::CmsisDap::Edbg::Avr::AvrEvent();
|
||||
avrEvent.init(*cmsisResponse);
|
||||
return avrEvent.getEventDataSize() > 0 ? std::optional(avrEvent): std::nullopt;
|
||||
} else {
|
||||
return avrEvent.getEventDataSize() > 0 ? std::optional(avrEvent) : std::nullopt;
|
||||
}
|
||||
|
||||
throw DeviceCommunicationFailure("Unexpected response to AvrEventCommand from device");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Protocols::CmsisDap::Edbg::Avr::AvrResponse> EdbgInterface::requestAvrResponses() {
|
||||
std::vector<Protocols::CmsisDap::Edbg::Avr::AvrResponse> EdbgInterface::requestAvrResponses() {
|
||||
using Protocols::CmsisDap::Edbg::Avr::AvrResponseCommand;
|
||||
|
||||
std::vector<Protocols::CmsisDap::Edbg::Avr::AvrResponse> responses;
|
||||
AvrResponseCommand responseCommand;
|
||||
|
||||
@@ -84,9 +84,12 @@ std::vector<Protocols::CmsisDap::Edbg::Avr::AvrResponse> EdbgInterface::requestA
|
||||
}
|
||||
|
||||
if (response.getFragmentCount() == 0 && response.getFragmentNumber() == 0) {
|
||||
throw DeviceCommunicationFailure("Failed to fetch AVRResponse objects - unexpected empty response");
|
||||
throw DeviceCommunicationFailure(
|
||||
"Failed to fetch AVRResponse objects - unexpected empty response"
|
||||
);
|
||||
}
|
||||
|
||||
} else if (response.getFragmentNumber() == 0) {
|
||||
if (response.getFragmentNumber() == 0) {
|
||||
// End of response data ( &this packet can be ignored)
|
||||
break;
|
||||
}
|
||||
@@ -95,4 +98,5 @@ std::vector<Protocols::CmsisDap::Edbg::Avr::AvrResponse> EdbgInterface::requestA
|
||||
}
|
||||
|
||||
return responses;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceCommunicationFailure.hpp"
|
||||
|
||||
using namespace Bloom::Usb;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::Usb
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void HidInterface::init() {
|
||||
void HidInterface::init() {
|
||||
if (this->libUsbDevice == nullptr) {
|
||||
throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer.");
|
||||
}
|
||||
@@ -25,7 +26,8 @@ void HidInterface::init() {
|
||||
|
||||
if (hidDevice->input_ep_max_packet_size < 1) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Invalid max packet size for USB endpoint, on interface " + std::to_string(this->getNumber())
|
||||
"Invalid max packet size for USB endpoint, on interface "
|
||||
+ std::to_string(this->getNumber())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,9 +35,9 @@ void HidInterface::init() {
|
||||
this->setInputReportSize(static_cast<std::size_t>(hidDevice->input_ep_max_packet_size));
|
||||
this->libUsbDeviceHandle = hidDevice->device_handle;
|
||||
this->initialised = true;
|
||||
}
|
||||
}
|
||||
|
||||
void HidInterface::close() {
|
||||
void HidInterface::close() {
|
||||
auto* hidDevice = this->getHidDevice();
|
||||
|
||||
if (hidDevice != nullptr) {
|
||||
@@ -47,9 +49,9 @@ void HidInterface::close() {
|
||||
|
||||
hid_exit();
|
||||
Interface::close();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned char> HidInterface::read(unsigned int timeout) {
|
||||
std::vector<unsigned char> HidInterface::read(unsigned int timeout) {
|
||||
std::vector<unsigned char> output;
|
||||
auto readSize = this->getInputReportSize();
|
||||
|
||||
@@ -67,9 +69,9 @@ std::vector<unsigned char> HidInterface::read(unsigned int timeout) {
|
||||
|
||||
output.resize(totalByteCount);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
void HidInterface::write(std::vector<unsigned char> buffer) {
|
||||
void HidInterface::write(std::vector<unsigned char> buffer) {
|
||||
if (buffer.size() > this->getInputReportSize()) {
|
||||
throw DeviceCommunicationFailure(
|
||||
"Cannot send data via HID interface - data exceeds maximum packet size."
|
||||
@@ -92,9 +94,9 @@ void HidInterface::write(std::vector<unsigned char> buffer) {
|
||||
+ " bytes to HID interface. Bytes written: " + std::to_string(transferred));
|
||||
throw DeviceCommunicationFailure("Failed to write data to HID interface.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t HidInterface::read(unsigned char* buffer, std::size_t maxLength, unsigned int timeout) {
|
||||
std::size_t HidInterface::read(unsigned char* buffer, std::size_t maxLength, unsigned int timeout) {
|
||||
int transferred;
|
||||
|
||||
if ((transferred = hid_read_timeout(
|
||||
@@ -108,10 +110,13 @@ std::size_t HidInterface::read(unsigned char* buffer, std::size_t maxLength, uns
|
||||
}
|
||||
|
||||
return static_cast<std::size_t>(transferred);
|
||||
}
|
||||
}
|
||||
|
||||
std::string HidInterface::getDevicePathByInterfaceNumber(const std::uint16_t& interfaceNumber) {
|
||||
hid_device_info* hidDeviceInfoList = hid_enumerate(this->getVendorId(), this->getProductId());
|
||||
std::string HidInterface::getDevicePathByInterfaceNumber(const std::uint16_t& interfaceNumber) {
|
||||
hid_device_info* hidDeviceInfoList = hid_enumerate(
|
||||
this->getVendorId(),
|
||||
this->getProductId()
|
||||
);
|
||||
|
||||
while (hidDeviceInfoList != nullptr) {
|
||||
if (hidDeviceInfoList->interface_number == interfaceNumber) {
|
||||
@@ -128,4 +133,5 @@ std::string HidInterface::getDevicePathByInterfaceNumber(const std::uint16_t& in
|
||||
auto path = std::string(hidDeviceInfoList->path);
|
||||
hid_free_enumeration(hidDeviceInfoList);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#include "Interface.hpp"
|
||||
|
||||
#include <libusb-1.0/libusb.h>
|
||||
#include <chrono>
|
||||
|
||||
#include "src/TargetController/Exceptions/DeviceFailure.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceCommunicationFailure.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
|
||||
using namespace Bloom::Usb;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::Usb
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void Interface::init() {
|
||||
void Interface::init() {
|
||||
if (this->libUsbDevice == nullptr) {
|
||||
throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer.");
|
||||
}
|
||||
@@ -20,17 +20,17 @@ void Interface::init() {
|
||||
}
|
||||
|
||||
this->initialised = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Interface::close() {
|
||||
void Interface::close() {
|
||||
if (this->libUsbDeviceHandle != nullptr) {
|
||||
this->release();
|
||||
}
|
||||
|
||||
this->initialised = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Interface::claim() {
|
||||
void Interface::claim() {
|
||||
int interfaceNumber = this->getNumber();
|
||||
|
||||
this->detachKernelDriver();
|
||||
@@ -42,9 +42,9 @@ void Interface::claim() {
|
||||
}
|
||||
|
||||
this->claimed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Interface::detachKernelDriver() {
|
||||
void Interface::detachKernelDriver() {
|
||||
int interfaceNumber = this->getNumber();
|
||||
int libUsbStatusCode;
|
||||
|
||||
@@ -59,21 +59,22 @@ void Interface::detachKernelDriver() {
|
||||
throw DeviceInitializationFailure("Failed to check for active kernel driver on USB interface.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Interface::release() {
|
||||
void Interface::release() {
|
||||
if (this->isClaimed()) {
|
||||
if (libusb_release_interface(this->libUsbDeviceHandle, this->getNumber()) != 0) {
|
||||
throw DeviceFailure(
|
||||
"Failed to release interface {" + std::to_string(this->getNumber()) + "} on USB device\n"
|
||||
"Failed to release interface {" + std::to_string(this->getNumber())
|
||||
+ "} on USB device\n"
|
||||
);
|
||||
}
|
||||
|
||||
this->claimed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Interface::read(unsigned char* buffer, unsigned char endPoint, size_t length, size_t timeout) {
|
||||
int Interface::read(unsigned char* buffer, unsigned char endPoint, size_t length, size_t timeout) {
|
||||
int totalTransferred = 0;
|
||||
int transferred = 0;
|
||||
int libUsbStatusCode = 0;
|
||||
@@ -98,9 +99,9 @@ int Interface::read(unsigned char* buffer, unsigned char endPoint, size_t length
|
||||
}
|
||||
|
||||
return transferred;
|
||||
}
|
||||
}
|
||||
|
||||
void Interface::write(unsigned char* buffer, unsigned char endPoint, int length) {
|
||||
void Interface::write(unsigned char* buffer, unsigned char endPoint, int length) {
|
||||
int transferred = 0;
|
||||
int libUsbStatusCode = 0;
|
||||
|
||||
@@ -118,4 +119,5 @@ void Interface::write(unsigned char* buffer, unsigned char endPoint, int length)
|
||||
"Failed to read from USB device. Error code returned: " + std::to_string(libUsbStatusCode)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,18 +3,20 @@
|
||||
#include "src/Logger/Logger.hpp"
|
||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||
|
||||
using Bloom::Usb::UsbDevice;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::Usb
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void UsbDevice::init() {
|
||||
void UsbDevice::init() {
|
||||
libusb_init(&this->libUsbContext);
|
||||
// libusb_set_option(this->libUsbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE);
|
||||
auto devices = this->findMatchingDevices();
|
||||
|
||||
if (devices.empty()) {
|
||||
throw DeviceInitializationFailure("Failed to find USB device with matching vendor & product ID.");
|
||||
}
|
||||
|
||||
} else if (devices.size() > 1) {
|
||||
if (devices.size() > 1) {
|
||||
// TODO: implement support for multiple devices (maybe via serial number?)
|
||||
throw DeviceInitializationFailure(
|
||||
"Numerous devices of matching vendor & product ID found.\n"
|
||||
@@ -23,57 +25,59 @@ void UsbDevice::init() {
|
||||
}
|
||||
|
||||
// For now, just use the first device found.
|
||||
auto device = devices.front();
|
||||
auto* device = devices.front();
|
||||
this->setLibUsbDevice(device);
|
||||
|
||||
int libUsbStatusCode;
|
||||
const int libUsbStatusCode = libusb_open(libUsbDevice, &this->libUsbDeviceHandle);
|
||||
|
||||
// Obtain a device handle from libusb
|
||||
if ((libUsbStatusCode = libusb_open(libUsbDevice, &this->libUsbDeviceHandle)) < 0) {
|
||||
if (libUsbStatusCode < 0) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to open USB device - error code " + std::to_string(libUsbStatusCode) + " returned."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UsbDevice::setConfiguration(int configIndex) {
|
||||
void UsbDevice::setConfiguration(int configIndex) {
|
||||
libusb_config_descriptor* configDescriptor = {};
|
||||
int libUsbStatusCode;
|
||||
int libUsbStatusCode = libusb_get_config_descriptor(this->libUsbDevice, 0, &configDescriptor);
|
||||
|
||||
if ((libUsbStatusCode = libusb_get_config_descriptor(this->libUsbDevice, 0, &configDescriptor))) {
|
||||
if (libUsbStatusCode < 0) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to obtain USB configuration descriptor - error code " + std::to_string(libUsbStatusCode)
|
||||
+ " returned."
|
||||
);
|
||||
}
|
||||
|
||||
if ((libUsbStatusCode = libusb_set_configuration(this->libUsbDeviceHandle, configDescriptor->bConfigurationValue))) {
|
||||
libUsbStatusCode = libusb_set_configuration(this->libUsbDeviceHandle, configDescriptor->bConfigurationValue);
|
||||
if (libUsbStatusCode < 0) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to set USB configuration - error code " + std::to_string(libUsbStatusCode) + " returned."
|
||||
);
|
||||
}
|
||||
|
||||
libusb_free_config_descriptor(configDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<libusb_device*> UsbDevice::findMatchingDevices(
|
||||
std::vector<libusb_device*> UsbDevice::findMatchingDevices(
|
||||
std::optional<std::uint16_t> vendorId, std::optional<std::uint16_t> productId
|
||||
) {
|
||||
auto libUsbContext = this->libUsbContext;
|
||||
) {
|
||||
auto* libUsbContext = this->libUsbContext;
|
||||
libusb_device** devices = nullptr;
|
||||
libusb_device* device;
|
||||
std::vector<libusb_device*> matchedDevices;
|
||||
ssize_t i = 0, libUsbStatusCode;
|
||||
|
||||
auto vendorIdToMatch = vendorId.value_or(this->vendorId);
|
||||
auto productIdToMatch = productId.value_or(this->productId);
|
||||
|
||||
if ((libUsbStatusCode = libusb_get_device_list(libUsbContext, &devices)) < 0) {
|
||||
ssize_t libUsbStatusCode = libusb_get_device_list(libUsbContext, &devices);
|
||||
if (libUsbStatusCode < 0) {
|
||||
throw DeviceInitializationFailure(
|
||||
"Failed to retrieve USB devices - return code: '" + std::to_string(libUsbStatusCode) + "'"
|
||||
);
|
||||
}
|
||||
|
||||
ssize_t i = 0;
|
||||
while ((device = devices[i++]) != nullptr) {
|
||||
struct libusb_device_descriptor desc = {};
|
||||
|
||||
@@ -90,9 +94,9 @@ std::vector<libusb_device*> UsbDevice::findMatchingDevices(
|
||||
|
||||
libusb_free_device_list(devices, 1);
|
||||
return matchedDevices;
|
||||
}
|
||||
}
|
||||
|
||||
void UsbDevice::close() {
|
||||
void UsbDevice::close() {
|
||||
if (this->libUsbDeviceHandle != nullptr) {
|
||||
libusb_close(this->libUsbDeviceHandle);
|
||||
this->libUsbDeviceHandle = nullptr;
|
||||
@@ -101,4 +105,5 @@ void UsbDevice::close() {
|
||||
if (this->libUsbContext != nullptr) {
|
||||
libusb_exit(this->libUsbContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
using namespace Bloom::Events;
|
||||
namespace Bloom
|
||||
{
|
||||
using namespace Bloom::Events;
|
||||
|
||||
std::set<Events::EventType> EventListener::getRegisteredEventTypes() {
|
||||
std::set<Events::EventType> EventListener::getRegisteredEventTypes() {
|
||||
return this->registeredEventTypes.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
void EventListener::registerEvent(SharedGenericEventPointer event) {
|
||||
void EventListener::registerEvent(SharedGenericEventPointer event) {
|
||||
Logger::debug("Event \"" + event->getName() + "\" (" + std::to_string(event->id)
|
||||
+ ") registered for listener " + this->name);
|
||||
auto queueLock = this->eventQueueByEventType.acquireLock();
|
||||
@@ -21,15 +22,15 @@ void EventListener::registerEvent(SharedGenericEventPointer event) {
|
||||
if (this->interruptEventNotifier != nullptr && this->interruptEventNotifier->isInitialised()) {
|
||||
this->interruptEventNotifier->notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventListener::waitAndDispatch(int msTimeout) {
|
||||
void EventListener::waitAndDispatch(int msTimeout) {
|
||||
auto queueLock = this->eventQueueByEventType.acquireLock();
|
||||
auto& eventQueueByType = this->eventQueueByEventType.getReference();
|
||||
auto registeredEventTypes = this->getRegisteredEventTypes();
|
||||
std::optional<SharedGenericEventPointer> event;
|
||||
|
||||
auto eventsFound = [®isteredEventTypes, &event, &eventQueueByType] () -> bool {
|
||||
auto eventsFound = [®isteredEventTypes, &event, &eventQueueByType]() -> bool {
|
||||
for (auto& eventQueue: eventQueueByType) {
|
||||
if (registeredEventTypes.contains(eventQueue.first) && !eventQueue.second.empty()) {
|
||||
return true;
|
||||
@@ -52,10 +53,11 @@ void EventListener::waitAndDispatch(int msTimeout) {
|
||||
queueLock.unlock();
|
||||
|
||||
this->dispatchCurrentEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void EventListener::dispatchEvent(const SharedGenericEventPointer& event) {
|
||||
void EventListener::dispatchEvent(const SharedGenericEventPointer& event) {
|
||||
Logger::debug("Dispatching event " + event->getName() + " (" + std::to_string(event->id) + ").");
|
||||
|
||||
// Dispatch the event to all registered handlers
|
||||
auto mappingLock = this->eventTypeToCallbacksMapping.acquireLock();
|
||||
auto& callbacks = this->eventTypeToCallbacksMapping.getReference().find(event->getType())->second;
|
||||
@@ -64,17 +66,17 @@ void EventListener::dispatchEvent(const SharedGenericEventPointer& event) {
|
||||
for (auto& callback : callbacks) {
|
||||
callback(*(event.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventListener::dispatchCurrentEvents() {
|
||||
void EventListener::dispatchCurrentEvents() {
|
||||
auto events = this->getEvents();
|
||||
|
||||
for (const auto& event: events) {
|
||||
dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SharedGenericEventPointer> EventListener::getEvents() {
|
||||
std::vector<SharedGenericEventPointer> EventListener::getEvents() {
|
||||
auto queueLock = this->eventQueueByEventType.acquireLock();
|
||||
auto& eventQueueByType = this->eventQueueByEventType.getReference();
|
||||
std::vector<SharedGenericEventPointer> output;
|
||||
@@ -86,14 +88,19 @@ std::vector<SharedGenericEventPointer> EventListener::getEvents() {
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(output.begin(), output.end(), [] (const SharedGenericEventPointer& a, const SharedGenericEventPointer& b) {
|
||||
std::sort(
|
||||
output.begin(),
|
||||
output.end(),
|
||||
[](const SharedGenericEventPointer& a, const SharedGenericEventPointer& b) {
|
||||
return a->id < b->id;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
void EventListener::clearAllCallbacks() {
|
||||
void EventListener::clearAllCallbacks() {
|
||||
auto lock = this->eventTypeToCallbacksMapping.acquireLock();
|
||||
this->eventTypeToCallbacksMapping.getReference().clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,36 @@
|
||||
#include "EventManager.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
|
||||
void EventManager::registerListener(std::shared_ptr<EventListener> listener) {
|
||||
namespace Bloom
|
||||
{
|
||||
void EventManager::registerListener(std::shared_ptr<EventListener> listener) {
|
||||
auto registerListenersLock = std::unique_lock(this->registerListenerMutex);
|
||||
this->registeredListeners.insert(std::pair(listener->getId(), std::move(listener)));
|
||||
}
|
||||
}
|
||||
|
||||
void EventManager::deregisterListener(size_t listenerId) {
|
||||
void EventManager::deregisterListener(size_t listenerId) {
|
||||
auto registerListenersLock = std::unique_lock(this->registerListenerMutex);
|
||||
this->registeredListeners.erase(listenerId);
|
||||
}
|
||||
}
|
||||
|
||||
void EventManager::triggerEvent(const std::shared_ptr<const Events::Event>& event) {
|
||||
void EventManager::triggerEvent(const std::shared_ptr<const Events::Event>& event) {
|
||||
auto registerListenersLock = std::unique_lock(this->registerListenerMutex);
|
||||
|
||||
for(const auto& [listenerId, listener] : this->registeredListeners) {
|
||||
for (const auto&[listenerId, listener] : this->registeredListeners) {
|
||||
if (listener->isEventTypeRegistered(event->getType())) {
|
||||
listener->registerEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool EventManager::isEventTypeListenedFor(Events::EventType eventType) {
|
||||
bool EventManager::isEventTypeListenedFor(Events::EventType eventType) {
|
||||
auto registerListenersLock = std::unique_lock(this->registerListenerMutex);
|
||||
|
||||
for(const auto& [listenerId, listener] : this->registeredListeners) {
|
||||
for (const auto&[listenerId, listener] : this->registeredListeners) {
|
||||
if (listener->isEventTypeRegistered(eventType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
|
||||
std::string Paths::applicationDirPath() {
|
||||
namespace Bloom
|
||||
{
|
||||
std::string Paths::applicationDirPath() {
|
||||
auto pathCharArray = std::array<char, PATH_MAX>();
|
||||
|
||||
if (readlink("/proc/self/exe", pathCharArray.data(), PATH_MAX) < 0) {
|
||||
@@ -17,4 +17,5 @@ std::string Paths::applicationDirPath() {
|
||||
}
|
||||
|
||||
return std::filesystem::path(std::string(pathCharArray.begin(), pathCharArray.end())).parent_path();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,11 @@
|
||||
#include "src/Application.hpp"
|
||||
#include "InsightWorker/Tasks/QueryLatestVersionNumber.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
void Insight::run() {
|
||||
void Insight::run() {
|
||||
try {
|
||||
this->startup();
|
||||
|
||||
@@ -32,9 +33,9 @@ void Insight::run() {
|
||||
}
|
||||
|
||||
this->shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void Insight::startup() {
|
||||
void Insight::startup() {
|
||||
Logger::info("Starting Insight");
|
||||
this->setThreadState(ThreadState::STARTING);
|
||||
this->eventManager.registerListener(this->eventListener);
|
||||
@@ -146,9 +147,9 @@ void Insight::startup() {
|
||||
});
|
||||
|
||||
this->mainWindow->show();
|
||||
}
|
||||
}
|
||||
|
||||
void Insight::shutdown() {
|
||||
void Insight::shutdown() {
|
||||
if (this->getThreadState() == ThreadState::STOPPED) {
|
||||
return;
|
||||
}
|
||||
@@ -163,9 +164,9 @@ void Insight::shutdown() {
|
||||
this->application.exit(0);
|
||||
|
||||
this->setThreadState(ThreadState::STOPPED);
|
||||
}
|
||||
}
|
||||
|
||||
void Insight::checkBloomVersion() {
|
||||
void Insight::checkBloomVersion() {
|
||||
auto currentVersionNumber = Application::VERSION;
|
||||
|
||||
auto* versionQueryTask = new QueryLatestVersionNumber(
|
||||
@@ -187,26 +188,27 @@ void Insight::checkBloomVersion() {
|
||||
);
|
||||
|
||||
this->insightWorker->queueTask(versionQueryTask);
|
||||
}
|
||||
}
|
||||
|
||||
void Insight::onShutdownApplicationEvent(const Events::ShutdownApplication&) {
|
||||
void Insight::onShutdownApplicationEvent(const Events::ShutdownApplication&) {
|
||||
/*
|
||||
* Once Insight shuts down, control of the main thread will be returned to Application::run(), which
|
||||
* will pickup the ShutdownApplication event and proceed with the shutdown.
|
||||
*/
|
||||
this->shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void Insight::onTargetControllerThreadStateChangedEvent(const Events::TargetControllerThreadStateChanged& event) {
|
||||
void Insight::onTargetControllerThreadStateChangedEvent(const Events::TargetControllerThreadStateChanged& event) {
|
||||
if (event.getState() == ThreadState::STOPPED) {
|
||||
// Something horrible has happened with the TargetController - Insight is useless without the TargetController
|
||||
this->shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Insight::onDebugServerThreadStateChangedEvent(const Events::DebugServerThreadStateChanged& event) {
|
||||
void Insight::onDebugServerThreadStateChangedEvent(const Events::DebugServerThreadStateChanged& event) {
|
||||
if (event.getState() == ThreadState::STOPPED) {
|
||||
// Something horrible has happened with the DebugServer
|
||||
this->shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,22 +6,23 @@
|
||||
#include "src/Helpers/Thread.hpp"
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
using Bloom::Targets::TargetState;
|
||||
using Bloom::Targets::TargetState;
|
||||
|
||||
InsightWorker::InsightWorker(EventManager& eventManager): eventManager(eventManager) {}
|
||||
InsightWorker::InsightWorker(EventManager& eventManager): eventManager(eventManager) {}
|
||||
|
||||
void InsightWorker::queueTask(InsightWorkerTask* task) {
|
||||
void InsightWorker::queueTask(InsightWorkerTask* task) {
|
||||
auto taskQueueLock = this->queuedTasks.acquireLock();
|
||||
task->moveToThread(this->thread());
|
||||
task->setParent(this);
|
||||
this->queuedTasks.getReference().push(task);
|
||||
emit this->taskQueued();
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWorker::startup() {
|
||||
void InsightWorker::startup() {
|
||||
Logger::debug("Starting InsightWorker thread");
|
||||
this->eventManager.registerListener(this->eventListener);
|
||||
|
||||
@@ -52,13 +53,13 @@ void InsightWorker::startup() {
|
||||
);
|
||||
|
||||
emit this->ready();
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWorker::requestPinStates(int variantId) {
|
||||
void InsightWorker::requestPinStates(int variantId) {
|
||||
this->targetControllerConsole.requestPinStates(variantId);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<InsightWorkerTask*> InsightWorker::getQueuedTask() {
|
||||
std::optional<InsightWorkerTask*> InsightWorker::getQueuedTask() {
|
||||
auto task = std::optional<InsightWorkerTask*>();
|
||||
|
||||
auto& queuedTasks = this->queuedTasks.getReference();
|
||||
@@ -70,29 +71,30 @@ std::optional<InsightWorkerTask*> InsightWorker::getQueuedTask() {
|
||||
}
|
||||
|
||||
return task;
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWorker::onTargetStoppedEvent(const Events::TargetExecutionStopped& event) {
|
||||
void InsightWorker::onTargetStoppedEvent(const Events::TargetExecutionStopped& event) {
|
||||
/*
|
||||
* When we report a target halt to Insight, Insight will immediately seek more data from the target (such as GPIO
|
||||
* pin states). This can be problematic for cases where the target had halted due to a conditional breakpoint.
|
||||
* When we report a target halt to Insight, Insight will immediately seek more data from the target (such as
|
||||
* GPIO pin states). This can be problematic for cases where the target had halted due to a conditional
|
||||
* breakpoint.
|
||||
*
|
||||
* For conditional breakpoints, a software breakpoint is employed to halt target execution and give the debug
|
||||
* client an opportunity to check the condition. In cases where the condition is not met, the client will
|
||||
* immediately request for execution to be resumed. It's important that Insight does not get in the way of this
|
||||
* process, as it could end up slowing things down significantly.
|
||||
*
|
||||
* For the above reason, we don't want to report any target halts to Insight, unless we can be sure that the client
|
||||
* isn't going to immediately resume execution upon checking the condition.
|
||||
* For the above reason, we don't want to report any target halts to Insight, unless we can be sure that the
|
||||
* client isn't going to immediately resume execution upon checking the condition.
|
||||
*
|
||||
* We do this by providing a time window for the TargetExecutionResumed event. If the event is triggered within
|
||||
* that time window, we won't report the target halt to Insight, thus preventing Insight from needlessly seeking
|
||||
* data from the target and slowing things down.
|
||||
* that time window, we won't report the target halt to Insight, thus preventing Insight from needlessly
|
||||
* seeking data from the target and slowing things down.
|
||||
*
|
||||
* This isn't the best approach, TBH, as it introduces a delay to Insight's response to the target halting. The
|
||||
* problem is, we cannot differentiate a conditional breakpoint with a software breakpoint, so this seems to be the
|
||||
* only way. It would be nice if the debug client gave us some form of indication of whether the breakpoint is a
|
||||
* conditional one.
|
||||
* problem is, we cannot differentiate a conditional breakpoint with a software breakpoint, so this seems to be
|
||||
* the only way. It would be nice if the debug client gave us some form of indication of whether the breakpoint
|
||||
* is a conditional one.
|
||||
*/
|
||||
auto resumedEvent = this->eventListener->waitForEvent<Events::TargetExecutionResumed>(
|
||||
std::chrono::milliseconds(650)
|
||||
@@ -102,17 +104,17 @@ void InsightWorker::onTargetStoppedEvent(const Events::TargetExecutionStopped& e
|
||||
emit this->targetStateUpdated(TargetState::STOPPED);
|
||||
emit this->targetProgramCounterUpdated(event.programCounter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWorker::onTargetResumedEvent(const Events::TargetExecutionResumed& event) {
|
||||
void InsightWorker::onTargetResumedEvent(const Events::TargetExecutionResumed& event) {
|
||||
emit this->targetStateUpdated(TargetState::RUNNING);
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWorker::onTargetRegistersWrittenEvent(const Events::RegistersWrittenToTarget& event) {
|
||||
void InsightWorker::onTargetRegistersWrittenEvent(const Events::RegistersWrittenToTarget& event) {
|
||||
emit this->targetRegistersWritten(event.registers, event.createdTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWorker::onTargetControllerStateReportedEvent(const Events::TargetControllerStateReported& event) {
|
||||
void InsightWorker::onTargetControllerStateReportedEvent(const Events::TargetControllerStateReported& event) {
|
||||
if (this->lastTargetControllerState == TargetControllerState::ACTIVE
|
||||
&& event.state == TargetControllerState::SUSPENDED
|
||||
) {
|
||||
@@ -129,12 +131,13 @@ void InsightWorker::onTargetControllerStateReportedEvent(const Events::TargetCon
|
||||
}
|
||||
}
|
||||
this->lastTargetControllerState = event.state;
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWorker::executeTasks() {
|
||||
void InsightWorker::executeTasks() {
|
||||
auto task = std::optional<InsightWorkerTask*>();
|
||||
|
||||
while ((task = this->getQueuedTask()).has_value()) {
|
||||
task.value()->execute(this->targetControllerConsole);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
|
||||
void InsightWorkerTask::execute(TargetControllerConsole& targetControllerConsole) {
|
||||
namespace Bloom
|
||||
{
|
||||
void InsightWorkerTask::execute(TargetControllerConsole& targetControllerConsole) {
|
||||
try {
|
||||
this->state = InsightWorkerTaskState::STARTED;
|
||||
emit this->started();
|
||||
@@ -17,4 +17,5 @@ void InsightWorkerTask::execute(TargetControllerConsole& targetControllerConsole
|
||||
Logger::error("InsightWorker task failed - " + std::string(exception.what()));
|
||||
emit this->failed(QString::fromStdString(exception.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
#include "src/Helpers/Paths.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
|
||||
void QueryLatestVersionNumber::run(TargetControllerConsole& targetControllerConsole) {
|
||||
namespace Bloom
|
||||
{
|
||||
void QueryLatestVersionNumber::run(TargetControllerConsole& targetControllerConsole) {
|
||||
auto* networkAccessManager = new QNetworkAccessManager(this);
|
||||
auto queryVersionEndpointUrl = QUrl(QString::fromStdString(Paths::homeDomainName() + "/latest-version"));
|
||||
queryVersionEndpointUrl.setScheme("http");
|
||||
@@ -31,4 +31,5 @@ void QueryLatestVersionNumber::run(TargetControllerConsole& targetControllerCons
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "ReadStackPointer.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
|
||||
void ReadStackPointer::run(TargetControllerConsole& targetControllerConsole) {
|
||||
namespace Bloom
|
||||
{
|
||||
void ReadStackPointer::run(TargetControllerConsole& targetControllerConsole) {
|
||||
emit this->stackPointerRead(targetControllerConsole.getStackPointer());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "ReadTargetMemory.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
|
||||
void ReadTargetMemory::run(TargetControllerConsole& targetControllerConsole) {
|
||||
namespace Bloom
|
||||
{
|
||||
void ReadTargetMemory::run(TargetControllerConsole& targetControllerConsole) {
|
||||
emit this->targetMemoryRead(
|
||||
targetControllerConsole.readMemory(
|
||||
this->memoryType,
|
||||
@@ -11,4 +11,5 @@ void ReadTargetMemory::run(TargetControllerConsole& targetControllerConsole) {
|
||||
this->excludedAddressRanges
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "ReadTargetRegisters.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
|
||||
void ReadTargetRegisters::run(TargetControllerConsole& targetControllerConsole) {
|
||||
namespace Bloom
|
||||
{
|
||||
void ReadTargetRegisters::run(TargetControllerConsole& targetControllerConsole) {
|
||||
emit this->targetRegistersRead(targetControllerConsole.readRegisters(this->descriptors));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "RefreshTargetPinStates.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
|
||||
void RefreshTargetPinStates::run(TargetControllerConsole& targetControllerConsole) {
|
||||
namespace Bloom
|
||||
{
|
||||
void RefreshTargetPinStates::run(TargetControllerConsole& targetControllerConsole) {
|
||||
emit this->targetPinStatesRetrieved(targetControllerConsole.getPinStates(this->variantId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "SetTargetPinState.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
|
||||
void SetTargetPinState::run(TargetControllerConsole& targetControllerConsole) {
|
||||
namespace Bloom
|
||||
{
|
||||
void SetTargetPinState::run(TargetControllerConsole& targetControllerConsole) {
|
||||
targetControllerConsole.setPinState(this->pinDescriptor, this->pinState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "WriteTargetRegister.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
|
||||
void WriteTargetRegister::run(TargetControllerConsole& targetControllerConsole) {
|
||||
namespace Bloom
|
||||
{
|
||||
void WriteTargetRegister::run(TargetControllerConsole& targetControllerConsole) {
|
||||
targetControllerConsole.writeRegisters({this->targetRegister});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
#include "src/Helpers/Paths.hpp"
|
||||
#include "src/Application.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
using namespace Exceptions;
|
||||
namespace Bloom
|
||||
{
|
||||
using namespace Exceptions;
|
||||
|
||||
AboutWindow::AboutWindow(QWidget* parent): QObject(parent) {
|
||||
AboutWindow::AboutWindow(QWidget* parent): QObject(parent) {
|
||||
auto aboutWindowUiFile = QFile(QString::fromStdString(
|
||||
Paths::compiledResourcesPath()
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/UiFiles/AboutWindow.ui"
|
||||
@@ -39,4 +40,5 @@ AboutWindow::AboutWindow(QWidget* parent): QObject(parent) {
|
||||
if (versionLabel != nullptr) {
|
||||
versionLabel->setText("Bloom v" + QString::fromStdString(Application::VERSION.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
#include "BloomProxyStyle.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
|
||||
int BloomProxyStyle::styleHint(
|
||||
namespace Bloom
|
||||
{
|
||||
int BloomProxyStyle::styleHint(
|
||||
StyleHint hint,
|
||||
const QStyleOption* option,
|
||||
const QWidget* widget,
|
||||
QStyleHintReturn* returnData
|
||||
) const {
|
||||
) const {
|
||||
if (hint == QStyle::SH_ComboBox_Popup) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return QProxyStyle::styleHint(hint, option, widget, returnData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,31 +15,32 @@
|
||||
#include "src/Helpers/Paths.hpp"
|
||||
#include "src/Targets/TargetDescriptor.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
using namespace Bloom::Exceptions;
|
||||
using namespace Bloom::Widgets;
|
||||
namespace Bloom
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
using Bloom::Targets::TargetDescriptor;
|
||||
using Bloom::Targets::TargetState;
|
||||
using Bloom::Targets::TargetPinState;
|
||||
using Bloom::Targets::TargetVariant;
|
||||
using Bloom::Targets::TargetPackage;
|
||||
using Bloom::Targets::TargetPinDescriptor;
|
||||
using Bloom::Targets::TargetMemoryType;
|
||||
using Bloom::Targets::TargetDescriptor;
|
||||
using Bloom::Targets::TargetState;
|
||||
using Bloom::Targets::TargetPinState;
|
||||
using Bloom::Targets::TargetVariant;
|
||||
using Bloom::Targets::TargetPackage;
|
||||
using Bloom::Targets::TargetPinDescriptor;
|
||||
using Bloom::Targets::TargetMemoryType;
|
||||
|
||||
InsightWindow::InsightWindow(
|
||||
InsightWindow::InsightWindow(
|
||||
InsightWorker& insightWorker,
|
||||
const EnvironmentConfig& environmentConfig,
|
||||
const InsightConfig& insightConfig,
|
||||
InsightProjectSettings& insightProjectSettings
|
||||
):
|
||||
QMainWindow(nullptr),
|
||||
insightWorker(insightWorker),
|
||||
environmentConfig(environmentConfig),
|
||||
targetConfig(environmentConfig.targetConfig),
|
||||
insightConfig(insightConfig),
|
||||
insightProjectSettings(insightProjectSettings)
|
||||
{
|
||||
)
|
||||
: QMainWindow(nullptr)
|
||||
, insightWorker(insightWorker)
|
||||
, environmentConfig(environmentConfig)
|
||||
, targetConfig(environmentConfig.targetConfig)
|
||||
, insightConfig(insightConfig)
|
||||
, insightProjectSettings(insightProjectSettings)
|
||||
{
|
||||
this->setObjectName("main-window");
|
||||
this->setWindowTitle("Bloom Insight");
|
||||
|
||||
@@ -212,34 +213,34 @@ InsightWindow::InsightWindow(
|
||||
this,
|
||||
&InsightWindow::onTargetProgramCounterUpdate
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::init(TargetDescriptor targetDescriptor) {
|
||||
void InsightWindow::init(TargetDescriptor targetDescriptor) {
|
||||
this->targetDescriptor = std::move(targetDescriptor);
|
||||
this->activate();
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::resizeEvent(QResizeEvent* event) {
|
||||
void InsightWindow::resizeEvent(QResizeEvent* event) {
|
||||
const auto windowSize = this->size();
|
||||
|
||||
this->windowContainer->setFixedSize(windowSize);
|
||||
this->layoutContainer->setFixedSize(windowSize);
|
||||
|
||||
this->adjustPanels();
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::showEvent(QShowEvent* event) {
|
||||
void InsightWindow::showEvent(QShowEvent* event) {
|
||||
this->adjustPanels();
|
||||
this->adjustMinimumSize();
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::closeEvent(QCloseEvent* event) {
|
||||
void InsightWindow::closeEvent(QCloseEvent* event) {
|
||||
this->insightProjectSettings.mainWindowSize = this->size();
|
||||
|
||||
return QMainWindow::closeEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
bool InsightWindow::isVariantSupported(const TargetVariant& variant) {
|
||||
bool InsightWindow::isVariantSupported(const TargetVariant& variant) {
|
||||
const auto pinCount = variant.pinDescriptorsByNumber.size();
|
||||
|
||||
/*
|
||||
@@ -273,18 +274,18 @@ bool InsightWindow::isVariantSupported(const TargetVariant& variant) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::setUiDisabled(bool disable) {
|
||||
void InsightWindow::setUiDisabled(bool disable) {
|
||||
this->uiDisabled = disable;
|
||||
|
||||
if (this->refreshIoInspectionButton != nullptr) {
|
||||
this->refreshIoInspectionButton->setDisabled(disable);
|
||||
this->refreshIoInspectionButton->repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::activate() {
|
||||
void InsightWindow::activate() {
|
||||
this->targetNameLabel->setText(QString::fromStdString(this->targetDescriptor.name));
|
||||
this->targetIdLabel->setText("0x" + QString::fromStdString(this->targetDescriptor.id).remove("0x").toUpper());
|
||||
|
||||
@@ -315,9 +316,9 @@ void InsightWindow::activate() {
|
||||
|
||||
this->setUiDisabled(this->targetState != TargetState::STOPPED);
|
||||
this->activated = true;
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::populateVariantMenu() {
|
||||
void InsightWindow::populateVariantMenu() {
|
||||
/*
|
||||
* We don't want to present the user with duplicate target variants.
|
||||
*
|
||||
@@ -379,9 +380,9 @@ void InsightWindow::populateVariantMenu() {
|
||||
this->variantMenu->addAction(variantAction);
|
||||
processedVariants.push_back(targetVariant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::selectDefaultVariant() {
|
||||
void InsightWindow::selectDefaultVariant() {
|
||||
if (this->supportedVariantsByName.empty()) {
|
||||
return;
|
||||
}
|
||||
@@ -414,9 +415,9 @@ void InsightWindow::selectDefaultVariant() {
|
||||
*/
|
||||
this->selectVariant(&(this->supportedVariantsByName.begin()->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::selectVariant(const TargetVariant* variant) {
|
||||
void InsightWindow::selectVariant(const TargetVariant* variant) {
|
||||
if (!this->isVariantSupported(*variant)) {
|
||||
Logger::error("Attempted to select unsupported target variant.");
|
||||
return;
|
||||
@@ -471,9 +472,9 @@ void InsightWindow::selectVariant(const TargetVariant* variant) {
|
||||
this->adjustMinimumSize();
|
||||
this->targetPackageWidget->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::createPanes() {
|
||||
void InsightWindow::createPanes() {
|
||||
// Target registers pane
|
||||
auto* leftPanelLayout = this->leftPanel->layout();
|
||||
this->targetRegistersSidePane = new TargetRegistersPaneWidget(
|
||||
@@ -529,9 +530,9 @@ void InsightWindow::createPanes() {
|
||||
this->eepromInspectionButton->setChecked(false);
|
||||
this->eepromInspectionButton->setDisabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::destroyPanes() {
|
||||
void InsightWindow::destroyPanes() {
|
||||
if (this->targetRegistersSidePane != nullptr) {
|
||||
this->targetRegistersSidePane->deactivate();
|
||||
this->targetRegistersSidePane->deleteLater();
|
||||
@@ -541,8 +542,8 @@ void InsightWindow::destroyPanes() {
|
||||
}
|
||||
|
||||
/*
|
||||
* Before we destroy the memory inspection pane widgets, we take a copy of their current settings (memory regions,
|
||||
* hex viewer settings, etc), in order to persist them through debug sessions.
|
||||
* Before we destroy the memory inspection pane widgets, we take a copy of their current settings (memory
|
||||
* regions, hex viewer settings, etc), in order to persist them through debug sessions.
|
||||
*/
|
||||
if (this->ramInspectionPane != nullptr) {
|
||||
this->ramInspectionPane->deactivate();
|
||||
@@ -563,9 +564,9 @@ void InsightWindow::destroyPanes() {
|
||||
this->eepromInspectionButton->setChecked(false);
|
||||
this->eepromInspectionButton->setDisabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::deactivate() {
|
||||
void InsightWindow::deactivate() {
|
||||
if (this->selectedVariant != nullptr) {
|
||||
this->previouslySelectedVariant = *(this->selectedVariant);
|
||||
this->selectedVariant = nullptr;
|
||||
@@ -596,9 +597,9 @@ void InsightWindow::deactivate() {
|
||||
|
||||
this->setUiDisabled(true);
|
||||
this->activated = false;
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::adjustPanels() {
|
||||
void InsightWindow::adjustPanels() {
|
||||
const auto targetPackageWidgetSize = (this->targetPackageWidget != nullptr)
|
||||
? this->targetPackageWidget->size() : QSize();
|
||||
const auto containerSize = this->container->size();
|
||||
@@ -624,9 +625,9 @@ void InsightWindow::adjustPanels() {
|
||||
(containerSize.height() / 2) - this->bottomMenuBar->height()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::adjustMinimumSize() {
|
||||
void InsightWindow::adjustMinimumSize() {
|
||||
auto minSize = QSize(800, 500);
|
||||
|
||||
if (this->targetPackageWidget != nullptr) {
|
||||
@@ -639,22 +640,22 @@ void InsightWindow::adjustMinimumSize() {
|
||||
}
|
||||
|
||||
this->setMinimumSize(minSize);
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::onTargetControllerSuspended() {
|
||||
void InsightWindow::onTargetControllerSuspended() {
|
||||
if (this->activated) {
|
||||
this->deactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::onTargetControllerResumed(const TargetDescriptor& targetDescriptor) {
|
||||
void InsightWindow::onTargetControllerResumed(const TargetDescriptor& targetDescriptor) {
|
||||
if (!this->activated) {
|
||||
this->targetDescriptor = targetDescriptor;
|
||||
this->activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::onTargetStateUpdate(TargetState newState) {
|
||||
void InsightWindow::onTargetStateUpdate(TargetState newState) {
|
||||
this->targetState = newState;
|
||||
|
||||
if (newState == TargetState::RUNNING) {
|
||||
@@ -669,15 +670,15 @@ void InsightWindow::onTargetStateUpdate(TargetState newState) {
|
||||
} else {
|
||||
this->targetStatusLabel->setText("Unknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::onTargetProgramCounterUpdate(quint32 programCounter) {
|
||||
void InsightWindow::onTargetProgramCounterUpdate(quint32 programCounter) {
|
||||
this->programCounterValueLabel->setText(
|
||||
"0x" + QString::number(programCounter, 16).toUpper() + " (" + QString::number(programCounter) + ")"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::refresh() {
|
||||
void InsightWindow::refresh() {
|
||||
if (this->targetState != TargetState::STOPPED || this->selectedVariant == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -705,9 +706,9 @@ void InsightWindow::refresh() {
|
||||
this->setUiDisabled(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::openReportIssuesUrl() {
|
||||
void InsightWindow::openReportIssuesUrl() {
|
||||
auto url = QUrl(QString::fromStdString(Paths::homeDomainName() + "/report-issue"));
|
||||
/*
|
||||
* The https://bloom.oscillate.io/report-issue URL just redirects to the Bloom GitHub issue page.
|
||||
@@ -730,28 +731,30 @@ void InsightWindow::openReportIssuesUrl() {
|
||||
url.setQuery(urlQuery);
|
||||
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::openGettingStartedUrl() {
|
||||
QDesktopServices::openUrl(QUrl(QString::fromStdString(Paths::homeDomainName() + "/docs/getting-started")));
|
||||
}
|
||||
void InsightWindow::openGettingStartedUrl() {
|
||||
QDesktopServices::openUrl(
|
||||
QUrl(QString::fromStdString(Paths::homeDomainName() + "/docs/getting-started"))
|
||||
);
|
||||
}
|
||||
|
||||
void InsightWindow::openAboutWindow() {
|
||||
void InsightWindow::openAboutWindow() {
|
||||
if (this->aboutWindowWidget == nullptr) {
|
||||
this->aboutWindowWidget = new AboutWindow(this);
|
||||
}
|
||||
|
||||
this->aboutWindowWidget->show();
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::toggleTargetRegistersPane() {
|
||||
void InsightWindow::toggleTargetRegistersPane() {
|
||||
if (this->targetRegistersSidePane->activated) {
|
||||
this->targetRegistersSidePane->deactivate();
|
||||
this->targetRegistersButton->setChecked(false);
|
||||
|
||||
/*
|
||||
* Given that the target registers side pane is currently the only pane in the left panel, the panel will be
|
||||
* empty so no need to leave it visible.
|
||||
* Given that the target registers side pane is currently the only pane in the left panel, the panel
|
||||
* will be empty so no need to leave it visible.
|
||||
*/
|
||||
this->leftPanel->setVisible(false);
|
||||
|
||||
@@ -760,9 +763,9 @@ void InsightWindow::toggleTargetRegistersPane() {
|
||||
this->targetRegistersButton->setChecked(true);
|
||||
this->leftPanel->setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::toggleRamInspectionPane() {
|
||||
void InsightWindow::toggleRamInspectionPane() {
|
||||
if (this->ramInspectionPane->activated) {
|
||||
this->ramInspectionPane->deactivate();
|
||||
this->bottomPanel->hide();
|
||||
@@ -779,9 +782,9 @@ void InsightWindow::toggleRamInspectionPane() {
|
||||
}
|
||||
|
||||
this->adjustMinimumSize();
|
||||
}
|
||||
}
|
||||
|
||||
void InsightWindow::toggleEepromInspectionPane() {
|
||||
void InsightWindow::toggleEepromInspectionPane() {
|
||||
if (this->eepromInspectionPane->activated) {
|
||||
this->eepromInspectionPane->deactivate();
|
||||
this->bottomPanel->hide();
|
||||
@@ -798,4 +801,5 @@ void InsightWindow::toggleEepromInspectionPane() {
|
||||
}
|
||||
|
||||
this->adjustMinimumSize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
#include "Widgets/ExpandingHeightScrollAreaWidget.hpp"
|
||||
#include "Widgets/TargetWidgets/TargetPackageWidgetContainer.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
using namespace Bloom::Widgets;
|
||||
namespace Bloom
|
||||
{
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
UiLoader::UiLoader(QObject* parent): QUiLoader(parent) {
|
||||
UiLoader::UiLoader(QObject* parent): QUiLoader(parent) {
|
||||
this->customWidgetConstructorsByWidgetName = decltype(this->customWidgetConstructorsByWidgetName) {
|
||||
{
|
||||
"PanelWidget",
|
||||
@@ -90,13 +91,14 @@ UiLoader::UiLoader(QObject* parent): QUiLoader(parent) {
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
QWidget* UiLoader::createWidget(const QString& className, QWidget* parent, const QString& name) {
|
||||
QWidget* UiLoader::createWidget(const QString& className, QWidget* parent, const QString& name) {
|
||||
if (this->customWidgetConstructorsByWidgetName.contains(className)) {
|
||||
// This is a custom widget - call the mapped constructor
|
||||
return this->customWidgetConstructorsByWidgetName.at(className)(parent, name);
|
||||
}
|
||||
|
||||
return QUiLoader::createWidget(className, parent, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "ClickableWidget.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
void ClickableWidget::mouseReleaseEvent(QMouseEvent* event) {
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
void ClickableWidget::mouseReleaseEvent(QMouseEvent* event) {
|
||||
if (event->button() == Qt::MouseButton::LeftButton) {
|
||||
emit this->clicked();
|
||||
|
||||
@@ -11,12 +11,13 @@ void ClickableWidget::mouseReleaseEvent(QMouseEvent* event) {
|
||||
}
|
||||
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void ClickableWidget::mouseDoubleClickEvent(QMouseEvent* event) {
|
||||
void ClickableWidget::mouseDoubleClickEvent(QMouseEvent* event) {
|
||||
if (event->button() == Qt::MouseButton::LeftButton) {
|
||||
emit this->doubleClicked();
|
||||
}
|
||||
|
||||
QWidget::mouseDoubleClickEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
#include "src/Helpers/Paths.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
using Bloom::Exceptions::Exception;
|
||||
|
||||
using Bloom::Exceptions::Exception;
|
||||
|
||||
ErrorDialogue::ErrorDialogue(
|
||||
ErrorDialogue::ErrorDialogue(
|
||||
const QString& windowTitle,
|
||||
const QString& errorMessage,
|
||||
QWidget* parent
|
||||
): QDialog(parent) {
|
||||
): QDialog(parent) {
|
||||
this->setObjectName("error-dialogue");
|
||||
this->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
this->setWindowTitle(windowTitle);
|
||||
@@ -45,7 +45,9 @@ ErrorDialogue::ErrorDialogue(
|
||||
auto uiLoader = UiLoader(this);
|
||||
this->container = uiLoader.load(&dialogueUiFile, this);
|
||||
|
||||
this->errorMessageDescriptionLabel = this->container->findChild<QLabel*>("error-message-description-label");
|
||||
this->errorMessageDescriptionLabel = this->container->findChild<QLabel*>(
|
||||
"error-message-description-label"
|
||||
);
|
||||
this->okButton = this->container->findChild<QPushButton*>("ok-btn");
|
||||
|
||||
this->container->setContentsMargins(15, 10, 15, 15);
|
||||
@@ -53,12 +55,16 @@ ErrorDialogue::ErrorDialogue(
|
||||
this->errorMessageDescriptionLabel->setText(errorMessage);
|
||||
|
||||
QObject::connect(this->okButton, &QPushButton::clicked, this, &QDialog::close);
|
||||
}
|
||||
}
|
||||
|
||||
void ErrorDialogue::showEvent(QShowEvent* event) {
|
||||
void ErrorDialogue::showEvent(QShowEvent* event) {
|
||||
const auto containerSize = this->container->sizeHint();
|
||||
const auto windowSize = QSize(std::max(containerSize.width(), 500), std::max(containerSize.height(), 100));
|
||||
const auto windowSize = QSize(
|
||||
std::max(containerSize.width(), 500),
|
||||
std::max(containerSize.height(), 100)
|
||||
);
|
||||
|
||||
this->setFixedSize(windowSize);
|
||||
this->container->setFixedSize(windowSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#include "LabeledSeparator.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
LabeledSeparator::LabeledSeparator(QString title, QWidget* parent): title(std::move(title)), QWidget(parent) {
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
LabeledSeparator::LabeledSeparator(QString title, QWidget* parent): title(std::move(title)), QWidget(parent) {
|
||||
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
||||
this->setFixedHeight(LabeledSeparator::DEFAULT_HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
void LabeledSeparator::paintEvent(QPaintEvent* event) {
|
||||
void LabeledSeparator::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter(this);
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
}
|
||||
|
||||
void LabeledSeparator::drawWidget(QPainter& painter) {
|
||||
void LabeledSeparator::drawWidget(QPainter& painter) {
|
||||
const auto fontMetrics = painter.fontMetrics();
|
||||
const auto titleSize = fontMetrics.size(Qt::TextFlag::TextSingleLine, this->title);
|
||||
const auto titleRect = QRect(
|
||||
@@ -32,4 +32,5 @@ void LabeledSeparator::drawWidget(QPainter& painter) {
|
||||
|
||||
painter.setPen(this->lineColor);
|
||||
painter.drawLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
#include <QLayout>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
PanelWidget::PanelWidget(QWidget* parent): QFrame(parent) {
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
PanelWidget::PanelWidget(QWidget* parent): QFrame(parent) {
|
||||
this->setMouseTracking(false);
|
||||
this->setAttribute(Qt::WA_Hover, true);
|
||||
}
|
||||
}
|
||||
|
||||
void PanelWidget::setMinimumResize(int minimumResize) {
|
||||
void PanelWidget::setMinimumResize(int minimumResize) {
|
||||
this->minimumResize = minimumResize;
|
||||
|
||||
const auto currentSize = this->size();
|
||||
@@ -20,9 +20,9 @@ void PanelWidget::setMinimumResize(int minimumResize) {
|
||||
} else if (this->panelType == PanelWidgetType::BOTTOM && currentSize.height() < this->minimumResize) {
|
||||
this->setFixedHeight(this->minimumResize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PanelWidget::setMaximumResize(int maximumResize) {
|
||||
void PanelWidget::setMaximumResize(int maximumResize) {
|
||||
this->maximumResize = maximumResize;
|
||||
|
||||
const auto currentSize = this->size();
|
||||
@@ -33,9 +33,9 @@ void PanelWidget::setMaximumResize(int maximumResize) {
|
||||
} else if (this->panelType == PanelWidgetType::BOTTOM && currentSize.height() > this->maximumResize) {
|
||||
this->setFixedHeight(this->maximumResize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PanelWidget::setPanelType(PanelWidgetType panelType) {
|
||||
void PanelWidget::setPanelType(PanelWidgetType panelType) {
|
||||
this->panelType = panelType;
|
||||
|
||||
if (this->panelType == PanelWidgetType::LEFT) {
|
||||
@@ -46,9 +46,9 @@ void PanelWidget::setPanelType(PanelWidgetType panelType) {
|
||||
this->resizeCursor = Qt::SplitVCursor;
|
||||
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PanelWidget::event(QEvent* event) {
|
||||
bool PanelWidget::event(QEvent* event) {
|
||||
if (event->type() == QEvent::Type::HoverMove) {
|
||||
auto hoverEvent = static_cast<QHoverEvent*>(event);
|
||||
if (this->resizingActive || this->isPositionWithinHandleArea(hoverEvent->position().toPoint())) {
|
||||
@@ -60,9 +60,9 @@ bool PanelWidget::event(QEvent* event) {
|
||||
}
|
||||
|
||||
return QFrame::event(event);
|
||||
}
|
||||
}
|
||||
|
||||
void PanelWidget::mousePressEvent(QMouseEvent* event) {
|
||||
void PanelWidget::mousePressEvent(QMouseEvent* event) {
|
||||
const auto position = event->pos();
|
||||
|
||||
if (event->buttons() & Qt::LeftButton && this->isPositionWithinHandleArea(position)) {
|
||||
@@ -79,17 +79,17 @@ void PanelWidget::mousePressEvent(QMouseEvent* event) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PanelWidget::mouseReleaseEvent(QMouseEvent* event) {
|
||||
void PanelWidget::mouseReleaseEvent(QMouseEvent* event) {
|
||||
if (this->resizingActive) {
|
||||
this->resizingActive = false;
|
||||
this->resizingOffset = 0;
|
||||
this->setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PanelWidget::mouseMoveEvent(QMouseEvent* event) {
|
||||
void PanelWidget::mouseMoveEvent(QMouseEvent* event) {
|
||||
if (this->resizingActive) {
|
||||
const auto position = event->pos();
|
||||
|
||||
@@ -110,9 +110,9 @@ void PanelWidget::mouseMoveEvent(QMouseEvent* event) {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<QPoint, QPoint> PanelWidget::getHandleArea() const {
|
||||
std::pair<QPoint, QPoint> PanelWidget::getHandleArea() const {
|
||||
const auto currentSize = this->size();
|
||||
|
||||
if (this->panelType == PanelWidgetType::LEFT) {
|
||||
@@ -127,13 +127,14 @@ std::pair<QPoint, QPoint> PanelWidget::getHandleArea() const {
|
||||
QPoint(currentSize.width(), this->handleSize)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PanelWidget::isPositionWithinHandleArea(const QPoint& position) const {
|
||||
bool PanelWidget::isPositionWithinHandleArea(const QPoint& position) const {
|
||||
const auto handleArea = this->getHandleArea();
|
||||
|
||||
return (
|
||||
position.x() >= handleArea.first.x() && position.x() <= handleArea.second.x()
|
||||
&& position.y() >= handleArea.first.y() && position.y() <= handleArea.second.y()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
void RotatableLabel::paintEvent(QPaintEvent* event) {
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
void RotatableLabel::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter(this);
|
||||
static auto containerSize = this->getContainerSize();
|
||||
static auto textSize = QLabel::minimumSizeHint();
|
||||
@@ -22,9 +22,9 @@ void RotatableLabel::paintEvent(QPaintEvent* event) {
|
||||
);
|
||||
|
||||
painter.restore();
|
||||
}
|
||||
}
|
||||
|
||||
QSize RotatableLabel::getContainerSize() const {
|
||||
QSize RotatableLabel::getContainerSize() const {
|
||||
auto size = QSize();
|
||||
auto textSize = QLabel::sizeHint();
|
||||
|
||||
@@ -58,4 +58,5 @@ QSize RotatableLabel::getContainerSize() const {
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
SvgToolButton::SvgToolButton(QWidget* parent): QToolButton(parent) {
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
SvgToolButton::SvgToolButton(QWidget* parent): QToolButton(parent) {
|
||||
this->setButtonWidth(10);
|
||||
this->setButtonHeight(10);
|
||||
}
|
||||
}
|
||||
|
||||
void SvgToolButton::childEvent(QChildEvent* childEvent) {
|
||||
void SvgToolButton::childEvent(QChildEvent* childEvent) {
|
||||
if ((childEvent->added() || childEvent->polished()) && childEvent->child()->isWidgetType()) {
|
||||
/*
|
||||
* If a menu widget has been added as a child to this SvgToolButton, associate the menu with the button
|
||||
@@ -20,4 +20,5 @@ void SvgToolButton::childEvent(QChildEvent* childEvent) {
|
||||
this->setMenu(menuWidget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
#include <QPainter>
|
||||
#include <cmath>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
SvgWidget::SvgWidget(QWidget* parent): QFrame(parent) {
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
SvgWidget::SvgWidget(QWidget* parent): QFrame(parent) {
|
||||
this->renderer.setAspectRatioMode(Qt::AspectRatioMode::KeepAspectRatioByExpanding);
|
||||
}
|
||||
}
|
||||
|
||||
void SvgWidget::startSpin() {
|
||||
void SvgWidget::startSpin() {
|
||||
if (this->spinningAnimation == nullptr) {
|
||||
this->spinningAnimation = new QPropertyAnimation(this, "angle", this);
|
||||
this->spinningAnimation->setDuration(2000);
|
||||
@@ -22,16 +22,16 @@ void SvgWidget::startSpin() {
|
||||
}
|
||||
|
||||
this->spinningAnimation->start();
|
||||
}
|
||||
}
|
||||
|
||||
void SvgWidget::stopSpin() {
|
||||
void SvgWidget::stopSpin() {
|
||||
if (this->spinningAnimation != nullptr) {
|
||||
this->spinningAnimation->stop();
|
||||
this->setAngle(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SvgWidget::paintEvent(QPaintEvent* paintEvent) {
|
||||
void SvgWidget::paintEvent(QPaintEvent* paintEvent) {
|
||||
auto painter = QPainter(this);
|
||||
auto svgSize = this->renderer.defaultSize();
|
||||
auto margins = this->contentsMargins();
|
||||
@@ -52,14 +52,18 @@ void SvgWidget::paintEvent(QPaintEvent* paintEvent) {
|
||||
}
|
||||
|
||||
this->renderer.render(&painter, QRectF(
|
||||
std::ceil(static_cast<float>(containerSize.width() - svgSize.width()) / 2 + static_cast<float>(margins.left())),
|
||||
std::ceil(static_cast<float>(containerSize.height() - svgSize.height()) / 2 + static_cast<float>(margins.top())),
|
||||
std::ceil(
|
||||
static_cast<float>(containerSize.width() - svgSize.width()) / 2 + static_cast<float>(margins.left())
|
||||
),
|
||||
std::ceil(
|
||||
static_cast<float>(containerSize.height() - svgSize.height()) / 2 + static_cast<float>(margins.top())
|
||||
),
|
||||
svgSize.width(),
|
||||
svgSize.height()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void SvgWidget::changeEvent(QEvent* event) {
|
||||
void SvgWidget::changeEvent(QEvent* event) {
|
||||
if (event->type() == QEvent::EnabledChange && !this->disabledSvgFilePath.isEmpty()) {
|
||||
if (!this->isEnabled()) {
|
||||
this->renderer.load(this->disabledSvgFilePath);
|
||||
@@ -70,4 +74,5 @@ void SvgWidget::changeEvent(QEvent* event) {
|
||||
|
||||
this->repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
|
||||
#include "ByteItem.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
AnnotationItem::AnnotationItem(
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
AnnotationItem::AnnotationItem(
|
||||
std::uint32_t startAddress,
|
||||
std::size_t size,
|
||||
QString labelText,
|
||||
AnnotationItemPosition position
|
||||
):
|
||||
):
|
||||
QGraphicsItem(nullptr),
|
||||
startAddress(startAddress),
|
||||
size(size),
|
||||
@@ -20,30 +20,30 @@ AnnotationItem::AnnotationItem(
|
||||
position(position),
|
||||
width(static_cast<int>((ByteItem::WIDTH + ByteItem::RIGHT_MARGIN) * size - ByteItem::RIGHT_MARGIN)),
|
||||
height(position == AnnotationItemPosition::TOP ? AnnotationItem::TOP_HEIGHT : AnnotationItem::BOTTOM_HEIGHT
|
||||
) {
|
||||
) {
|
||||
this->setAcceptHoverEvents(true);
|
||||
this->setToolTip(this->labelText);
|
||||
}
|
||||
}
|
||||
|
||||
AnnotationItem::AnnotationItem(
|
||||
AnnotationItem::AnnotationItem(
|
||||
const Targets::TargetMemoryAddressRange& addressRange,
|
||||
const QString& labelText,
|
||||
AnnotationItemPosition position
|
||||
): AnnotationItem(
|
||||
): AnnotationItem(
|
||||
addressRange.startAddress,
|
||||
addressRange.endAddress - addressRange.startAddress + 1,
|
||||
labelText,
|
||||
position
|
||||
) {}
|
||||
) {}
|
||||
|
||||
AnnotationItem::AnnotationItem(const FocusedMemoryRegion& focusedMemoryRegion, AnnotationItemPosition position)
|
||||
: AnnotationItem(
|
||||
AnnotationItem::AnnotationItem(const FocusedMemoryRegion& focusedMemoryRegion, AnnotationItemPosition position)
|
||||
: AnnotationItem(
|
||||
focusedMemoryRegion.addressRange,
|
||||
focusedMemoryRegion.name,
|
||||
position
|
||||
) {}
|
||||
) {}
|
||||
|
||||
void AnnotationItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
void AnnotationItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
auto lineColor = this->getLineColor();
|
||||
auto labelFontColor = this->getLabelFontColor();
|
||||
|
||||
@@ -60,11 +60,16 @@ void AnnotationItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* op
|
||||
auto labelSize = fontMetrics.size(Qt::TextSingleLine, this->labelText);
|
||||
if (labelSize.width() > this->width) {
|
||||
labelSize.setWidth(this->width);
|
||||
this->labelText = fontMetrics.elidedText(this->labelText, Qt::TextElideMode::ElideRight, this->width);
|
||||
this->labelText = fontMetrics.elidedText(
|
||||
this->labelText,
|
||||
Qt::TextElideMode::ElideRight,
|
||||
this->width
|
||||
);
|
||||
}
|
||||
|
||||
constexpr auto verticalLineLength = 5;
|
||||
const auto verticalLineYStart = this->position == AnnotationItemPosition::BOTTOM ? 0 : AnnotationItem::TOP_HEIGHT;
|
||||
const auto verticalLineYStart = this->position == AnnotationItemPosition::BOTTOM ? 0
|
||||
: AnnotationItem::TOP_HEIGHT;
|
||||
const auto verticalLineYEnd = this->position == AnnotationItemPosition::BOTTOM ?
|
||||
verticalLineLength : AnnotationItem::TOP_HEIGHT - verticalLineLength;
|
||||
|
||||
@@ -109,4 +114,5 @@ void AnnotationItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* op
|
||||
|
||||
painter->setPen(labelFontColor);
|
||||
painter->drawText(labelRect, Qt::AlignCenter, this->labelText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "ByteAddressContainer.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
void ByteAddressContainer::adjustAddressLabels(
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
void ByteAddressContainer::adjustAddressLabels(
|
||||
const std::map<std::size_t, std::vector<ByteItem*>>& byteItemsByRowIndex
|
||||
) {
|
||||
) {
|
||||
static const auto margins = QMargins(0, 10, 0, 0);
|
||||
|
||||
const auto newRowCount = byteItemsByRowIndex.size();
|
||||
@@ -46,9 +46,9 @@ void ByteAddressContainer::adjustAddressLabels(
|
||||
}
|
||||
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void ByteAddressContainer::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
void ByteAddressContainer::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
static const auto backgroundColor = QColor(0x35, 0x36, 0x33);
|
||||
static const auto borderColor = QColor(0x41, 0x42, 0x3F);
|
||||
|
||||
@@ -68,4 +68,5 @@ void ByteAddressContainer::paint(QPainter* painter, const QStyleOptionGraphicsIt
|
||||
ByteAddressContainer::WIDTH - 1,
|
||||
static_cast<int>(this->boundingRect().height())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
#include "ByteAddressItem.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QStyle>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
void ByteAddressItem::setAddressHex(const QString& addressHex) {
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
void ByteAddressItem::setAddressHex(const QString& addressHex) {
|
||||
this->setCacheMode(
|
||||
QGraphicsItem::CacheMode::ItemCoordinateCache,
|
||||
QSize(ByteAddressItem::WIDTH, ByteAddressItem::HEIGHT)
|
||||
);
|
||||
this->addressHex = addressHex;
|
||||
}
|
||||
}
|
||||
|
||||
void ByteAddressItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
painter->setRenderHints(QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform, true);
|
||||
void ByteAddressItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
painter->setRenderHints(
|
||||
QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform,
|
||||
true
|
||||
);
|
||||
|
||||
static const auto widgetRect = this->boundingRect();
|
||||
static auto fontColor = QColor(0x8F, 0x91, 0x92);
|
||||
@@ -25,4 +27,5 @@ void ByteAddressItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* o
|
||||
painter->setFont(font);
|
||||
painter->setPen(fontColor);
|
||||
painter->drawText(widgetRect, Qt::AlignCenter, this->addressHex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#include "ByteItem.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QStyle>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
ByteItem::ByteItem(
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
ByteItem::ByteItem(
|
||||
std::size_t byteIndex,
|
||||
std::uint32_t address,
|
||||
std::optional<std::uint32_t>& currentStackPointer,
|
||||
@@ -13,29 +12,35 @@ ByteItem::ByteItem(
|
||||
std::optional<AnnotationItem*>& hoveredAnnotationItem,
|
||||
std::set<std::uint32_t>& highlightedAddresses,
|
||||
const HexViewerWidgetSettings& settings
|
||||
):
|
||||
QGraphicsItem(nullptr),
|
||||
byteIndex(byteIndex),
|
||||
address(address),
|
||||
currentStackPointer(currentStackPointer),
|
||||
hoveredByteItem(hoveredByteItem),
|
||||
hoveredAnnotationItem(hoveredAnnotationItem),
|
||||
highlightedAddresses(highlightedAddresses),
|
||||
settings(settings)
|
||||
{
|
||||
)
|
||||
: QGraphicsItem(nullptr)
|
||||
, byteIndex(byteIndex)
|
||||
, address(address)
|
||||
, currentStackPointer(currentStackPointer)
|
||||
, hoveredByteItem(hoveredByteItem)
|
||||
, hoveredAnnotationItem(hoveredAnnotationItem)
|
||||
, highlightedAddresses(highlightedAddresses)
|
||||
, settings(settings)
|
||||
{
|
||||
this->setCacheMode(
|
||||
QGraphicsItem::CacheMode::ItemCoordinateCache,
|
||||
QSize(ByteItem::WIDTH, ByteItem::HEIGHT)
|
||||
);
|
||||
this->setAcceptHoverEvents(true);
|
||||
|
||||
this->addressHex = "0x" + QString::number(this->address, 16).rightJustified(8, '0').toUpper();
|
||||
this->relativeAddressHex = "0x" + QString::number(this->byteIndex, 16).rightJustified(8, '0').toUpper();
|
||||
this->addressHex = "0x" + QString::number(this->address, 16).rightJustified(
|
||||
8,
|
||||
'0'
|
||||
).toUpper();
|
||||
this->relativeAddressHex = "0x" + QString::number(this->byteIndex, 16).rightJustified(
|
||||
8,
|
||||
'0'
|
||||
).toUpper();
|
||||
|
||||
this->setSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItem::setValue(unsigned char value) {
|
||||
void ByteItem::setValue(unsigned char value) {
|
||||
this->valueChanged = this->valueInitialised && this->value != value;
|
||||
|
||||
this->value = value;
|
||||
@@ -45,10 +50,13 @@ void ByteItem::setValue(unsigned char value) {
|
||||
|
||||
this->valueInitialised = this->excludedMemoryRegion == nullptr;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
painter->setRenderHints(QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform, true);
|
||||
void ByteItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
painter->setRenderHints(
|
||||
QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform,
|
||||
true
|
||||
);
|
||||
painter->setPen(Qt::PenStyle::NoPen);
|
||||
|
||||
// TODO: This code could do with some tidying. It's getting quite messy.
|
||||
@@ -163,4 +171,5 @@ void ByteItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
|
||||
static const auto placeholderString = QString("??");
|
||||
painter->drawText(widgetRect, Qt::AlignCenter, placeholderString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "ByteItemContainerGraphicsView.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
using Bloom::Targets::TargetMemoryDescriptor;
|
||||
|
||||
using Bloom::Targets::TargetMemoryDescriptor;
|
||||
|
||||
ByteItemContainerGraphicsView::ByteItemContainerGraphicsView(
|
||||
ByteItemContainerGraphicsView::ByteItemContainerGraphicsView(
|
||||
const TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||
@@ -12,7 +12,7 @@ ByteItemContainerGraphicsView::ByteItemContainerGraphicsView(
|
||||
const HexViewerWidgetSettings& settings,
|
||||
QLabel* hoveredAddressLabel,
|
||||
QWidget* parent
|
||||
): QGraphicsView(parent) {
|
||||
): QGraphicsView(parent) {
|
||||
this->setObjectName("graphics-view");
|
||||
this->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
|
||||
this->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn);
|
||||
@@ -32,22 +32,23 @@ ByteItemContainerGraphicsView::ByteItemContainerGraphicsView(
|
||||
|
||||
this->setScene(this->scene);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemContainerGraphicsView::scrollToByteItemAtAddress(std::uint32_t address) {
|
||||
void ByteItemContainerGraphicsView::scrollToByteItemAtAddress(std::uint32_t address) {
|
||||
this->centerOn(this->scene->getByteItemPositionByAddress(address));
|
||||
}
|
||||
}
|
||||
|
||||
bool ByteItemContainerGraphicsView::event(QEvent* event) {
|
||||
bool ByteItemContainerGraphicsView::event(QEvent* event) {
|
||||
const auto eventType = event->type();
|
||||
if (eventType == QEvent::Type::EnabledChange) {
|
||||
this->scene->setEnabled(this->isEnabled());
|
||||
}
|
||||
|
||||
return QGraphicsView::event(event);
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemContainerGraphicsView::resizeEvent(QResizeEvent* event) {
|
||||
void ByteItemContainerGraphicsView::resizeEvent(QResizeEvent* event) {
|
||||
QGraphicsView::resizeEvent(event);
|
||||
this->scene->adjustSize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
using Bloom::Targets::TargetMemoryDescriptor;
|
||||
|
||||
using Bloom::Targets::TargetMemoryDescriptor;
|
||||
|
||||
ByteItemGraphicsScene::ByteItemGraphicsScene(
|
||||
ByteItemGraphicsScene::ByteItemGraphicsScene(
|
||||
const TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||
@@ -14,16 +14,16 @@ ByteItemGraphicsScene::ByteItemGraphicsScene(
|
||||
const HexViewerWidgetSettings& settings,
|
||||
QLabel* hoveredAddressLabel,
|
||||
QGraphicsView* parent
|
||||
):
|
||||
QGraphicsScene(parent),
|
||||
targetMemoryDescriptor(targetMemoryDescriptor),
|
||||
focusedMemoryRegions(focusedMemoryRegions),
|
||||
excludedMemoryRegions(excludedMemoryRegions),
|
||||
insightWorker(insightWorker),
|
||||
settings(settings),
|
||||
hoveredAddressLabel(hoveredAddressLabel),
|
||||
parent(parent)
|
||||
{
|
||||
)
|
||||
: QGraphicsScene(parent)
|
||||
, targetMemoryDescriptor(targetMemoryDescriptor)
|
||||
, focusedMemoryRegions(focusedMemoryRegions)
|
||||
, excludedMemoryRegions(excludedMemoryRegions)
|
||||
, insightWorker(insightWorker)
|
||||
, settings(settings)
|
||||
, hoveredAddressLabel(hoveredAddressLabel)
|
||||
, parent(parent)
|
||||
{
|
||||
this->setObjectName("byte-widget-container");
|
||||
|
||||
this->byteAddressContainer = new ByteAddressContainer();
|
||||
@@ -62,28 +62,28 @@ ByteItemGraphicsScene::ByteItemGraphicsScene(
|
||||
|
||||
this->refreshRegions();
|
||||
this->adjustSize();
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::updateValues(const Targets::TargetMemoryBuffer& buffer) {
|
||||
void ByteItemGraphicsScene::updateValues(const Targets::TargetMemoryBuffer& buffer) {
|
||||
for (auto& [address, byteWidget] : this->byteItemsByAddress) {
|
||||
byteWidget->setValue(buffer.at(byteWidget->byteIndex));
|
||||
}
|
||||
|
||||
this->updateAnnotationValues(buffer);
|
||||
this->lastValueBuffer = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::updateStackPointer(std::uint32_t stackPointer) {
|
||||
void ByteItemGraphicsScene::updateStackPointer(std::uint32_t stackPointer) {
|
||||
this->currentStackPointer = stackPointer;
|
||||
this->invalidateChildItemCaches();
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::setHighlightedAddresses(const std::set<std::uint32_t>& highlightedAddresses) {
|
||||
void ByteItemGraphicsScene::setHighlightedAddresses(const std::set<std::uint32_t>& highlightedAddresses) {
|
||||
this->highlightedAddresses = highlightedAddresses;
|
||||
this->invalidateChildItemCaches();
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::refreshRegions() {
|
||||
void ByteItemGraphicsScene::refreshRegions() {
|
||||
for (auto& [byteAddress, byteWidget] : this->byteItemsByAddress) {
|
||||
byteWidget->focusedMemoryRegion = nullptr;
|
||||
byteWidget->excludedMemoryRegion = nullptr;
|
||||
@@ -139,22 +139,22 @@ void ByteItemGraphicsScene::refreshRegions() {
|
||||
}
|
||||
|
||||
this->adjustSize(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::adjustSize(bool forced) {
|
||||
void ByteItemGraphicsScene::adjustSize(bool forced) {
|
||||
const auto width = this->getSceneWidth();
|
||||
|
||||
const auto columnCount = static_cast<std::size_t>(
|
||||
std::floor(
|
||||
(width - this->margins.left() - this->margins.right() - ByteAddressContainer::WIDTH + ByteItem::RIGHT_MARGIN)
|
||||
/ (ByteItem::WIDTH + ByteItem::RIGHT_MARGIN)
|
||||
(width - this->margins.left() - this->margins.right() - ByteAddressContainer::WIDTH
|
||||
+ ByteItem::RIGHT_MARGIN) / (ByteItem::WIDTH + ByteItem::RIGHT_MARGIN)
|
||||
)
|
||||
);
|
||||
const auto rowCount = static_cast<int>(
|
||||
std::ceil(static_cast<double>(this->byteItemsByAddress.size()) / static_cast<double>(columnCount))
|
||||
);
|
||||
|
||||
// Don't bother recalculating the byte item & annotation positions if the number of rows & columns have not changed.
|
||||
// Don't bother recalculating the byte & annotation positions if the number of rows & columns haven't changed.
|
||||
if (this->byteItemsByAddress.empty()
|
||||
|| (
|
||||
!forced
|
||||
@@ -193,9 +193,9 @@ void ByteItemGraphicsScene::adjustSize(bool forced) {
|
||||
}
|
||||
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::setEnabled(bool enabled) {
|
||||
void ByteItemGraphicsScene::setEnabled(bool enabled) {
|
||||
if (this->enabled != enabled) {
|
||||
this->enabled = enabled;
|
||||
|
||||
@@ -211,9 +211,9 @@ void ByteItemGraphicsScene::setEnabled(bool enabled) {
|
||||
this->byteAddressContainer->update();
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::invalidateChildItemCaches() {
|
||||
void ByteItemGraphicsScene::invalidateChildItemCaches() {
|
||||
for (auto& [address, byteWidget] : this->byteItemsByAddress) {
|
||||
byteWidget->update();
|
||||
}
|
||||
@@ -221,25 +221,25 @@ void ByteItemGraphicsScene::invalidateChildItemCaches() {
|
||||
for (auto* annotationItem : this->annotationItems) {
|
||||
annotationItem->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPointF ByteItemGraphicsScene::getByteItemPositionByAddress(std::uint32_t address) {
|
||||
QPointF ByteItemGraphicsScene::getByteItemPositionByAddress(std::uint32_t address) {
|
||||
if (this->byteItemsByAddress.contains(address)) {
|
||||
return this->byteItemsByAddress.at(address)->pos();
|
||||
}
|
||||
|
||||
return QPointF();
|
||||
}
|
||||
}
|
||||
|
||||
bool ByteItemGraphicsScene::event(QEvent* event) {
|
||||
bool ByteItemGraphicsScene::event(QEvent* event) {
|
||||
if (event->type() == QEvent::Type::GraphicsSceneLeave && this->hoveredByteWidget.has_value()) {
|
||||
this->onByteWidgetLeave();
|
||||
}
|
||||
|
||||
return QGraphicsScene::event(event);
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) {
|
||||
void ByteItemGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) {
|
||||
auto hoveredItems = this->items(mouseEvent->scenePos());
|
||||
ByteItem* hoveredByteItem = nullptr;
|
||||
AnnotationItem* hoveredAnnotationItem = nullptr;
|
||||
@@ -266,9 +266,9 @@ void ByteItemGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent)
|
||||
if (this->hoveredAnnotationItem.has_value()) {
|
||||
this->onAnnotationItemLeave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::updateAnnotationValues(const Targets::TargetMemoryBuffer& buffer) {
|
||||
void ByteItemGraphicsScene::updateAnnotationValues(const Targets::TargetMemoryBuffer& buffer) {
|
||||
const auto memoryStartAddress = this->targetMemoryDescriptor.addressRange.startAddress;
|
||||
for (auto* valueAnnotationItem : this->valueAnnotationItems) {
|
||||
if (valueAnnotationItem->size > buffer.size()) {
|
||||
@@ -283,13 +283,13 @@ void ByteItemGraphicsScene::updateAnnotationValues(const Targets::TargetMemoryBu
|
||||
buffer.begin() + relativeEndAddress + 1
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::adjustByteItemPositions() {
|
||||
void ByteItemGraphicsScene::adjustByteItemPositions() {
|
||||
const auto columnCount = static_cast<std::size_t>(
|
||||
std::floor(
|
||||
(this->getSceneWidth() - this->margins.left() - this->margins.right() - ByteAddressContainer::WIDTH + ByteItem::RIGHT_MARGIN)
|
||||
/ (ByteItem::WIDTH + ByteItem::RIGHT_MARGIN)
|
||||
(this->getSceneWidth() - this->margins.left() - this->margins.right() - ByteAddressContainer::WIDTH
|
||||
+ ByteItem::RIGHT_MARGIN) / (ByteItem::WIDTH + ByteItem::RIGHT_MARGIN)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -359,7 +359,9 @@ void ByteItemGraphicsScene::adjustByteItemPositions() {
|
||||
|
||||
byteWidget->setPos(
|
||||
static_cast<int>(
|
||||
columnIndex * (ByteItem::WIDTH + ByteItem::RIGHT_MARGIN) + this->margins.left() + ByteAddressContainer::WIDTH),
|
||||
columnIndex * (ByteItem::WIDTH + ByteItem::RIGHT_MARGIN) + this->margins.left()
|
||||
+ ByteAddressContainer::WIDTH
|
||||
),
|
||||
rowYPosition
|
||||
);
|
||||
|
||||
@@ -376,9 +378,9 @@ void ByteItemGraphicsScene::adjustByteItemPositions() {
|
||||
this->byteItemsByColumnIndex = std::move(byteWidgetsByColumnIndex);
|
||||
|
||||
this->byteAddressContainer->adjustAddressLabels(this->byteItemsByRowIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::adjustAnnotationItemPositions() {
|
||||
void ByteItemGraphicsScene::adjustAnnotationItemPositions() {
|
||||
if (this->byteItemsByAddress.empty() || !this->settings.displayAnnotations) {
|
||||
return;
|
||||
}
|
||||
@@ -404,14 +406,14 @@ void ByteItemGraphicsScene::adjustAnnotationItemPositions() {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::onTargetStateChanged(Targets::TargetState newState) {
|
||||
void ByteItemGraphicsScene::onTargetStateChanged(Targets::TargetState newState) {
|
||||
using Targets::TargetState;
|
||||
this->targetState = newState;
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::onByteWidgetEnter(ByteItem* widget) {
|
||||
void ByteItemGraphicsScene::onByteWidgetEnter(ByteItem* widget) {
|
||||
if (this->hoveredByteWidget.has_value()) {
|
||||
if (this->hoveredByteWidget.value() == widget) {
|
||||
// This byte item is already marked as hovered
|
||||
@@ -439,9 +441,9 @@ void ByteItemGraphicsScene::onByteWidgetEnter(ByteItem* widget) {
|
||||
} else {
|
||||
widget->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::onByteWidgetLeave() {
|
||||
void ByteItemGraphicsScene::onByteWidgetLeave() {
|
||||
auto* byteItem = this->hoveredByteWidget.value();
|
||||
this->hoveredByteWidget = std::nullopt;
|
||||
|
||||
@@ -459,9 +461,9 @@ void ByteItemGraphicsScene::onByteWidgetLeave() {
|
||||
} else {
|
||||
byteItem->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::onAnnotationItemEnter(AnnotationItem* annotationItem) {
|
||||
void ByteItemGraphicsScene::onAnnotationItemEnter(AnnotationItem* annotationItem) {
|
||||
if (this->hoveredAnnotationItem.has_value()) {
|
||||
if (this->hoveredAnnotationItem.value() == annotationItem) {
|
||||
return;
|
||||
@@ -479,9 +481,9 @@ void ByteItemGraphicsScene::onAnnotationItemEnter(AnnotationItem* annotationItem
|
||||
) {
|
||||
this->byteItemsByAddress.at(byteItemAddress)->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::onAnnotationItemLeave() {
|
||||
void ByteItemGraphicsScene::onAnnotationItemLeave() {
|
||||
auto* annotationItem = this->hoveredAnnotationItem.value();
|
||||
this->hoveredAnnotationItem = std::nullopt;
|
||||
|
||||
@@ -492,4 +494,5 @@ void ByteItemGraphicsScene::onAnnotationItemLeave() {
|
||||
) {
|
||||
this->byteItemsByAddress.at(byteItemAddress)->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,26 +5,27 @@
|
||||
#include "src/Helpers/Paths.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
using Bloom::Targets::TargetMemoryDescriptor;
|
||||
using Bloom::Targets::TargetMemoryDescriptor;
|
||||
|
||||
HexViewerWidget::HexViewerWidget(
|
||||
HexViewerWidget::HexViewerWidget(
|
||||
const TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||
HexViewerWidgetSettings& settings,
|
||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||
InsightWorker& insightWorker,
|
||||
QWidget* parent
|
||||
):
|
||||
QWidget(parent),
|
||||
targetMemoryDescriptor(targetMemoryDescriptor),
|
||||
settings(settings),
|
||||
focusedMemoryRegions(focusedMemoryRegions),
|
||||
excludedMemoryRegions(excludedMemoryRegions),
|
||||
insightWorker(insightWorker)
|
||||
{
|
||||
)
|
||||
: QWidget(parent)
|
||||
, targetMemoryDescriptor(targetMemoryDescriptor)
|
||||
, settings(settings)
|
||||
, focusedMemoryRegions(focusedMemoryRegions)
|
||||
, excludedMemoryRegions(excludedMemoryRegions)
|
||||
, insightWorker(insightWorker)
|
||||
{
|
||||
this->setObjectName("hex-viewer-widget");
|
||||
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
|
||||
@@ -48,7 +49,9 @@ HexViewerWidget::HexViewerWidget(
|
||||
this->bottomBar = this->container->findChild<QWidget*>("bottom-bar");
|
||||
|
||||
this->refreshButton = this->toolBar->findChild<SvgToolButton*>("refresh-memory-btn");
|
||||
this->highlightStackMemoryButton = this->toolBar->findChild<SvgToolButton*>("highlight-stack-memory-btn");
|
||||
this->highlightStackMemoryButton = this->toolBar->findChild<SvgToolButton*>(
|
||||
"highlight-stack-memory-btn"
|
||||
);
|
||||
this->highlightHoveredRowAndColumnButton = this->toolBar->findChild<SvgToolButton*>(
|
||||
"highlight-hovered-rows-columns-btn"
|
||||
);
|
||||
@@ -161,74 +164,74 @@ HexViewerWidget::HexViewerWidget(
|
||||
);
|
||||
|
||||
this->show();
|
||||
}
|
||||
}
|
||||
|
||||
void HexViewerWidget::updateValues(const Targets::TargetMemoryBuffer& buffer) {
|
||||
void HexViewerWidget::updateValues(const Targets::TargetMemoryBuffer& buffer) {
|
||||
this->byteItemGraphicsScene->updateValues(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void HexViewerWidget::refreshRegions() {
|
||||
void HexViewerWidget::refreshRegions() {
|
||||
this->byteItemGraphicsScene->refreshRegions();
|
||||
}
|
||||
}
|
||||
|
||||
void HexViewerWidget::setStackPointer(std::uint32_t stackPointer) {
|
||||
void HexViewerWidget::setStackPointer(std::uint32_t stackPointer) {
|
||||
this->byteItemGraphicsScene->updateStackPointer(stackPointer);
|
||||
}
|
||||
}
|
||||
|
||||
void HexViewerWidget::resizeEvent(QResizeEvent* event) {
|
||||
void HexViewerWidget::resizeEvent(QResizeEvent* event) {
|
||||
this->container->setFixedSize(
|
||||
this->width(),
|
||||
this->height()
|
||||
);
|
||||
|
||||
this->byteItemGraphicsView->setFixedSize(this->byteItemGraphicsViewContainer->size());
|
||||
}
|
||||
}
|
||||
|
||||
void HexViewerWidget::showEvent(QShowEvent* event) {
|
||||
void HexViewerWidget::showEvent(QShowEvent* event) {
|
||||
this->byteItemGraphicsView->setFixedSize(this->byteItemGraphicsViewContainer->size());
|
||||
}
|
||||
}
|
||||
|
||||
void HexViewerWidget::onTargetStateChanged(Targets::TargetState newState) {
|
||||
void HexViewerWidget::onTargetStateChanged(Targets::TargetState newState) {
|
||||
using Targets::TargetState;
|
||||
this->targetState = newState;
|
||||
}
|
||||
}
|
||||
|
||||
void HexViewerWidget::setStackMemoryHighlightingEnabled(bool enabled) {
|
||||
void HexViewerWidget::setStackMemoryHighlightingEnabled(bool enabled) {
|
||||
this->highlightStackMemoryButton->setChecked(enabled);
|
||||
this->settings.highlightStackMemory = enabled;
|
||||
|
||||
this->byteItemGraphicsScene->invalidateChildItemCaches();
|
||||
}
|
||||
}
|
||||
|
||||
void HexViewerWidget::setHoveredRowAndColumnHighlightingEnabled(bool enabled) {
|
||||
void HexViewerWidget::setHoveredRowAndColumnHighlightingEnabled(bool enabled) {
|
||||
this->highlightHoveredRowAndColumnButton->setChecked(enabled);
|
||||
this->settings.highlightHoveredRowAndCol = enabled;
|
||||
|
||||
this->byteItemGraphicsScene->invalidateChildItemCaches();
|
||||
}
|
||||
}
|
||||
|
||||
void HexViewerWidget::setFocusedMemoryHighlightingEnabled(bool enabled) {
|
||||
void HexViewerWidget::setFocusedMemoryHighlightingEnabled(bool enabled) {
|
||||
this->highlightFocusedMemoryButton->setChecked(enabled);
|
||||
this->settings.highlightFocusedMemory = enabled;
|
||||
|
||||
this->byteItemGraphicsScene->invalidateChildItemCaches();
|
||||
}
|
||||
}
|
||||
|
||||
void HexViewerWidget::setAnnotationsEnabled(bool enabled) {
|
||||
void HexViewerWidget::setAnnotationsEnabled(bool enabled) {
|
||||
this->displayAnnotationsButton->setChecked(enabled);
|
||||
this->settings.displayAnnotations = enabled;
|
||||
|
||||
this->byteItemGraphicsScene->adjustSize(true);
|
||||
}
|
||||
}
|
||||
|
||||
void HexViewerWidget::setDisplayAsciiEnabled(bool enabled) {
|
||||
void HexViewerWidget::setDisplayAsciiEnabled(bool enabled) {
|
||||
this->displayAsciiButton->setChecked(enabled);
|
||||
this->settings.displayAsciiValues = enabled;
|
||||
|
||||
this->byteItemGraphicsScene->invalidateChildItemCaches();
|
||||
}
|
||||
}
|
||||
|
||||
void HexViewerWidget::onGoToAddressInputChanged() {
|
||||
void HexViewerWidget::onGoToAddressInputChanged() {
|
||||
auto addressConversionOk = false;
|
||||
const auto address = this->goToAddressInput->text().toUInt(&addressConversionOk, 16);
|
||||
|
||||
@@ -241,4 +244,5 @@ void HexViewerWidget::onGoToAddressInputChanged() {
|
||||
}
|
||||
|
||||
this->byteItemGraphicsScene->setHighlightedAddresses({});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
ValueAnnotationItem::ValueAnnotationItem(const FocusedMemoryRegion& focusedMemoryRegion)
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
ValueAnnotationItem::ValueAnnotationItem(const FocusedMemoryRegion& focusedMemoryRegion)
|
||||
: AnnotationItem(focusedMemoryRegion, AnnotationItemPosition::TOP)
|
||||
, focusedMemoryRegion(focusedMemoryRegion)
|
||||
, endianness(focusedMemoryRegion.endianness)
|
||||
{
|
||||
{
|
||||
this->labelText = QString(ValueAnnotationItem::DEFAULT_LABEL_TEXT);
|
||||
}
|
||||
}
|
||||
|
||||
void ValueAnnotationItem::setValue(const Targets::TargetMemoryBuffer& value) {
|
||||
void ValueAnnotationItem::setValue(const Targets::TargetMemoryBuffer& value) {
|
||||
this->value = value;
|
||||
|
||||
if (this->endianness == Targets::TargetMemoryEndianness::LITTLE) {
|
||||
@@ -21,17 +21,17 @@ void ValueAnnotationItem::setValue(const Targets::TargetMemoryBuffer& value) {
|
||||
|
||||
this->refreshLabelText();
|
||||
this->setToolTip(this->labelText);
|
||||
}
|
||||
}
|
||||
|
||||
void ValueAnnotationItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
void ValueAnnotationItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
auto font = painter->font();
|
||||
font.setItalic(true);
|
||||
painter->setFont(font);
|
||||
|
||||
AnnotationItem::paint(painter, option, widget);
|
||||
}
|
||||
}
|
||||
|
||||
void ValueAnnotationItem::refreshLabelText() {
|
||||
void ValueAnnotationItem::refreshLabelText() {
|
||||
this->update();
|
||||
|
||||
if (this->value.empty()) {
|
||||
@@ -109,4 +109,5 @@ void ValueAnnotationItem::refreshLabelText() {
|
||||
this->labelText = QString(ValueAnnotationItem::DEFAULT_LABEL_TEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,13 @@
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/UiLoader.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
using Targets::TargetMemoryAddressRange;
|
||||
|
||||
ExcludedRegionItem::ExcludedRegionItem(
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
ExcludedRegionItem::ExcludedRegionItem(
|
||||
const ExcludedMemoryRegion& region,
|
||||
const Targets::TargetMemoryDescriptor& memoryDescriptor,
|
||||
QWidget* parent
|
||||
): memoryRegion(region), RegionItem(region, memoryDescriptor, parent) {
|
||||
): memoryRegion(region), RegionItem(region, memoryDescriptor, parent) {
|
||||
auto formUiFile = QFile(
|
||||
QString::fromStdString(Paths::compiledResourcesPath()
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane"
|
||||
@@ -31,9 +28,11 @@ ExcludedRegionItem::ExcludedRegionItem(
|
||||
this->formWidget = uiLoader.load(&formUiFile, this);
|
||||
|
||||
this->initFormInputs();
|
||||
}
|
||||
}
|
||||
|
||||
void ExcludedRegionItem::applyChanges() {
|
||||
using Targets::TargetMemoryAddressRange;
|
||||
|
||||
void ExcludedRegionItem::applyChanges() {
|
||||
this->memoryRegion.name = this->nameInput->text();
|
||||
|
||||
const auto inputAddressRange = TargetMemoryAddressRange(
|
||||
@@ -41,6 +40,8 @@ void ExcludedRegionItem::applyChanges() {
|
||||
this->endAddressInput->text().toUInt(nullptr, 16)
|
||||
);
|
||||
this->memoryRegion.addressRangeInputType = this->getSelectedAddressInputType();
|
||||
this->memoryRegion.addressRange = this->memoryRegion.addressRangeInputType == MemoryRegionAddressInputType::RELATIVE ?
|
||||
this->memoryRegion.addressRange =
|
||||
this->memoryRegion.addressRangeInputType == MemoryRegionAddressInputType::RELATIVE ?
|
||||
this->convertRelativeToAbsoluteAddressRange(inputAddressRange) : inputAddressRange;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,15 @@
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/UiLoader.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
using namespace Bloom::Widgets;
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
using Targets::TargetMemoryAddressRange;
|
||||
|
||||
using Targets::TargetMemoryAddressRange;
|
||||
|
||||
FocusedRegionItem::FocusedRegionItem(
|
||||
FocusedRegionItem::FocusedRegionItem(
|
||||
const FocusedMemoryRegion& region,
|
||||
const Targets::TargetMemoryDescriptor& memoryDescriptor,
|
||||
QWidget* parent
|
||||
): memoryRegion(region), RegionItem(region, memoryDescriptor, parent) {
|
||||
): memoryRegion(region), RegionItem(region, memoryDescriptor, parent) {
|
||||
auto formUiFile = QFile(
|
||||
QString::fromStdString(Paths::compiledResourcesPath()
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane"
|
||||
@@ -31,9 +30,9 @@ FocusedRegionItem::FocusedRegionItem(
|
||||
this->formWidget = uiLoader.load(&formUiFile, this);
|
||||
|
||||
this->initFormInputs();
|
||||
}
|
||||
}
|
||||
|
||||
void FocusedRegionItem::applyChanges() {
|
||||
void FocusedRegionItem::applyChanges() {
|
||||
this->memoryRegion.name = this->nameInput->text();
|
||||
|
||||
const auto inputAddressRange = TargetMemoryAddressRange(
|
||||
@@ -47,7 +46,9 @@ void FocusedRegionItem::applyChanges() {
|
||||
|
||||
auto selectedDataTypeOptionName = this->dataTypeInput->currentData().toString();
|
||||
if (FocusedRegionItem::dataTypeOptionsByName.contains(selectedDataTypeOptionName)) {
|
||||
this->memoryRegion.dataType = FocusedRegionItem::dataTypeOptionsByName.at(selectedDataTypeOptionName).dataType;
|
||||
this->memoryRegion.dataType = FocusedRegionItem::dataTypeOptionsByName.at(
|
||||
selectedDataTypeOptionName
|
||||
).dataType;
|
||||
}
|
||||
|
||||
auto selectedEndiannessOptionName = this->endiannessInput->currentData().toString();
|
||||
@@ -56,9 +57,9 @@ void FocusedRegionItem::applyChanges() {
|
||||
selectedEndiannessOptionName
|
||||
).endianness;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FocusedRegionItem::initFormInputs() {
|
||||
void FocusedRegionItem::initFormInputs() {
|
||||
RegionItem::initFormInputs();
|
||||
const auto& region = this->memoryRegion;
|
||||
|
||||
@@ -75,11 +76,15 @@ void FocusedRegionItem::initFormInputs() {
|
||||
|
||||
switch (region.dataType) {
|
||||
case MemoryRegionDataType::UNSIGNED_INTEGER: {
|
||||
this->dataTypeInput->setCurrentText(FocusedRegionItem::dataTypeOptionsByName.at("unsigned_integer").text);
|
||||
this->dataTypeInput->setCurrentText(
|
||||
FocusedRegionItem::dataTypeOptionsByName.at("unsigned_integer").text
|
||||
);
|
||||
break;
|
||||
}
|
||||
case MemoryRegionDataType::SIGNED_INTEGER: {
|
||||
this->dataTypeInput->setCurrentText(FocusedRegionItem::dataTypeOptionsByName.at("signed_integer").text);
|
||||
this->dataTypeInput->setCurrentText(
|
||||
FocusedRegionItem::dataTypeOptionsByName.at("signed_integer").text
|
||||
);
|
||||
break;
|
||||
}
|
||||
case MemoryRegionDataType::ASCII_STRING: {
|
||||
@@ -101,4 +106,5 @@ void FocusedRegionItem::initFormInputs() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,22 +10,21 @@
|
||||
#include "src/Helpers/Paths.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
using namespace Bloom::Widgets;
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
using Bloom::Exceptions::Exception;
|
||||
|
||||
using Bloom::Exceptions::Exception;
|
||||
|
||||
MemoryRegionManagerWindow::MemoryRegionManagerWindow(
|
||||
MemoryRegionManagerWindow::MemoryRegionManagerWindow(
|
||||
const Targets::TargetMemoryDescriptor& memoryDescriptor,
|
||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||
QWidget* parent
|
||||
):
|
||||
QWidget(parent),
|
||||
memoryDescriptor(memoryDescriptor),
|
||||
focusedMemoryRegions(focusedMemoryRegions),
|
||||
excludedMemoryRegions(excludedMemoryRegions)
|
||||
{
|
||||
)
|
||||
: QWidget(parent)
|
||||
, memoryDescriptor(memoryDescriptor)
|
||||
, focusedMemoryRegions(focusedMemoryRegions)
|
||||
, excludedMemoryRegions(excludedMemoryRegions)
|
||||
{
|
||||
this->setWindowFlag(Qt::Window);
|
||||
this->setObjectName("memory-region-manager-window");
|
||||
this->setWindowTitle(
|
||||
@@ -118,9 +117,9 @@ MemoryRegionManagerWindow::MemoryRegionManagerWindow(
|
||||
// Position the inspection window at the center of the main Insight window
|
||||
this->move(parent->window()->geometry().center() - this->rect().center());
|
||||
this->show();
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryRegionManagerWindow::refreshRegions() {
|
||||
void MemoryRegionManagerWindow::refreshRegions() {
|
||||
this->clearRegions();
|
||||
|
||||
for (const auto& focusedRegion: this->focusedMemoryRegions) {
|
||||
@@ -132,9 +131,9 @@ void MemoryRegionManagerWindow::refreshRegions() {
|
||||
}
|
||||
|
||||
this->sortRegionItems();
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryRegionManagerWindow::showEvent(QShowEvent* event) {
|
||||
void MemoryRegionManagerWindow::showEvent(QShowEvent* event) {
|
||||
if (this->selectedRegion == nullptr && this->regionItemScrollAreaViewportLayout->count() > 0) {
|
||||
auto* firstRegionItem = qobject_cast<RegionItem*>(
|
||||
this->regionItemScrollAreaViewportLayout->itemAt(0)->widget()
|
||||
@@ -144,9 +143,9 @@ void MemoryRegionManagerWindow::showEvent(QShowEvent* event) {
|
||||
firstRegionItem->setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryRegionManagerWindow::clearRegions() {
|
||||
void MemoryRegionManagerWindow::clearRegions() {
|
||||
this->selectedRegion = nullptr;
|
||||
|
||||
for (auto* focusedRegionItem: this->focusedRegionItems) {
|
||||
@@ -165,9 +164,9 @@ void MemoryRegionManagerWindow::clearRegions() {
|
||||
|
||||
this->focusedRegionItems.clear();
|
||||
this->excludedRegionItems.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryRegionManagerWindow::sortRegionItems() {
|
||||
void MemoryRegionManagerWindow::sortRegionItems() {
|
||||
/*
|
||||
* This isn't very pretty.
|
||||
*
|
||||
@@ -192,42 +191,60 @@ void MemoryRegionManagerWindow::sortRegionItems() {
|
||||
for (auto* regionItem: sortedRegionItems) {
|
||||
this->regionItemScrollAreaViewportLayout->addWidget(regionItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FocusedRegionItem* MemoryRegionManagerWindow::addFocusedRegion(const FocusedMemoryRegion& region) {
|
||||
auto* focusedRegionItem = new FocusedRegionItem(region, this->memoryDescriptor, this->regionItemScrollAreaViewport);
|
||||
FocusedRegionItem* MemoryRegionManagerWindow::addFocusedRegion(const FocusedMemoryRegion& region) {
|
||||
auto* focusedRegionItem = new FocusedRegionItem(
|
||||
region,
|
||||
this->memoryDescriptor,
|
||||
this->regionItemScrollAreaViewport
|
||||
);
|
||||
this->focusedRegionItems.insert(focusedRegionItem);
|
||||
|
||||
this->regionItemScrollAreaViewportLayout->addWidget(focusedRegionItem);
|
||||
this->stackedFormLayout->addWidget(focusedRegionItem->getFormWidget());
|
||||
|
||||
QObject::connect(focusedRegionItem, &RegionItem::selected, this, &MemoryRegionManagerWindow::onRegionSelected);
|
||||
QObject::connect(
|
||||
focusedRegionItem,
|
||||
&RegionItem::selected,
|
||||
this,
|
||||
&MemoryRegionManagerWindow::onRegionSelected
|
||||
);
|
||||
|
||||
return focusedRegionItem;
|
||||
}
|
||||
}
|
||||
|
||||
ExcludedRegionItem* MemoryRegionManagerWindow::addExcludedRegion(const ExcludedMemoryRegion& region) {
|
||||
auto* excludedRegionItem = new ExcludedRegionItem(region, this->memoryDescriptor, this->regionItemScrollAreaViewport);
|
||||
ExcludedRegionItem* MemoryRegionManagerWindow::addExcludedRegion(const ExcludedMemoryRegion& region) {
|
||||
auto* excludedRegionItem = new ExcludedRegionItem(
|
||||
region,
|
||||
this->memoryDescriptor,
|
||||
this->regionItemScrollAreaViewport
|
||||
);
|
||||
this->excludedRegionItems.insert(excludedRegionItem);
|
||||
|
||||
this->regionItemScrollAreaViewportLayout->addWidget(excludedRegionItem);
|
||||
this->stackedFormLayout->addWidget(excludedRegionItem->getFormWidget());
|
||||
|
||||
QObject::connect(excludedRegionItem, &RegionItem::selected, this, &MemoryRegionManagerWindow::onRegionSelected);
|
||||
QObject::connect(
|
||||
excludedRegionItem,
|
||||
&RegionItem::selected,
|
||||
this,
|
||||
&MemoryRegionManagerWindow::onRegionSelected
|
||||
);
|
||||
|
||||
return excludedRegionItem;
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryRegionManagerWindow::onRegionSelected(RegionItem* selectedRegion) {
|
||||
void MemoryRegionManagerWindow::onRegionSelected(RegionItem* selectedRegion) {
|
||||
if (this->selectedRegion != nullptr && this->selectedRegion != selectedRegion) {
|
||||
this->selectedRegion->setSelected(false);
|
||||
}
|
||||
|
||||
this->selectedRegion = selectedRegion;
|
||||
this->stackedFormLayout->setCurrentWidget(this->selectedRegion->getFormWidget());
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryRegionManagerWindow::onNewFocusedRegionTrigger() {
|
||||
void MemoryRegionManagerWindow::onNewFocusedRegionTrigger() {
|
||||
using Targets::TargetMemoryAddressRange;
|
||||
|
||||
auto* region = this->addFocusedRegion(FocusedMemoryRegion(
|
||||
@@ -239,9 +256,9 @@ void MemoryRegionManagerWindow::onNewFocusedRegionTrigger() {
|
||||
));
|
||||
|
||||
region->setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryRegionManagerWindow::onNewExcludedRegionTrigger() {
|
||||
void MemoryRegionManagerWindow::onNewExcludedRegionTrigger() {
|
||||
using Targets::TargetMemoryAddressRange;
|
||||
|
||||
auto* region = this->addExcludedRegion(ExcludedMemoryRegion(
|
||||
@@ -253,9 +270,9 @@ void MemoryRegionManagerWindow::onNewExcludedRegionTrigger() {
|
||||
));
|
||||
|
||||
region->setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryRegionManagerWindow::onDeleteRegionTrigger() {
|
||||
void MemoryRegionManagerWindow::onDeleteRegionTrigger() {
|
||||
if (this->selectedRegion == nullptr) {
|
||||
return;
|
||||
}
|
||||
@@ -293,9 +310,9 @@ void MemoryRegionManagerWindow::onDeleteRegionTrigger() {
|
||||
regionItem->setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryRegionManagerWindow::applyChanges() {
|
||||
void MemoryRegionManagerWindow::applyChanges() {
|
||||
auto processedFocusedMemoryRegions = std::vector<FocusedMemoryRegion>();
|
||||
auto processedExcludedMemoryRegions = std::vector<ExcludedMemoryRegion>();
|
||||
|
||||
@@ -383,10 +400,11 @@ void MemoryRegionManagerWindow::applyChanges() {
|
||||
this->excludedMemoryRegions = std::move(processedExcludedMemoryRegions);
|
||||
this->close();
|
||||
emit this->changesApplied();
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryRegionManagerWindow::openHelpPage() {
|
||||
void MemoryRegionManagerWindow::openHelpPage() {
|
||||
QDesktopServices::openUrl(
|
||||
QUrl(QString::fromStdString(Paths::homeDomainName() + "/docs/manage-memory-regions"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QString>
|
||||
|
||||
using namespace Bloom;
|
||||
using namespace Bloom::Widgets;
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
using Targets::TargetMemoryAddressRange;
|
||||
|
||||
using Targets::TargetMemoryAddressRange;
|
||||
|
||||
RegionItem::RegionItem(
|
||||
RegionItem::RegionItem(
|
||||
const MemoryRegion& region,
|
||||
const Targets::TargetMemoryDescriptor& memoryDescriptor,
|
||||
QWidget* parent
|
||||
): memoryDescriptor(memoryDescriptor), ClickableWidget(parent) {
|
||||
): memoryDescriptor(memoryDescriptor), ClickableWidget(parent) {
|
||||
this->setObjectName("region-item");
|
||||
this->setFixedHeight(50);
|
||||
this->layout->setContentsMargins(5, 5, 5, 0);
|
||||
@@ -61,9 +60,9 @@ RegionItem::RegionItem(
|
||||
QObject::connect(this, &ClickableWidget::rightClicked, this, onClick);
|
||||
|
||||
this->setSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
void RegionItem::setSelected(bool selected) {
|
||||
void RegionItem::setSelected(bool selected) {
|
||||
this->setProperty("selected", selected);
|
||||
this->style()->unpolish(this);
|
||||
this->style()->polish(this);
|
||||
@@ -71,9 +70,9 @@ void RegionItem::setSelected(bool selected) {
|
||||
if (selected) {
|
||||
emit this->selected(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QStringList RegionItem::getValidationFailures() const {
|
||||
QStringList RegionItem::getValidationFailures() const {
|
||||
auto validationFailures = QStringList();
|
||||
|
||||
if (this->nameInput->text().isEmpty()) {
|
||||
@@ -105,8 +104,9 @@ QStringList RegionItem::getValidationFailures() const {
|
||||
);
|
||||
|
||||
const auto absoluteAddressRange = addressType == MemoryRegionAddressInputType::RELATIVE ?
|
||||
this->convertRelativeToAbsoluteAddressRange(TargetMemoryAddressRange(startAddress, endAddress))
|
||||
: TargetMemoryAddressRange(startAddress, endAddress);
|
||||
this->convertRelativeToAbsoluteAddressRange(
|
||||
TargetMemoryAddressRange(startAddress, endAddress)
|
||||
) : TargetMemoryAddressRange(startAddress, endAddress);
|
||||
|
||||
if (absoluteAddressRange.startAddress < memoryAddressRange.startAddress
|
||||
|| absoluteAddressRange.startAddress > memoryAddressRange.endAddress
|
||||
@@ -125,9 +125,9 @@ QStringList RegionItem::getValidationFailures() const {
|
||||
}
|
||||
|
||||
return validationFailures;
|
||||
}
|
||||
}
|
||||
|
||||
void RegionItem::initFormInputs() {
|
||||
void RegionItem::initFormInputs() {
|
||||
const auto& region = this->getMemoryRegion();
|
||||
|
||||
this->nameInput = this->formWidget->findChild<TextInput*>("name-input");
|
||||
@@ -137,7 +137,9 @@ void RegionItem::initFormInputs() {
|
||||
this->sizeInput = this->formWidget->findChild<TextInput*>("size-input");
|
||||
|
||||
this->nameInput->setText(region.name);
|
||||
this->sizeInput->setText(QString::number((region.addressRange.endAddress - region.addressRange.startAddress) + 1));
|
||||
this->sizeInput->setText(
|
||||
QString::number((region.addressRange.endAddress - region.addressRange.startAddress) + 1)
|
||||
);
|
||||
|
||||
for (const auto& [optionName, option] : RegionItem::addressRangeTypeOptionsByName) {
|
||||
this->addressTypeInput->addItem(option.text, optionName);
|
||||
@@ -147,50 +149,58 @@ void RegionItem::initFormInputs() {
|
||||
auto relativeAddressRange = this->convertAbsoluteToRelativeAddressRange(region.addressRange);
|
||||
this->addressTypeInput->setCurrentText(RegionItem::addressRangeTypeOptionsByName.at("relative").text);
|
||||
|
||||
this->startAddressInput->setText("0x" + QString::number(relativeAddressRange.startAddress, 16).toUpper());
|
||||
this->endAddressInput->setText("0x" + QString::number(relativeAddressRange.endAddress, 16).toUpper());
|
||||
this->startAddressInput->setText(
|
||||
"0x" + QString::number(relativeAddressRange.startAddress, 16).toUpper()
|
||||
);
|
||||
this->endAddressInput->setText(
|
||||
"0x" + QString::number(relativeAddressRange.endAddress, 16).toUpper()
|
||||
);
|
||||
|
||||
} else {
|
||||
this->addressTypeInput->setCurrentText(RegionItem::addressRangeTypeOptionsByName.at("absolute").text);
|
||||
|
||||
this->startAddressInput->setText("0x" + QString::number(region.addressRange.startAddress, 16).toUpper());
|
||||
this->endAddressInput->setText("0x" + QString::number(region.addressRange.endAddress, 16).toUpper());
|
||||
this->startAddressInput->setText(
|
||||
"0x" + QString::number(region.addressRange.startAddress, 16).toUpper()
|
||||
);
|
||||
this->endAddressInput->setText(
|
||||
"0x" + QString::number(region.addressRange.endAddress, 16).toUpper()
|
||||
);
|
||||
}
|
||||
|
||||
QObject::connect(this->startAddressInput, &QLineEdit::textEdited, this, &RegionItem::onAddressRangeInputChange);
|
||||
QObject::connect(this->endAddressInput, &QLineEdit::textEdited, this, &RegionItem::onAddressRangeInputChange);
|
||||
QObject::connect(this->sizeInput, &QLineEdit::textEdited, this, &RegionItem::onSizeInputChange);
|
||||
QObject::connect(this->nameInput, &QLineEdit::textEdited, this, &RegionItem::onNameInputChange);
|
||||
}
|
||||
}
|
||||
|
||||
MemoryRegionAddressInputType RegionItem::getSelectedAddressInputType() const {
|
||||
MemoryRegionAddressInputType RegionItem::getSelectedAddressInputType() const {
|
||||
auto selectedAddressTypeOptionName = this->addressTypeInput->currentData().toString();
|
||||
if (RegionItem::addressRangeTypeOptionsByName.contains(selectedAddressTypeOptionName)) {
|
||||
return RegionItem::addressRangeTypeOptionsByName.at(selectedAddressTypeOptionName).addressType;
|
||||
}
|
||||
|
||||
return MemoryRegionAddressInputType::ABSOLUTE;
|
||||
}
|
||||
}
|
||||
|
||||
TargetMemoryAddressRange RegionItem::convertAbsoluteToRelativeAddressRange(
|
||||
TargetMemoryAddressRange RegionItem::convertAbsoluteToRelativeAddressRange(
|
||||
const TargetMemoryAddressRange& absoluteAddressRange
|
||||
) const {
|
||||
) const {
|
||||
return TargetMemoryAddressRange(
|
||||
absoluteAddressRange.startAddress - this->memoryDescriptor.addressRange.startAddress,
|
||||
absoluteAddressRange.endAddress - this->memoryDescriptor.addressRange.startAddress
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TargetMemoryAddressRange RegionItem::convertRelativeToAbsoluteAddressRange(
|
||||
TargetMemoryAddressRange RegionItem::convertRelativeToAbsoluteAddressRange(
|
||||
const TargetMemoryAddressRange& relativeAddressRange
|
||||
) const {
|
||||
) const {
|
||||
return TargetMemoryAddressRange(
|
||||
relativeAddressRange.startAddress + this->memoryDescriptor.addressRange.startAddress,
|
||||
relativeAddressRange.endAddress + this->memoryDescriptor.addressRange.startAddress
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void RegionItem::onAddressRangeInputChange() {
|
||||
void RegionItem::onAddressRangeInputChange() {
|
||||
bool startAddressConversionOk = false;
|
||||
bool endAddressConversionOk = false;
|
||||
std::uint32_t startAddress = this->startAddressInput->text().toUInt(&startAddressConversionOk, 16);
|
||||
@@ -199,9 +209,9 @@ void RegionItem::onAddressRangeInputChange() {
|
||||
if (startAddressConversionOk && endAddressConversionOk && startAddress <= endAddress) {
|
||||
this->sizeInput->setText(QString::number((endAddress - startAddress) + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegionItem::onSizeInputChange() {
|
||||
void RegionItem::onSizeInputChange() {
|
||||
bool startAddressConversionOk = false;
|
||||
bool sizeConversionOk = false;
|
||||
std::uint32_t startAddress = this->startAddressInput->text().toUInt(&startAddressConversionOk, 16);
|
||||
@@ -210,10 +220,11 @@ void RegionItem::onSizeInputChange() {
|
||||
if (startAddressConversionOk && sizeConversionOk && size > 0) {
|
||||
this->endAddressInput->setText("0x" + QString::number((startAddress + size) - 1, 16).toUpper());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegionItem::onNameInputChange() {
|
||||
void RegionItem::onNameInputChange() {
|
||||
auto newName = this->nameInput->text();
|
||||
newName.truncate(RegionItem::NAME_LABEL_MAX_LENGTH);
|
||||
this->nameLabel->setText(newName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
#include <QScrollArea>
|
||||
#include <QMargins>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
BitBodyWidget::BitBodyWidget(
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
BitBodyWidget::BitBodyWidget(
|
||||
int bitIndex,
|
||||
std::bitset<std::numeric_limits<unsigned char>::digits>::reference bit,
|
||||
bool readOnly,
|
||||
QWidget* parent
|
||||
): ClickableWidget(parent), bitIndex(bitIndex), bit(bit), readOnly(readOnly) {
|
||||
): ClickableWidget(parent), bitIndex(bitIndex), bit(bit), readOnly(readOnly) {
|
||||
this->setFixedSize(BitBodyWidget::WIDTH, BitBodyWidget::HEIGHT);
|
||||
this->setContentsMargins(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool BitBodyWidget::event(QEvent* event) {
|
||||
bool BitBodyWidget::event(QEvent* event) {
|
||||
if (this->isEnabled() && !this->readOnly) {
|
||||
switch (event->type()) {
|
||||
case QEvent::Enter: {
|
||||
@@ -36,9 +36,9 @@ bool BitBodyWidget::event(QEvent* event) {
|
||||
}
|
||||
|
||||
return QWidget::event(event);
|
||||
}
|
||||
}
|
||||
|
||||
void BitBodyWidget::mouseReleaseEvent(QMouseEvent* event) {
|
||||
void BitBodyWidget::mouseReleaseEvent(QMouseEvent* event) {
|
||||
if (this->isEnabled()) {
|
||||
if (!this->readOnly && event->button() == Qt::MouseButton::LeftButton) {
|
||||
this->bit = !this->bit;
|
||||
@@ -47,15 +47,18 @@ void BitBodyWidget::mouseReleaseEvent(QMouseEvent* event) {
|
||||
|
||||
ClickableWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BitBodyWidget::paintEvent(QPaintEvent* event) {
|
||||
void BitBodyWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter(this);
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
}
|
||||
|
||||
void BitBodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform, true);
|
||||
void BitBodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(
|
||||
QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform,
|
||||
true
|
||||
);
|
||||
|
||||
auto bodyColor = QColor(this->bit == true ? "#7B5E38" : "#908D85");
|
||||
|
||||
@@ -75,4 +78,5 @@ void BitBodyWidget::drawWidget(QPainter& painter) {
|
||||
BitBodyWidget::WIDTH,
|
||||
BitBodyWidget::HEIGHT
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
|
||||
#include "BitBodyWidget.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
BitWidget::BitWidget(
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
BitWidget::BitWidget(
|
||||
int bitIndex,
|
||||
int bitNumber,
|
||||
std::bitset<std::numeric_limits<unsigned char>::digits>& bitset,
|
||||
bool readOnly,
|
||||
QWidget* parent
|
||||
): QWidget(parent), bitIndex(bitIndex), bitNumber(bitNumber), bitset(bitset), readOnly(readOnly) {
|
||||
): QWidget(parent), bitIndex(bitIndex), bitNumber(bitNumber), bitset(bitset), readOnly(readOnly) {
|
||||
this->setFixedSize(BitWidget::WIDTH, BitWidget::HEIGHT);
|
||||
|
||||
auto* layout = new QVBoxLayout(this);
|
||||
@@ -52,4 +52,5 @@ BitWidget::BitWidget(
|
||||
emit this->bitChanged();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
#include "../TargetRegisterInspectorWindow.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
BitsetWidget::BitsetWidget(int byteNumber, unsigned char& byte, bool readOnly, QWidget* parent):
|
||||
QWidget(parent), byteNumber(byteNumber), byte(byte), readOnly(readOnly) {
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
BitsetWidget::BitsetWidget(int byteNumber, unsigned char& byte, bool readOnly, QWidget* parent)
|
||||
: QWidget(parent), byteNumber(byteNumber), byte(byte), readOnly(readOnly) {
|
||||
this->setObjectName("bitset-widget");
|
||||
auto* bitLayout = new QHBoxLayout(this);
|
||||
bitLayout->setSpacing(BitWidget::SPACING);
|
||||
@@ -43,20 +43,20 @@ QWidget(parent), byteNumber(byteNumber), byte(byte), readOnly(readOnly) {
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BitsetWidget::updateValue() {
|
||||
void BitsetWidget::updateValue() {
|
||||
this->bitset = {this->byte};
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void BitsetWidget::paintEvent(QPaintEvent* event) {
|
||||
void BitsetWidget::paintEvent(QPaintEvent* event) {
|
||||
QWidget::paintEvent(event);
|
||||
auto painter = QPainter(this);
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
}
|
||||
|
||||
void BitsetWidget::drawWidget(QPainter& painter) {
|
||||
void BitsetWidget::drawWidget(QPainter& painter) {
|
||||
auto byteHex = "0x" + QString::number(this->byte, 16).toUpper();
|
||||
|
||||
painter.setPen(QColor("#474747"));
|
||||
@@ -105,4 +105,5 @@ void BitsetWidget::drawWidget(QPainter& painter) {
|
||||
Qt::AlignCenter,
|
||||
byteHex
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
#include <QStyle>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
CurrentItem::CurrentItem(
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
CurrentItem::CurrentItem(
|
||||
const Targets::TargetMemoryBuffer& registerValue,
|
||||
QWidget* parent
|
||||
): Item(registerValue, parent) {
|
||||
): Item(registerValue, parent) {
|
||||
this->setObjectName("current-item");
|
||||
this->setFixedHeight(30);
|
||||
this->titleLabel->setText("Current value");
|
||||
this->layout->addWidget(titleLabel, 0, Qt::AlignmentFlag::AlignLeft);
|
||||
this->layout->setContentsMargins(5, 0, 5, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
#include <QStyle>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
Item::Item(const Targets::TargetMemoryBuffer& registerValue, QWidget* parent):
|
||||
ClickableWidget(parent), registerValue(registerValue) {
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
Item::Item(const Targets::TargetMemoryBuffer& registerValue, QWidget* parent)
|
||||
: ClickableWidget(parent), registerValue(registerValue) {
|
||||
auto onClick = [this] {
|
||||
this->setSelected(true);
|
||||
};
|
||||
@@ -14,9 +14,9 @@ ClickableWidget(parent), registerValue(registerValue) {
|
||||
QObject::connect(this, &ClickableWidget::rightClicked, this, onClick);
|
||||
|
||||
this->setSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Item::setSelected(bool selected) {
|
||||
void Item::setSelected(bool selected) {
|
||||
this->setProperty("selected", selected);
|
||||
this->style()->unpolish(this);
|
||||
this->style()->polish(this);
|
||||
@@ -24,4 +24,5 @@ void Item::setSelected(bool selected) {
|
||||
if (selected) {
|
||||
emit this->selected(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QByteArray>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
RegisterHistoryItem::RegisterHistoryItem(
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
RegisterHistoryItem::RegisterHistoryItem(
|
||||
const Targets::TargetMemoryBuffer& registerValue,
|
||||
const QDateTime& changeDate,
|
||||
QWidget* parent
|
||||
): Item(registerValue, parent) {
|
||||
): Item(registerValue, parent) {
|
||||
this->setObjectName("register-history-item");
|
||||
this->setFixedHeight(50);
|
||||
this->layout->setContentsMargins(5, 8, 5, 0);
|
||||
@@ -38,4 +38,5 @@ RegisterHistoryItem::RegisterHistoryItem(
|
||||
this->layout->addWidget(this->dateLabel, 0, Qt::AlignmentFlag::AlignTop);
|
||||
this->layout->addLayout(subLabelLayout);
|
||||
this->layout->addStretch(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,19 +12,20 @@
|
||||
#include "src/Helpers/DateTime.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptors;
|
||||
using Bloom::Targets::TargetRegisterType;
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptors;
|
||||
using Bloom::Targets::TargetRegisterType;
|
||||
|
||||
RegisterHistoryWidget::RegisterHistoryWidget(
|
||||
RegisterHistoryWidget::RegisterHistoryWidget(
|
||||
const Targets::TargetRegisterDescriptor& registerDescriptor,
|
||||
const Targets::TargetMemoryBuffer& currentValue,
|
||||
InsightWorker& insightWorker,
|
||||
QWidget* parent
|
||||
): QWidget(parent), registerDescriptor(registerDescriptor), insightWorker(insightWorker) {
|
||||
): QWidget(parent), registerDescriptor(registerDescriptor), insightWorker(insightWorker) {
|
||||
this->setObjectName("target-register-history-widget");
|
||||
this->setFixedWidth(300);
|
||||
|
||||
@@ -82,39 +83,39 @@ RegisterHistoryWidget::RegisterHistoryWidget(
|
||||
this->itemContainerLayout->addWidget(separatorWidget);
|
||||
|
||||
this->show();
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterHistoryWidget::updateCurrentItemValue(const Targets::TargetMemoryBuffer& registerValue) {
|
||||
void RegisterHistoryWidget::updateCurrentItemValue(const Targets::TargetMemoryBuffer& registerValue) {
|
||||
this->currentItem->registerValue = registerValue;
|
||||
|
||||
if (this->selectedItemWidget != nullptr && this->currentItem == this->selectedItemWidget) {
|
||||
this->selectCurrentItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterHistoryWidget::selectCurrentItem() {
|
||||
void RegisterHistoryWidget::selectCurrentItem() {
|
||||
this->currentItem->setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterHistoryWidget::addItem(const Targets::TargetMemoryBuffer& registerValue, const QDateTime& changeDate) {
|
||||
void RegisterHistoryWidget::addItem(const Targets::TargetMemoryBuffer& registerValue, const QDateTime& changeDate) {
|
||||
auto* item = new RegisterHistoryItem(registerValue, changeDate, this->itemContainer);
|
||||
QObject::connect(item, &Item::selected, this, &RegisterHistoryWidget::onItemSelectionChange);
|
||||
this->itemContainerLayout->insertWidget(2, item);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterHistoryWidget::resizeEvent(QResizeEvent* event) {
|
||||
void RegisterHistoryWidget::resizeEvent(QResizeEvent* event) {
|
||||
this->container->setFixedSize(
|
||||
this->width(),
|
||||
this->height()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterHistoryWidget::onTargetStateChanged(Targets::TargetState newState) {
|
||||
void RegisterHistoryWidget::onTargetStateChanged(Targets::TargetState newState) {
|
||||
using Targets::TargetState;
|
||||
this->targetState = newState;
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterHistoryWidget::onItemSelectionChange(Item* newlySelectedWidget) {
|
||||
void RegisterHistoryWidget::onItemSelectionChange(Item* newlySelectedWidget) {
|
||||
if (this->selectedItemWidget != newlySelectedWidget) {
|
||||
if (this->selectedItemWidget != nullptr) {
|
||||
this->selectedItemWidget->setSelected(false);
|
||||
@@ -124,13 +125,17 @@ void RegisterHistoryWidget::onItemSelectionChange(Item* newlySelectedWidget) {
|
||||
}
|
||||
|
||||
emit this->historyItemSelected(newlySelectedWidget->registerValue);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterHistoryWidget::onRegistersWritten(Targets::TargetRegisters targetRegisters, const QDateTime& changeDate) {
|
||||
void RegisterHistoryWidget::onRegistersWritten(
|
||||
Targets::TargetRegisters targetRegisters,
|
||||
const QDateTime& changeDate
|
||||
) {
|
||||
for (const auto& targetRegister : targetRegisters) {
|
||||
if (targetRegister.descriptor == this->registerDescriptor) {
|
||||
this->addItem(targetRegister.value, changeDate);
|
||||
this->updateCurrentItemValue(targetRegister.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,26 +14,26 @@
|
||||
#include "src/Insight/InsightWorker/Tasks/ReadTargetRegisters.hpp"
|
||||
#include "src/Insight/InsightWorker/Tasks/WriteTargetRegister.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
using Bloom::Exceptions::Exception;
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptors;
|
||||
using Bloom::Targets::TargetRegisterType;
|
||||
using Bloom::Targets::TargetState;
|
||||
|
||||
using Bloom::Exceptions::Exception;
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptors;
|
||||
using Bloom::Targets::TargetRegisterType;
|
||||
using Bloom::Targets::TargetState;
|
||||
|
||||
TargetRegisterInspectorWindow::TargetRegisterInspectorWindow(
|
||||
TargetRegisterInspectorWindow::TargetRegisterInspectorWindow(
|
||||
const Targets::TargetRegisterDescriptor& registerDescriptor,
|
||||
InsightWorker& insightWorker,
|
||||
TargetState currentTargetState,
|
||||
std::optional<Targets::TargetMemoryBuffer> registerValue,
|
||||
const std::optional<Targets::TargetMemoryBuffer>& registerValue,
|
||||
QWidget* parent
|
||||
):
|
||||
QWidget(parent),
|
||||
registerDescriptor(registerDescriptor),
|
||||
insightWorker(insightWorker),
|
||||
registerValue(registerValue.value_or(Targets::TargetMemoryBuffer(registerDescriptor.size, 0)))
|
||||
{
|
||||
)
|
||||
: QWidget(parent)
|
||||
, registerDescriptor(registerDescriptor)
|
||||
, insightWorker(insightWorker)
|
||||
, registerValue(registerValue.value_or(Targets::TargetMemoryBuffer(registerDescriptor.size, 0)))
|
||||
{
|
||||
this->setWindowFlag(Qt::Window);
|
||||
auto registerName = QString::fromStdString(this->registerDescriptor.name.value()).toUpper();
|
||||
this->setObjectName("target-register-inspector-window");
|
||||
@@ -41,13 +41,15 @@ TargetRegisterInspectorWindow::TargetRegisterInspectorWindow(
|
||||
|
||||
auto windowUiFile = QFile(
|
||||
QString::fromStdString(Paths::compiledResourcesPath()
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegisterInspector/UiFiles/TargetRegisterInspectorWindow.ui"
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegisterInspector/UiFiles/"
|
||||
"TargetRegisterInspectorWindow.ui"
|
||||
)
|
||||
);
|
||||
|
||||
auto windowStylesheet = QFile(
|
||||
QString::fromStdString(Paths::compiledResourcesPath()
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegisterInspector/Stylesheets/TargetRegisterInspectorWindow.qss"
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegisterInspector/Stylesheets/"
|
||||
"TargetRegisterInspectorWindow.qss"
|
||||
)
|
||||
);
|
||||
|
||||
@@ -83,7 +85,9 @@ TargetRegisterInspectorWindow::TargetRegisterInspectorWindow(
|
||||
this->contentContainer = this->container->findChild<QWidget*>("content-container");
|
||||
this->registerValueContainer = this->container->findChild<QWidget*>("register-value-container");
|
||||
this->registerValueTextInput = this->container->findChild<QLineEdit*>("register-value-text-input");
|
||||
this->registerValueBitsetWidgetContainer = this->container->findChild<QWidget*>("register-value-bitset-widget-container");
|
||||
this->registerValueBitsetWidgetContainer = this->container->findChild<QWidget*>(
|
||||
"register-value-bitset-widget-container"
|
||||
);
|
||||
this->refreshValueButton = this->container->findChild<QPushButton*>("refresh-value-btn");
|
||||
this->applyButton = this->container->findChild<QPushButton*>("apply-btn");
|
||||
this->helpButton = this->container->findChild<QPushButton*>("help-btn");
|
||||
@@ -92,7 +96,9 @@ TargetRegisterInspectorWindow::TargetRegisterInspectorWindow(
|
||||
this->registerNameLabel->setText(registerName);
|
||||
|
||||
if (this->registerDescriptor.description.has_value()) {
|
||||
this->registerDescriptionLabel->setText(QString::fromStdString(this->registerDescriptor.description.value()));
|
||||
this->registerDescriptionLabel->setText(
|
||||
QString::fromStdString(this->registerDescriptor.description.value())
|
||||
);
|
||||
this->registerDescriptionLabel->setVisible(true);
|
||||
}
|
||||
|
||||
@@ -111,8 +117,12 @@ TargetRegisterInspectorWindow::TargetRegisterInspectorWindow(
|
||||
registerValueContainer->setContentsMargins(15, 15, 15, 15);
|
||||
registerDetailsContainer->setContentsMargins(15, 15, 15, 15);
|
||||
|
||||
auto* registerDetailsNameInput = registerDetailsContainer->findChild<QLineEdit*>("register-details-name-input");
|
||||
auto* registerDetailsSizeInput = registerDetailsContainer->findChild<QLineEdit*>("register-details-size-input");
|
||||
auto* registerDetailsNameInput = registerDetailsContainer->findChild<QLineEdit*>(
|
||||
"register-details-name-input"
|
||||
);
|
||||
auto* registerDetailsSizeInput = registerDetailsContainer->findChild<QLineEdit*>(
|
||||
"register-details-size-input"
|
||||
);
|
||||
auto* registerDetailsStartAddressInput = registerDetailsContainer->findChild<QLineEdit*>(
|
||||
"register-details-start-address-input"
|
||||
);
|
||||
@@ -128,7 +138,9 @@ TargetRegisterInspectorWindow::TargetRegisterInspectorWindow(
|
||||
this->registerValueTextInput->setDisabled(true);
|
||||
this->applyButton->setVisible(false);
|
||||
|
||||
auto* readOnlyIndicatorLabel = this->registerValueContainer->findChild<QLabel*>("read-only-indicator-label");
|
||||
auto* readOnlyIndicatorLabel = this->registerValueContainer->findChild<QLabel*>(
|
||||
"read-only-indicator-label"
|
||||
);
|
||||
readOnlyIndicatorLabel->show();
|
||||
}
|
||||
|
||||
@@ -216,19 +228,19 @@ TargetRegisterInspectorWindow::TargetRegisterInspectorWindow(
|
||||
this->move(parent->window()->geometry().center() - this->rect().center());
|
||||
|
||||
this->show();
|
||||
}
|
||||
}
|
||||
|
||||
bool TargetRegisterInspectorWindow::registerSupported(const Targets::TargetRegisterDescriptor& descriptor) {
|
||||
bool TargetRegisterInspectorWindow::registerSupported(const Targets::TargetRegisterDescriptor& descriptor) {
|
||||
return (descriptor.size > 0 && descriptor.size <= 8);
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegisterInspectorWindow::setValue(const Targets::TargetMemoryBuffer& registerValue) {
|
||||
void TargetRegisterInspectorWindow::setValue(const Targets::TargetMemoryBuffer& registerValue) {
|
||||
this->registerValue = registerValue;
|
||||
this->registerHistoryWidget->updateCurrentItemValue(this->registerValue);
|
||||
this->registerHistoryWidget->selectCurrentItem();
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegisterInspectorWindow::onValueTextInputChanged(QString text) {
|
||||
void TargetRegisterInspectorWindow::onValueTextInputChanged(QString text) {
|
||||
if (text.isEmpty()) {
|
||||
text = "0";
|
||||
}
|
||||
@@ -253,9 +265,9 @@ void TargetRegisterInspectorWindow::onValueTextInputChanged(QString text) {
|
||||
for (auto& bitsetWidget : this->bitsetWidgets) {
|
||||
bitsetWidget->updateValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegisterInspectorWindow::onTargetStateChanged(TargetState newState) {
|
||||
void TargetRegisterInspectorWindow::onTargetStateChanged(TargetState newState) {
|
||||
if (newState != TargetState::STOPPED) {
|
||||
this->registerValueTextInput->setDisabled(true);
|
||||
this->registerValueBitsetWidgetContainer->setDisabled(true);
|
||||
@@ -273,9 +285,11 @@ void TargetRegisterInspectorWindow::onTargetStateChanged(TargetState newState) {
|
||||
}
|
||||
|
||||
this->targetState = newState;
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegisterInspectorWindow::onHistoryItemSelected(const Targets::TargetMemoryBuffer& selectedRegisterValue) {
|
||||
void TargetRegisterInspectorWindow::onHistoryItemSelected(
|
||||
const Targets::TargetMemoryBuffer& selectedRegisterValue
|
||||
) {
|
||||
this->registerValue = selectedRegisterValue;
|
||||
this->updateValue();
|
||||
|
||||
@@ -285,29 +299,29 @@ void TargetRegisterInspectorWindow::onHistoryItemSelected(const Targets::TargetM
|
||||
} else {
|
||||
this->refreshValueButton->setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegisterInspectorWindow::updateRegisterValueInputField() {
|
||||
void TargetRegisterInspectorWindow::updateRegisterValueInputField() {
|
||||
auto value = QByteArray(
|
||||
reinterpret_cast<const char*>(this->registerValue.data()),
|
||||
static_cast<qsizetype>(this->registerValue.size())
|
||||
);
|
||||
|
||||
this->registerValueTextInput->setText("0x" + QString(value.toHex()).toUpper());
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegisterInspectorWindow::updateRegisterValueBitsetWidgets() {
|
||||
void TargetRegisterInspectorWindow::updateRegisterValueBitsetWidgets() {
|
||||
for (auto& bitsetWidget : this->bitsetWidgets) {
|
||||
bitsetWidget->updateValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegisterInspectorWindow::updateValue() {
|
||||
void TargetRegisterInspectorWindow::updateValue() {
|
||||
this->updateRegisterValueInputField();
|
||||
this->updateRegisterValueBitsetWidgets();
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegisterInspectorWindow::refreshRegisterValue() {
|
||||
void TargetRegisterInspectorWindow::refreshRegisterValue() {
|
||||
this->registerValueContainer->setDisabled(true);
|
||||
auto* readTargetRegisterTask = new ReadTargetRegisters({this->registerDescriptor});
|
||||
|
||||
@@ -336,11 +350,14 @@ void TargetRegisterInspectorWindow::refreshRegisterValue() {
|
||||
);
|
||||
|
||||
this->insightWorker.queueTask(readTargetRegisterTask);
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegisterInspectorWindow::applyChanges() {
|
||||
void TargetRegisterInspectorWindow::applyChanges() {
|
||||
this->registerValueContainer->setDisabled(true);
|
||||
const auto targetRegister = Targets::TargetRegister(this->registerDescriptor, this->registerValue);
|
||||
const auto targetRegister = Targets::TargetRegister(
|
||||
this->registerDescriptor,
|
||||
this->registerValue
|
||||
);
|
||||
auto* writeRegisterTask = new WriteTargetRegister(targetRegister);
|
||||
|
||||
QObject::connect(writeRegisterTask, &InsightWorkerTask::completed, this, [this, targetRegister] {
|
||||
@@ -366,8 +383,11 @@ void TargetRegisterInspectorWindow::applyChanges() {
|
||||
});
|
||||
|
||||
this->insightWorker.queueTask(writeRegisterTask);
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegisterInspectorWindow::openHelpPage() {
|
||||
QDesktopServices::openUrl(QUrl(QString::fromStdString(Paths::homeDomainName() + "/docs/register-inspection")));
|
||||
void TargetRegisterInspectorWindow::openHelpPage() {
|
||||
QDesktopServices::openUrl(
|
||||
QUrl(QString::fromStdString(Paths::homeDomainName() + "/docs/register-inspection"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Bloom::Widgets
|
||||
const Targets::TargetRegisterDescriptor& registerDescriptor,
|
||||
InsightWorker& insightWorker,
|
||||
Targets::TargetState currentTargetState,
|
||||
std::optional<Targets::TargetMemoryBuffer> registerValue = std::nullopt,
|
||||
const std::optional<Targets::TargetMemoryBuffer>& registerValue = std::nullopt,
|
||||
QWidget* parent = nullptr
|
||||
);
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#include <QStyle>
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
ItemWidget::ItemWidget(QWidget* parent): ClickableWidget(parent) {
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
ItemWidget::ItemWidget(QWidget* parent): ClickableWidget(parent) {
|
||||
auto onClick = [this] {
|
||||
this->setSelected(true);
|
||||
};
|
||||
@@ -13,9 +13,9 @@ ItemWidget::ItemWidget(QWidget* parent): ClickableWidget(parent) {
|
||||
QObject::connect(this, &ClickableWidget::rightClicked, this, onClick);
|
||||
|
||||
this->setSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemWidget::setSelected(bool selected) {
|
||||
void ItemWidget::setSelected(bool selected) {
|
||||
this->setProperty("selected", selected);
|
||||
this->style()->unpolish(this);
|
||||
this->style()->polish(this);
|
||||
@@ -25,4 +25,5 @@ void ItemWidget::setSelected(bool selected) {
|
||||
}
|
||||
|
||||
this->postSetSelected(selected);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,17 +8,18 @@
|
||||
|
||||
#include "src/Helpers/Paths.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
|
||||
RegisterGroupWidget::RegisterGroupWidget(
|
||||
RegisterGroupWidget::RegisterGroupWidget(
|
||||
QString name,
|
||||
const std::set<TargetRegisterDescriptor>& registerDescriptors,
|
||||
InsightWorker& insightWorker,
|
||||
TargetRegistersPaneWidget* parent
|
||||
): ItemWidget(parent), name(std::move(name)) {
|
||||
): ItemWidget(parent), name(std::move(name)) {
|
||||
this->setObjectName(this->name);
|
||||
|
||||
this->headerWidget->setObjectName("register-group-header");
|
||||
@@ -102,27 +103,27 @@ RegisterGroupWidget::RegisterGroupWidget(
|
||||
parent,
|
||||
&TargetRegistersPaneWidget::onItemSelectionChange
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterGroupWidget::collapse() {
|
||||
void RegisterGroupWidget::collapse() {
|
||||
this->arrowIcon->setAngle(0);
|
||||
this->bodyWidget->setVisible(false);
|
||||
this->collapsed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterGroupWidget::expand() {
|
||||
void RegisterGroupWidget::expand() {
|
||||
this->arrowIcon->setAngle(90);
|
||||
this->bodyWidget->setVisible(true);
|
||||
this->collapsed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterGroupWidget::setAllRegistersVisible(bool visible) {
|
||||
void RegisterGroupWidget::setAllRegistersVisible(bool visible) {
|
||||
for (const auto& registerWidget : this->registerWidgets) {
|
||||
registerWidget->setVisible(visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterGroupWidget::filterRegisters(const QString& keyword) {
|
||||
void RegisterGroupWidget::filterRegisters(const QString& keyword) {
|
||||
int matchingWidgetCount = 0;
|
||||
for (const auto& registerWidget : this->registerWidgets) {
|
||||
if (keyword.isEmpty() || (registerWidget->searchKeywords.contains(keyword, Qt::CaseInsensitive))) {
|
||||
@@ -147,4 +148,5 @@ void RegisterGroupWidget::filterRegisters(const QString& keyword) {
|
||||
this->collapse();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,23 +9,24 @@
|
||||
|
||||
#include "src/Insight/InsightWorker/Tasks/ReadTargetRegisters.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
|
||||
RegisterWidget::RegisterWidget(
|
||||
RegisterWidget::RegisterWidget(
|
||||
TargetRegisterDescriptor descriptor,
|
||||
InsightWorker& insightWorker,
|
||||
QWidget *parent
|
||||
)
|
||||
)
|
||||
: ItemWidget(parent)
|
||||
, descriptor(std::move(descriptor))
|
||||
, searchKeywords(QString::fromStdString(
|
||||
this->descriptor.name.value_or("") + this->descriptor.description.value_or("")
|
||||
).toLower())
|
||||
, insightWorker(insightWorker)
|
||||
{
|
||||
{
|
||||
this->setObjectName("register-item");
|
||||
this->setFixedHeight(25);
|
||||
|
||||
@@ -64,9 +65,9 @@ RegisterWidget::RegisterWidget(
|
||||
this,
|
||||
&RegisterWidget::onTargetStateChange
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterWidget::setRegisterValue(const Targets::TargetRegister& targetRegister) {
|
||||
void RegisterWidget::setRegisterValue(const Targets::TargetRegister& targetRegister) {
|
||||
const auto valueChanged = this->currentRegister.has_value()
|
||||
&& this->currentRegister.value().value != targetRegister.value;
|
||||
this->currentRegister = targetRegister;
|
||||
@@ -93,13 +94,13 @@ void RegisterWidget::setRegisterValue(const Targets::TargetRegister& targetRegis
|
||||
if (this->inspectWindow != nullptr) {
|
||||
this->inspectWindow->setValue(targetRegister.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterWidget::clearInlineValue() {
|
||||
void RegisterWidget::clearInlineValue() {
|
||||
this->valueLabel->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterWidget::contextMenuEvent(QContextMenuEvent* event) {
|
||||
void RegisterWidget::contextMenuEvent(QContextMenuEvent* event) {
|
||||
this->setSelected(true);
|
||||
|
||||
auto* menu = new QMenu(this);
|
||||
@@ -126,9 +127,9 @@ void RegisterWidget::contextMenuEvent(QContextMenuEvent* event) {
|
||||
this->copyValueBinaryAction->setEnabled(targetStoppedAndValuePresent);
|
||||
|
||||
menu->exec(event->globalPos());
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterWidget::openInspectionWindow() {
|
||||
void RegisterWidget::openInspectionWindow() {
|
||||
if (!TargetRegisterInspectorWindow::registerSupported(this->descriptor)) {
|
||||
return;
|
||||
}
|
||||
@@ -138,7 +139,8 @@ void RegisterWidget::openInspectionWindow() {
|
||||
this->descriptor,
|
||||
this->insightWorker,
|
||||
this->targetState,
|
||||
this->currentRegister.has_value() ? std::optional(this->currentRegister->value) : std::nullopt,
|
||||
this->currentRegister.has_value() ? std::optional(this->currentRegister->value)
|
||||
: std::nullopt,
|
||||
this
|
||||
);
|
||||
|
||||
@@ -154,9 +156,9 @@ void RegisterWidget::openInspectionWindow() {
|
||||
this->inspectWindow->activateWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterWidget::refreshValue() {
|
||||
void RegisterWidget::refreshValue() {
|
||||
auto* readRegisterTask = new ReadTargetRegisters({this->descriptor});
|
||||
|
||||
QObject::connect(
|
||||
@@ -173,15 +175,15 @@ void RegisterWidget::refreshValue() {
|
||||
);
|
||||
|
||||
this->insightWorker.queueTask(readRegisterTask);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterWidget::copyName() {
|
||||
void RegisterWidget::copyName() {
|
||||
if (this->nameLabel != nullptr) {
|
||||
QApplication::clipboard()->setText(this->nameLabel->text());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterWidget::copyValueHex() {
|
||||
void RegisterWidget::copyValueHex() {
|
||||
if (this->currentRegister.has_value()) {
|
||||
auto valueByteArray = QByteArray(
|
||||
reinterpret_cast<const char*>(this->currentRegister.value().value.data()),
|
||||
@@ -189,9 +191,9 @@ void RegisterWidget::copyValueHex() {
|
||||
).toHex();
|
||||
QApplication::clipboard()->setText(QString(valueByteArray).toUpper());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterWidget::copyValueDecimal() {
|
||||
void RegisterWidget::copyValueDecimal() {
|
||||
if (this->currentRegister.has_value()) {
|
||||
auto valueByteArray = QByteArray(
|
||||
reinterpret_cast<const char*>(this->currentRegister.value().value.data()),
|
||||
@@ -199,9 +201,9 @@ void RegisterWidget::copyValueDecimal() {
|
||||
).toHex();
|
||||
QApplication::clipboard()->setText(QString::number(valueByteArray.toUInt(nullptr, 16)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterWidget::copyValueBinary() {
|
||||
void RegisterWidget::copyValueBinary() {
|
||||
if (this->currentRegister.has_value()) {
|
||||
const auto registerValueSize = static_cast<qsizetype>(this->currentRegister.value().size());
|
||||
auto valueByteArray = QByteArray(
|
||||
@@ -217,18 +219,19 @@ void RegisterWidget::copyValueBinary() {
|
||||
|
||||
QApplication::clipboard()->setText(bitString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterWidget::postSetSelected(bool selected) {
|
||||
void RegisterWidget::postSetSelected(bool selected) {
|
||||
auto valueLabelStyle = this->valueLabel->style();
|
||||
valueLabelStyle->unpolish(this->valueLabel);
|
||||
valueLabelStyle->polish(this->valueLabel);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterWidget::onTargetStateChange(Targets::TargetState newState) {
|
||||
void RegisterWidget::onTargetStateChange(Targets::TargetState newState) {
|
||||
this->targetState = newState;
|
||||
|
||||
if (this->targetState == Targets::TargetState::RUNNING) {
|
||||
this->clearInlineValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,24 +12,26 @@
|
||||
|
||||
#include "src/Insight/InsightWorker/Tasks/ReadTargetRegisters.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
using Bloom::Targets::TargetDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptors;
|
||||
using Bloom::Targets::TargetRegisterType;
|
||||
using Bloom::Targets::TargetDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptor;
|
||||
using Bloom::Targets::TargetRegisterDescriptors;
|
||||
using Bloom::Targets::TargetRegisterType;
|
||||
|
||||
TargetRegistersPaneWidget::TargetRegistersPaneWidget(
|
||||
TargetRegistersPaneWidget::TargetRegistersPaneWidget(
|
||||
const TargetDescriptor& targetDescriptor,
|
||||
InsightWorker& insightWorker,
|
||||
PanelWidget* parent
|
||||
): QWidget(parent), parent(parent), targetDescriptor(targetDescriptor), insightWorker(insightWorker) {
|
||||
): QWidget(parent), parent(parent), targetDescriptor(targetDescriptor), insightWorker(insightWorker) {
|
||||
this->setObjectName("target-registers-side-pane");
|
||||
|
||||
auto targetRegistersPaneUiFile = QFile(
|
||||
QString::fromStdString(Paths::compiledResourcesPath()
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegistersPane/UiFiles/TargetRegistersSidePane.ui"
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegistersPane/UiFiles/"
|
||||
"TargetRegistersSidePane.ui"
|
||||
)
|
||||
);
|
||||
|
||||
@@ -121,9 +123,9 @@ TargetRegistersPaneWidget::TargetRegistersPaneWidget(
|
||||
this,
|
||||
&TargetRegistersPaneWidget::onRegistersRead
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegistersPaneWidget::filterRegisters(const QString& keyword) {
|
||||
void TargetRegistersPaneWidget::filterRegisters(const QString& keyword) {
|
||||
for (const auto& registerGroupWidget : this->registerGroupWidgets) {
|
||||
// If the group name matches the keyword, then don't bother iterating through all the register widgets
|
||||
if (keyword.isEmpty() || registerGroupWidget->name.contains(keyword, Qt::CaseInsensitive)) {
|
||||
@@ -141,21 +143,21 @@ void TargetRegistersPaneWidget::filterRegisters(const QString& keyword) {
|
||||
registerGroupWidget->filterRegisters(keyword);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegistersPaneWidget::collapseAllRegisterGroups() {
|
||||
void TargetRegistersPaneWidget::collapseAllRegisterGroups() {
|
||||
for (const auto& registerGroupWidget : this->registerGroupWidgets) {
|
||||
registerGroupWidget->collapse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegistersPaneWidget::expandAllRegisterGroups() {
|
||||
void TargetRegistersPaneWidget::expandAllRegisterGroups() {
|
||||
for (const auto& registerGroupWidget : this->registerGroupWidgets) {
|
||||
registerGroupWidget->expand();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegistersPaneWidget::refreshRegisterValues(std::optional<std::function<void(void)>> callback) {
|
||||
void TargetRegistersPaneWidget::refreshRegisterValues(std::optional<std::function<void(void)>> callback) {
|
||||
auto& descriptors = this->renderedDescriptors;
|
||||
|
||||
if (descriptors.empty()) {
|
||||
@@ -180,21 +182,21 @@ void TargetRegistersPaneWidget::refreshRegisterValues(std::optional<std::functio
|
||||
}
|
||||
|
||||
this->insightWorker.queueTask(readRegisterTask);
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegistersPaneWidget::activate() {
|
||||
void TargetRegistersPaneWidget::activate() {
|
||||
this->show();
|
||||
this->activated = true;
|
||||
this->postActivate();
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegistersPaneWidget::deactivate() {
|
||||
void TargetRegistersPaneWidget::deactivate() {
|
||||
this->hide();
|
||||
this->activated = false;
|
||||
this->postDeactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegistersPaneWidget::onItemSelectionChange(ItemWidget* newlySelectedWidget) {
|
||||
void TargetRegistersPaneWidget::onItemSelectionChange(ItemWidget* newlySelectedWidget) {
|
||||
// Only one item in the target registers pane can be selected at any given time.
|
||||
if (this->selectedItemWidget != newlySelectedWidget) {
|
||||
if (this->selectedItemWidget != nullptr) {
|
||||
@@ -203,9 +205,9 @@ void TargetRegistersPaneWidget::onItemSelectionChange(ItemWidget* newlySelectedW
|
||||
|
||||
this->selectedItemWidget = newlySelectedWidget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegistersPaneWidget::resizeEvent(QResizeEvent* event) {
|
||||
void TargetRegistersPaneWidget::resizeEvent(QResizeEvent* event) {
|
||||
const auto parentSize = this->parent->size();
|
||||
const auto width = parentSize.width() - 1;
|
||||
this->container->setFixedWidth(width);
|
||||
@@ -216,36 +218,39 @@ void TargetRegistersPaneWidget::resizeEvent(QResizeEvent* event) {
|
||||
* the scroll area.
|
||||
*/
|
||||
this->itemScrollArea->setFixedWidth(width - this->parent->getHandleSize());
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegistersPaneWidget::postActivate() {
|
||||
void TargetRegistersPaneWidget::postActivate() {
|
||||
if (this->targetState == Targets::TargetState::STOPPED) {
|
||||
this->refreshRegisterValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegistersPaneWidget::postDeactivate() {
|
||||
void TargetRegistersPaneWidget::postDeactivate() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegistersPaneWidget::onTargetStateChanged(Targets::TargetState newState) {
|
||||
void TargetRegistersPaneWidget::onTargetStateChanged(Targets::TargetState newState) {
|
||||
using Targets::TargetState;
|
||||
this->targetState = newState;
|
||||
|
||||
if (newState == TargetState::STOPPED && this->activated) {
|
||||
this->refreshRegisterValues();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TargetRegistersPaneWidget::onRegistersRead(const Targets::TargetRegisters& registers) {
|
||||
void TargetRegistersPaneWidget::onRegistersRead(const Targets::TargetRegisters& registers) {
|
||||
for (const auto& targetRegister : registers) {
|
||||
auto& descriptor = targetRegister.descriptor;
|
||||
|
||||
for (const auto& registerGroupWidget : this->registerGroupWidgets) {
|
||||
if (registerGroupWidget->registerWidgetsMappedByDescriptor.contains(descriptor)) {
|
||||
registerGroupWidget->registerWidgetsMappedByDescriptor.at(descriptor)->setRegisterValue(targetRegister);
|
||||
registerGroupWidget->registerWidgetsMappedByDescriptor.at(
|
||||
descriptor
|
||||
)->setRegisterValue(targetRegister);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#include "BodyWidget.hpp"
|
||||
|
||||
using namespace Bloom::Widgets::InsightTargetWidgets::Dip;
|
||||
|
||||
BodyWidget::BodyWidget(QWidget* parent, std::size_t pinCount): QWidget(parent) {
|
||||
namespace Bloom::Widgets::InsightTargetWidgets::Dip
|
||||
{
|
||||
BodyWidget::BodyWidget(QWidget* parent, std::size_t pinCount): QWidget(parent) {
|
||||
this->setObjectName("target-body");
|
||||
|
||||
/*
|
||||
@@ -29,15 +29,18 @@ BodyWidget::BodyWidget(QWidget* parent, std::size_t pinCount): QWidget(parent) {
|
||||
this->orientationIndicatorDiameter = this->firstPinIndicatorDiameter % 2 == 0 ?
|
||||
this->firstPinIndicatorDiameter + 3
|
||||
: this->firstPinIndicatorDiameter + 2;
|
||||
}
|
||||
}
|
||||
|
||||
void BodyWidget::paintEvent(QPaintEvent* event) {
|
||||
void BodyWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter(this);
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
}
|
||||
|
||||
void BodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform, true);
|
||||
void BodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(
|
||||
QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform,
|
||||
true
|
||||
);
|
||||
const auto bodyHeight = this->height();
|
||||
const auto bodyRect = QRectF(
|
||||
0,
|
||||
@@ -55,8 +58,8 @@ void BodyWidget::drawWidget(QPainter& painter) {
|
||||
);
|
||||
|
||||
/*
|
||||
* The orientation indicator is just a half-circle cut-out, positioned on the side of the DIP package closest to
|
||||
* the first pin.
|
||||
* The orientation indicator is just a half-circle cut-out, positioned on the side of the DIP package
|
||||
* closest to the first pin.
|
||||
*/
|
||||
const auto orientationIndicatorRect = QRectF(
|
||||
-(this->orientationIndicatorDiameter / 2),
|
||||
@@ -78,4 +81,5 @@ void BodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setBrush(backgroundColor);
|
||||
painter.drawEllipse(firstPinIndicatorRect);
|
||||
painter.drawEllipse(orientationIndicatorRect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,19 +8,21 @@
|
||||
|
||||
#include "src/Helpers/Paths.hpp"
|
||||
|
||||
using namespace Bloom::Widgets::InsightTargetWidgets::Dip;
|
||||
using namespace Bloom::Exceptions;
|
||||
namespace Bloom::Widgets::InsightTargetWidgets::Dip
|
||||
{
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
using Bloom::Targets::TargetVariant;
|
||||
using Bloom::Targets::TargetVariant;
|
||||
|
||||
DualInlinePackageWidget::DualInlinePackageWidget(
|
||||
DualInlinePackageWidget::DualInlinePackageWidget(
|
||||
const TargetVariant& targetVariant,
|
||||
InsightWorker& insightWorker,
|
||||
QWidget* parent
|
||||
): TargetPackageWidget(targetVariant, insightWorker, parent) {
|
||||
): TargetPackageWidget(targetVariant, insightWorker, parent) {
|
||||
auto stylesheetFile = QFile(QString::fromStdString(
|
||||
Paths::compiledResourcesPath()
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/Stylesheets/DualInlinePackage.qss"
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/Stylesheets/"
|
||||
"DualInlinePackage.qss"
|
||||
)
|
||||
);
|
||||
stylesheetFile.open(QFile::ReadOnly);
|
||||
@@ -99,14 +101,14 @@ DualInlinePackageWidget::DualInlinePackageWidget(
|
||||
width,
|
||||
height
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void DualInlinePackageWidget::paintEvent(QPaintEvent* event) {
|
||||
void DualInlinePackageWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter(this);
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
}
|
||||
|
||||
void DualInlinePackageWidget::drawWidget(QPainter& painter) {
|
||||
void DualInlinePackageWidget::drawWidget(QPainter& painter) {
|
||||
using Targets::TargetPinState;
|
||||
|
||||
static auto pinNameFont = QFont("'Ubuntu', sans-serif");
|
||||
@@ -247,4 +249,5 @@ void DualInlinePackageWidget::drawWidget(QPainter& painter) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,21 +2,25 @@
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
using namespace Bloom::Widgets::InsightTargetWidgets::Dip;
|
||||
using namespace Bloom::Targets;
|
||||
namespace Bloom::Widgets::InsightTargetWidgets::Dip
|
||||
{
|
||||
using namespace Bloom::Targets;
|
||||
|
||||
PinBodyWidget::PinBodyWidget(QWidget* parent, Targets::TargetPinDescriptor pinDescriptor)
|
||||
: TargetPinBodyWidget(parent, std::move(pinDescriptor)) {
|
||||
PinBodyWidget::PinBodyWidget(QWidget* parent, Targets::TargetPinDescriptor pinDescriptor)
|
||||
: TargetPinBodyWidget(parent, std::move(pinDescriptor)) {
|
||||
this->setFixedSize(PinBodyWidget::WIDTH, PinBodyWidget::HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
void PinBodyWidget::paintEvent(QPaintEvent* event) {
|
||||
void PinBodyWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter(this);
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
}
|
||||
|
||||
void PinBodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform, true);
|
||||
void PinBodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(
|
||||
QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform,
|
||||
true
|
||||
);
|
||||
auto pinWidth = PinBodyWidget::WIDTH;
|
||||
auto pinHeight = PinBodyWidget::HEIGHT;
|
||||
this->setFixedSize(pinWidth, pinHeight);
|
||||
@@ -32,4 +36,5 @@ void PinBodyWidget::drawWidget(QPainter& painter) {
|
||||
pinWidth,
|
||||
pinHeight
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#include "PinWidget.hpp"
|
||||
|
||||
using namespace Bloom::Widgets::InsightTargetWidgets::Dip;
|
||||
using namespace Bloom::Targets;
|
||||
namespace Bloom::Widgets::InsightTargetWidgets::Dip
|
||||
{
|
||||
using namespace Bloom::Targets;
|
||||
|
||||
PinWidget::PinWidget(
|
||||
PinWidget::PinWidget(
|
||||
const TargetPinDescriptor& pinDescriptor,
|
||||
const TargetVariant& targetVariant,
|
||||
InsightWorker& insightWorker,
|
||||
QWidget* parent
|
||||
): TargetPinWidget(pinDescriptor, targetVariant, insightWorker, parent) {
|
||||
): TargetPinWidget(pinDescriptor, targetVariant, insightWorker, parent) {
|
||||
this->setFixedSize(PinWidget::MINIMUM_WIDTH, PinWidget::MAXIMUM_HEIGHT);
|
||||
|
||||
this->layout = new QVBoxLayout();
|
||||
@@ -44,4 +45,5 @@ PinWidget::PinWidget(
|
||||
this->setLayout(this->layout);
|
||||
|
||||
connect(this->bodyWidget, &PinBodyWidget::clicked, this, &TargetPinWidget::onWidgetBodyClicked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
using namespace Bloom::Widgets::InsightTargetWidgets::Qfp;
|
||||
|
||||
void BodyWidget::paintEvent(QPaintEvent* event) {
|
||||
namespace Bloom::Widgets::InsightTargetWidgets::Qfp
|
||||
{
|
||||
void BodyWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter(this);
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
}
|
||||
|
||||
void BodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform, true);
|
||||
void BodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(
|
||||
QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform,
|
||||
true
|
||||
);
|
||||
|
||||
auto targetBodyColor = this->getBodyColor();
|
||||
auto backgroundColor = QColor("#373835");
|
||||
@@ -45,4 +48,5 @@ void BodyWidget::drawWidget(QPainter& painter) {
|
||||
18,
|
||||
18
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,26 +3,30 @@
|
||||
#include <QPainter>
|
||||
#include <QEvent>
|
||||
|
||||
using namespace Bloom::Widgets::InsightTargetWidgets::Qfp;
|
||||
using namespace Bloom::Targets;
|
||||
namespace Bloom::Widgets::InsightTargetWidgets::Qfp
|
||||
{
|
||||
using namespace Bloom::Targets;
|
||||
|
||||
PinBodyWidget::PinBodyWidget(QWidget* parent, Targets::TargetPinDescriptor pinDescriptor, bool isVertical)
|
||||
: TargetPinBodyWidget(parent, std::move(pinDescriptor)), isVertical(isVertical) {
|
||||
PinBodyWidget::PinBodyWidget(QWidget* parent, Targets::TargetPinDescriptor pinDescriptor, bool isVertical)
|
||||
: TargetPinBodyWidget(parent, std::move(pinDescriptor)), isVertical(isVertical) {
|
||||
if (isVertical) {
|
||||
this->setFixedSize(PinBodyWidget::WIDTH, PinBodyWidget::HEIGHT);
|
||||
|
||||
} else {
|
||||
this->setFixedSize(PinBodyWidget::HEIGHT, PinBodyWidget::WIDTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PinBodyWidget::paintEvent(QPaintEvent* event) {
|
||||
void PinBodyWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter(this);
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
}
|
||||
|
||||
void PinBodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform, true);
|
||||
void PinBodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(
|
||||
QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform,
|
||||
true
|
||||
);
|
||||
auto pinWidth = this->isVertical ? PinBodyWidget::WIDTH : PinBodyWidget::HEIGHT;
|
||||
auto pinHeight = this->isVertical ? PinBodyWidget::HEIGHT : PinBodyWidget::WIDTH;
|
||||
this->setFixedSize(pinWidth, pinHeight);
|
||||
@@ -38,4 +42,5 @@ void PinBodyWidget::drawWidget(QPainter& painter) {
|
||||
pinWidth,
|
||||
pinHeight
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,15 +7,16 @@
|
||||
#include "PinWidget.hpp"
|
||||
#include "PinBodyWidget.hpp"
|
||||
|
||||
using namespace Bloom::Widgets::InsightTargetWidgets::Qfp;
|
||||
using namespace Bloom::Targets;
|
||||
namespace Bloom::Widgets::InsightTargetWidgets::Qfp
|
||||
{
|
||||
using namespace Bloom::Targets;
|
||||
|
||||
PinWidget::PinWidget(
|
||||
PinWidget::PinWidget(
|
||||
const TargetPinDescriptor& pinDescriptor,
|
||||
const TargetVariant& targetVariant,
|
||||
InsightWorker& insightWorker,
|
||||
QWidget* parent
|
||||
): TargetPinWidget(pinDescriptor, targetVariant, insightWorker, parent) {
|
||||
): TargetPinWidget(pinDescriptor, targetVariant, insightWorker, parent) {
|
||||
this->layout = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||
this->layout->setContentsMargins(0, 0, 0, 0);
|
||||
this->layout->setSpacing(0);
|
||||
@@ -90,12 +91,13 @@ PinWidget::PinWidget(
|
||||
this->setLayout(this->layout);
|
||||
|
||||
connect(this->bodyWidget, &PinBodyWidget::clicked, this, &TargetPinWidget::onWidgetBodyClicked);
|
||||
}
|
||||
}
|
||||
|
||||
void PinWidget::updatePinState(const Targets::TargetPinState& pinState) {
|
||||
void PinWidget::updatePinState(const Targets::TargetPinState& pinState) {
|
||||
TargetPinWidget::updatePinState(pinState);
|
||||
|
||||
if (this->bodyWidget != nullptr) {
|
||||
this->bodyWidget->setPinState(pinState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,14 +11,15 @@
|
||||
#include "PinWidget.hpp"
|
||||
#include "BodyWidget.hpp"
|
||||
|
||||
using namespace Bloom::Widgets::InsightTargetWidgets::Qfp;
|
||||
using namespace Bloom::Targets;
|
||||
namespace Bloom::Widgets::InsightTargetWidgets::Qfp
|
||||
{
|
||||
using namespace Bloom::Targets;
|
||||
|
||||
QuadFlatPackageWidget::QuadFlatPackageWidget(
|
||||
QuadFlatPackageWidget::QuadFlatPackageWidget(
|
||||
const TargetVariant& targetVariant,
|
||||
InsightWorker& insightWorker,
|
||||
QWidget* parent
|
||||
): TargetPackageWidget(targetVariant, insightWorker, parent) {
|
||||
): TargetPackageWidget(targetVariant, insightWorker, parent) {
|
||||
assert((targetVariant.pinDescriptorsByNumber.size() % 4) == 0);
|
||||
|
||||
auto stylesheetFile = QFile(QString::fromStdString(
|
||||
@@ -182,14 +183,14 @@ QuadFlatPackageWidget::QuadFlatPackageWidget(
|
||||
width,
|
||||
height
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void QuadFlatPackageWidget::paintEvent(QPaintEvent* event) {
|
||||
void QuadFlatPackageWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter(this);
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
}
|
||||
|
||||
void QuadFlatPackageWidget::drawWidget(QPainter& painter) {
|
||||
void QuadFlatPackageWidget::drawWidget(QPainter& painter) {
|
||||
static auto pinNameFont = QFont("'Ubuntu', sans-serif");
|
||||
static auto pinDirectionFont = pinNameFont;
|
||||
pinNameFont.setPixelSize(11);
|
||||
@@ -222,8 +223,8 @@ void QuadFlatPackageWidget::drawWidget(QPainter& painter) {
|
||||
painter.setPen(pinStateChanged ? pinChangedFontColor : pinNameFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() - PinWidget::PIN_LABEL_LONG_LINE_LENGTH - PinWidget::MAXIMUM_LABEL_WIDTH
|
||||
- (PinWidget::PIN_LABEL_SPACING * 2),
|
||||
pinGeoPosition.x() - PinWidget::PIN_LABEL_LONG_LINE_LENGTH
|
||||
- PinWidget::MAXIMUM_LABEL_WIDTH - (PinWidget::PIN_LABEL_SPACING * 2),
|
||||
pinGeoPosition.y() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_HEIGHT / 2),
|
||||
PinWidget::MAXIMUM_LABEL_WIDTH,
|
||||
@@ -239,8 +240,9 @@ void QuadFlatPackageWidget::drawWidget(QPainter& painter) {
|
||||
painter.setPen(pinDirectionFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() - PinWidget::PIN_LABEL_LONG_LINE_LENGTH - PinWidget::MAXIMUM_LABEL_WIDTH
|
||||
- (PinWidget::PIN_LABEL_SPACING * 3) - PinWidget::MAXIMUM_PIN_DIRECTION_LABEL_WIDTH,
|
||||
pinGeoPosition.x() - PinWidget::PIN_LABEL_LONG_LINE_LENGTH
|
||||
- PinWidget::MAXIMUM_LABEL_WIDTH - (PinWidget::PIN_LABEL_SPACING * 3)
|
||||
- PinWidget::MAXIMUM_PIN_DIRECTION_LABEL_WIDTH,
|
||||
pinGeoPosition.y() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_HEIGHT / 2),
|
||||
PinWidget::MAXIMUM_PIN_DIRECTION_LABEL_WIDTH,
|
||||
@@ -256,7 +258,8 @@ void QuadFlatPackageWidget::drawWidget(QPainter& painter) {
|
||||
painter.drawLine(QLine(
|
||||
pinGeoPosition.x() + PinWidget::MAXIMUM_HORIZONTAL_WIDTH,
|
||||
pinGeoPosition.y() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2),
|
||||
pinGeoPosition.x() + PinWidget::MAXIMUM_HORIZONTAL_WIDTH + PinWidget::PIN_LABEL_LONG_LINE_LENGTH,
|
||||
pinGeoPosition.x() + PinWidget::MAXIMUM_HORIZONTAL_WIDTH
|
||||
+ PinWidget::PIN_LABEL_LONG_LINE_LENGTH,
|
||||
pinGeoPosition.y() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2)
|
||||
));
|
||||
|
||||
@@ -411,4 +414,5 @@ void QuadFlatPackageWidget::drawWidget(QPainter& painter) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,15 @@
|
||||
|
||||
#include "src/Insight/InsightWorker/Tasks/RefreshTargetPinStates.hpp"
|
||||
|
||||
using namespace Bloom;
|
||||
using namespace Bloom::Widgets::InsightTargetWidgets;
|
||||
namespace Bloom::Widgets::InsightTargetWidgets
|
||||
{
|
||||
using Bloom::Targets::TargetState;
|
||||
|
||||
using Bloom::Targets::TargetState;
|
||||
|
||||
TargetPackageWidget::TargetPackageWidget(
|
||||
TargetPackageWidget::TargetPackageWidget(
|
||||
Targets::TargetVariant targetVariant,
|
||||
InsightWorker& insightWorker,
|
||||
QWidget* parent
|
||||
): QWidget(parent), targetVariant(std::move(targetVariant)), insightWorker(insightWorker) {
|
||||
): QWidget(parent), targetVariant(std::move(targetVariant)), insightWorker(insightWorker) {
|
||||
QObject::connect(
|
||||
&(this->insightWorker),
|
||||
&InsightWorker::targetStateUpdated,
|
||||
@@ -29,9 +28,9 @@ TargetPackageWidget::TargetPackageWidget(
|
||||
);
|
||||
|
||||
this->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void TargetPackageWidget::refreshPinStates(std::optional<std::function<void(void)>> callback) {
|
||||
void TargetPackageWidget::refreshPinStates(std::optional<std::function<void(void)>> callback) {
|
||||
auto* refreshTask = new RefreshTargetPinStates(this->targetVariant.id);
|
||||
QObject::connect(
|
||||
refreshTask,
|
||||
@@ -50,9 +49,9 @@ void TargetPackageWidget::refreshPinStates(std::optional<std::function<void(void
|
||||
}
|
||||
|
||||
this->insightWorker.queueTask(refreshTask);
|
||||
}
|
||||
}
|
||||
|
||||
void TargetPackageWidget::updatePinStates(const Targets::TargetPinStateMappingType& pinStatesByNumber) {
|
||||
void TargetPackageWidget::updatePinStates(const Targets::TargetPinStateMappingType& pinStatesByNumber) {
|
||||
for (auto& pinWidget : this->pinWidgets) {
|
||||
auto pinNumber = pinWidget->getPinNumber();
|
||||
if (pinStatesByNumber.contains(pinNumber)) {
|
||||
@@ -61,9 +60,9 @@ void TargetPackageWidget::updatePinStates(const Targets::TargetPinStateMappingTy
|
||||
}
|
||||
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void TargetPackageWidget::onTargetStateChanged(TargetState newState) {
|
||||
void TargetPackageWidget::onTargetStateChanged(TargetState newState) {
|
||||
this->targetState = newState;
|
||||
|
||||
if (newState == TargetState::RUNNING) {
|
||||
@@ -76,9 +75,9 @@ void TargetPackageWidget::onTargetStateChanged(TargetState newState) {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TargetPackageWidget::onRegistersWritten(Targets::TargetRegisters targetRegisters) {
|
||||
void TargetPackageWidget::onRegistersWritten(Targets::TargetRegisters targetRegisters) {
|
||||
if (this->targetState != TargetState::STOPPED) {
|
||||
return;
|
||||
}
|
||||
@@ -90,4 +89,5 @@ void TargetPackageWidget::onRegistersWritten(Targets::TargetRegisters targetRegi
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user