Removed using namespace directive for class member function definitions in source files

This commit is contained in:
Nav
2022-02-05 15:32:08 +00:00
parent 9bbc534973
commit 53a3c815d7
116 changed files with 13113 additions and 12664 deletions

View File

@@ -3,90 +3,98 @@
#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() {
UsbDevice::init();
void AtmelIce::init() {
UsbDevice::init();
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
if (!usbHidInterface.isInitialised()) {
usbHidInterface.detachKernelDriver();
this->setConfiguration(0);
usbHidInterface.init();
if (!usbHidInterface.isInitialised()) {
usbHidInterface.detachKernelDriver();
this->setConfiguration(0);
usbHidInterface.init();
}
/*
* The Atmel-ICE EDBG/CMSIS-DAP interface doesn't operate properly when sending commands too quickly.
*
* Because of this, we have to enforce a minimum time gap between commands. See comment
* in CmsisDapInterface class declaration for more info.
*/
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
if (!this->sessionStarted) {
this->startSession();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
/*
* The Atmel-ICE EDBG/CMSIS-DAP interface doesn't operate properly when sending commands too quickly.
*
* Because of this, we have to enforce a minimum time gap between commands. See comment
* in CmsisDapInterface class declaration for more info.
*/
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
void AtmelIce::close() {
if (this->sessionStarted) {
this->endSession();
}
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
if (!this->sessionStarted) {
this->startSession();
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
std::string AtmelIce::getSerialNumber() {
using namespace CommandFrames::Discovery;
void AtmelIce::close() {
if (this->sessionStarted) {
this->endSession();
}
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
std::string AtmelIce::getSerialNumber() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
auto data = response.getPayloadData();
return std::string(data.begin(), data.end());
}
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()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Atmel-ICE!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Atmel-ICE!");
}
this->sessionStarted = true;
}
this->sessionStarted = true;
}
void AtmelIce::endSession() {
using namespace CommandFrames::HouseKeeping;
void AtmelIce::endSession() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::HouseKeeping::EndSession()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Atmel-ICE!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Atmel-ICE!");
}
this->sessionStarted = false;
}
this->sessionStarted = false;
}

View File

@@ -3,82 +3,90 @@
#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() {
UsbDevice::init();
void CuriosityNano::init() {
UsbDevice::init();
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
if (!usbHidInterface.isInitialised()) {
usbHidInterface.detachKernelDriver();
usbHidInterface.init();
if (!usbHidInterface.isInitialised()) {
usbHidInterface.detachKernelDriver();
usbHidInterface.init();
}
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
if (!this->sessionStarted) {
this->startSession();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
void CuriosityNano::close() {
if (this->sessionStarted) {
this->endSession();
}
if (!this->sessionStarted) {
this->startSession();
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
std::string CuriosityNano::getSerialNumber() {
using namespace CommandFrames::Discovery;
void CuriosityNano::close() {
if (this->sessionStarted) {
this->endSession();
}
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
std::string CuriosityNano::getSerialNumber() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
auto data = response.getPayloadData();
return std::string(data.begin(), data.end());
}
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()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Curiosity Nano!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Curiosity Nano!");
}
this->sessionStarted = true;
}
this->sessionStarted = true;
}
void CuriosityNano::endSession() {
using namespace CommandFrames::HouseKeeping;
void CuriosityNano::endSession() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::HouseKeeping::EndSession()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Curiosity Nano!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Curiosity Nano!");
}
this->sessionStarted = false;
}
this->sessionStarted = false;
}

View File

@@ -3,83 +3,91 @@
#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() {
UsbDevice::init();
void MplabPickit4::init() {
UsbDevice::init();
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
if (!usbHidInterface.isInitialised()) {
usbHidInterface.init();
if (!usbHidInterface.isInitialised()) {
usbHidInterface.init();
}
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
if (!this->sessionStarted) {
this->startSession();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
void MplabPickit4::close() {
if (this->sessionStarted) {
this->endSession();
}
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
if (!this->sessionStarted) {
this->startSession();
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
std::string MplabPickit4::getSerialNumber() {
using namespace CommandFrames::Discovery;
this->setInitialised(true);
}
void MplabPickit4::close() {
if (this->sessionStarted) {
this->endSession();
}
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
std::string MplabPickit4::getSerialNumber() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
auto data = response.getPayloadData();
return std::string(data.begin(), data.end());
}
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()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with MPLAB PICkit 4!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with MPLAB PICkit 4!");
}
this->sessionStarted = true;
}
this->sessionStarted = true;
}
void MplabPickit4::endSession() {
using namespace CommandFrames::HouseKeeping;
void MplabPickit4::endSession() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::HouseKeeping::EndSession()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with MPLAB PICkit 4!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with MPLAB PICkit 4!");
}
this->sessionStarted = false;
}
this->sessionStarted = false;
}

View File

@@ -3,82 +3,90 @@
#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() {
UsbDevice::init();
void MplabSnap::init() {
UsbDevice::init();
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
if (!usbHidInterface.isInitialised()) {
usbHidInterface.init();
if (!usbHidInterface.isInitialised()) {
usbHidInterface.init();
}
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
if (!this->sessionStarted) {
this->startSession();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
void MplabSnap::close() {
if (this->sessionStarted) {
this->endSession();
}
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
if (!this->sessionStarted) {
this->startSession();
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
std::string MplabSnap::getSerialNumber() {
using namespace CommandFrames::Discovery;
void MplabSnap::close() {
if (this->sessionStarted) {
this->endSession();
}
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
std::string MplabSnap::getSerialNumber() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
auto data = response.getPayloadData();
return std::string(data.begin(), data.end());
}
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()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with MPLAB Snap!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with MPLAB Snap!");
}
this->sessionStarted = true;
}
this->sessionStarted = true;
}
void MplabSnap::endSession() {
using namespace CommandFrames::HouseKeeping;
void MplabSnap::endSession() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::HouseKeeping::EndSession()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with MPLAB Snap!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with MPLAB Snap!");
}
this->sessionStarted = false;
}
this->sessionStarted = false;
}

View File

@@ -3,92 +3,100 @@
#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() {
UsbDevice::init();
void PowerDebugger::init() {
UsbDevice::init();
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
if (!usbHidInterface.isInitialised()) {
usbHidInterface.init();
}
if (!usbHidInterface.isInitialised()) {
usbHidInterface.init();
/*
* The Power Debugger EDBG/CMSIS-DAP interface doesn't operate properly when sending commands too quickly.
*
* Because of this, we have to enforce a minimum time gap between commands. See comment in
* CmsisDapInterface class declaration for more info.
*/
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
if (!this->sessionStarted) {
this->startSession();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
/*
* The Power Debugger EDBG/CMSIS-DAP interface doesn't operate properly when sending commands too quickly.
*
* Because of this, we have to enforce a minimum time gap between commands. See comment in
* CmsisDapInterface class declaration for more info.
*/
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
void PowerDebugger::close() {
if (this->sessionStarted) {
this->endSession();
}
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
if (!this->sessionStarted) {
this->startSession();
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
std::string PowerDebugger::getSerialNumber() {
using namespace CommandFrames::Discovery;
void PowerDebugger::close() {
if (this->sessionStarted) {
this->endSession();
}
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
std::string PowerDebugger::getSerialNumber() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
auto data = response.getPayloadData();
return std::string(data.begin(), data.end());
}
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()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure(
"Failed to start session with the Power Debugger - device returned failed response ID"
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure(
"Failed to start session with the Power Debugger - device returned failed response ID"
);
}
this->sessionStarted = true;
}
this->sessionStarted = true;
}
void PowerDebugger::endSession() {
using namespace CommandFrames::HouseKeeping;
void PowerDebugger::endSession() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::HouseKeeping::EndSession()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with the Power Debugger - device returned failed response ID");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure(
"Failed to end session with the Power Debugger - device returned failed response ID"
);
}
this->sessionStarted = false;
}
this->sessionStarted = false;
}

View File

@@ -3,82 +3,90 @@
#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() {
UsbDevice::init();
void XplainedMini::init() {
UsbDevice::init();
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
if (!usbHidInterface.isInitialised()) {
usbHidInterface.detachKernelDriver();
usbHidInterface.init();
if (!usbHidInterface.isInitialised()) {
usbHidInterface.detachKernelDriver();
usbHidInterface.init();
}
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
if (!this->sessionStarted) {
this->startSession();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
void XplainedMini::close() {
if (this->sessionStarted) {
this->endSession();
}
if (!this->sessionStarted) {
this->startSession();
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
std::string XplainedMini::getSerialNumber() {
using namespace CommandFrames::Discovery;
void XplainedMini::close() {
if (this->sessionStarted) {
this->endSession();
}
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
std::string XplainedMini::getSerialNumber() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
auto data = response.getPayloadData();
return std::string(data.begin(), data.end());
}
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()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Xplained Mini!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Xplained Mini!");
}
this->sessionStarted = true;
}
this->sessionStarted = true;
}
void XplainedMini::endSession() {
using namespace CommandFrames::HouseKeeping;
void XplainedMini::endSession() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::HouseKeeping::EndSession()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Xplained Mini!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Xplained Mini!");
}
this->sessionStarted = false;
}
this->sessionStarted = false;
}

View File

@@ -3,82 +3,90 @@
#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() {
UsbDevice::init();
void XplainedNano::init() {
UsbDevice::init();
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
if (!usbHidInterface.isInitialised()) {
usbHidInterface.detachKernelDriver();
usbHidInterface.init();
if (!usbHidInterface.isInitialised()) {
usbHidInterface.detachKernelDriver();
usbHidInterface.init();
}
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
if (!this->sessionStarted) {
this->startSession();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
void XplainedNano::close() {
if (this->sessionStarted) {
this->endSession();
}
if (!this->sessionStarted) {
this->startSession();
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
this->setInitialised(true);
}
std::string XplainedNano::getSerialNumber() {
using namespace CommandFrames::Discovery;
void XplainedNano::close() {
if (this->sessionStarted) {
this->endSession();
}
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
std::string XplainedNano::getSerialNumber() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
auto data = response.getPayloadData();
return std::string(data.begin(), data.end());
}
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()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Xplained Nano!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Xplained Nano!");
}
this->sessionStarted = true;
}
this->sessionStarted = true;
}
void XplainedNano::endSession() {
using namespace CommandFrames::HouseKeeping;
void XplainedNano::endSession() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::HouseKeeping::EndSession()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Xplained Nano!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Xplained Nano!");
}
this->sessionStarted = false;
}
this->sessionStarted = false;
}

View File

@@ -3,91 +3,99 @@
#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() {
UsbDevice::init();
void XplainedPro::init() {
UsbDevice::init();
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
usbHidInterface.setNumber(0);
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
usbHidInterface.setVendorId(this->vendorId);
usbHidInterface.setProductId(this->productId);
if (!usbHidInterface.isInitialised()) {
usbHidInterface.detachKernelDriver();
usbHidInterface.init();
if (!usbHidInterface.isInitialised()) {
usbHidInterface.detachKernelDriver();
usbHidInterface.init();
}
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
if (!this->sessionStarted) {
this->startSession();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
/*
* The Xplained Pro debug tool returns incorrect data for any read memory command that exceeds 256 bytes in the
* size of the read request, despite the fact that the HID report size is 512 bytes. The debug tool doesn't
* report any error, it just returns incorrect data.
*
* This means we must enforce a hard limit on the number of bytes we attempt to access, per request.
*/
this->edbgAvr8Interface->setMaximumMemoryAccessSizePerRequest(256);
this->setInitialised(true);
}
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
void XplainedPro::close() {
if (this->sessionStarted) {
this->endSession();
}
if (!this->sessionStarted) {
this->startSession();
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
std::string XplainedPro::getSerialNumber() {
using namespace CommandFrames::Discovery;
/*
* The Xplained Pro debug tool returns incorrect data for any read memory command that exceeds 256 bytes in the
* size of the read request, despite the fact that the HID report size is 512 bytes. The debug tool doesn't
* report any error, it just returns incorrect data.
*
* This means we must enforce a hard limit on the number of bytes we attempt to access, per request.
*/
this->edbgAvr8Interface->setMaximumMemoryAccessSizePerRequest(256);
this->setInitialised(true);
}
void XplainedPro::close() {
if (this->sessionStarted) {
this->endSession();
}
this->getEdbgInterface().getUsbHidInterface().close();
UsbDevice::close();
}
std::string XplainedPro::getSerialNumber() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::Discovery::Query(CommandFrames::Discovery::QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != CommandFrames::Discovery::ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
Query(QueryContext::SERIAL_NUMBER)
);
if (response.getResponseId() != ResponseId::OK) {
throw DeviceInitializationFailure(
"Failed to fetch serial number from device - invalid Discovery Protocol response ID."
);
}
auto data = response.getPayloadData();
return std::string(data.begin(), data.end());
}
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()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
StartSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Xplained Pro!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceInitializationFailure("Failed to start session with Xplained Pro!");
}
this->sessionStarted = true;
}
this->sessionStarted = true;
}
void XplainedPro::endSession() {
using namespace CommandFrames::HouseKeeping;
void XplainedPro::endSession() {
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
CommandFrames::HouseKeeping::EndSession()
);
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
EndSession()
);
if (response.getResponseId() == CommandFrames::HouseKeeping::ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Xplained Pro!");
if (response.getResponseId() == ResponseId::FAILED) {
// Failed response returned!
throw DeviceFailure("Failed to end session with Xplained Pro!");
}
this->sessionStarted = false;
}
this->sessionStarted = false;
}

View File

@@ -6,45 +6,47 @@
#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) {
if (this->msSendCommandDelay.count() > 0) {
using namespace std::chrono;
std::int64_t now = duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();
std::int64_t difference = (now - this->lastCommandSentTimeStamp);
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();
std::int64_t difference = (now - this->lastCommandSentTimeStamp);
if (difference < this->msSendCommandDelay.count()) {
std::this_thread::sleep_for(milliseconds(this->msSendCommandDelay.count() - difference));
if (difference < this->msSendCommandDelay.count()) {
std::this_thread::sleep_for(milliseconds(this->msSendCommandDelay.count() - difference));
}
this->lastCommandSentTimeStamp = now;
}
this->lastCommandSentTimeStamp = now;
this->getUsbHidInterface().write(static_cast<std::vector<unsigned char>>(cmsisDapCommand));
}
this->getUsbHidInterface().write(static_cast<std::vector<unsigned char>>(cmsisDapCommand));
}
std::unique_ptr<Response> CmsisDapInterface::getResponse() {
auto rawResponse = this->getUsbHidInterface().read(10000);
std::unique_ptr<Response> CmsisDapInterface::getResponse() {
auto rawResponse = this->getUsbHidInterface().read(10000);
if (rawResponse.empty()) {
throw DeviceCommunicationFailure("Empty CMSIS-DAP response received");
}
if (rawResponse.empty()) {
throw DeviceCommunicationFailure("Empty CMSIS-DAP response received");
auto response = std::make_unique<Response>(Response());
response->init(rawResponse);
return response;
}
auto response = std::make_unique<Response>(Response());
response->init(rawResponse);
return response;
}
std::unique_ptr<Response> CmsisDapInterface::sendCommandAndWaitForResponse(const Command& cmsisDapCommand) {
this->sendCommand(cmsisDapCommand);
auto response = this->getResponse();
std::unique_ptr<Response> CmsisDapInterface::sendCommandAndWaitForResponse(const Command& cmsisDapCommand) {
this->sendCommand(cmsisDapCommand);
auto response = this->getResponse();
if (response->getResponseId() != cmsisDapCommand.getCommandId()) {
// This response is not what we were expecting
throw DeviceCommunicationFailure("Unexpected response to CMSIS-DAP command.");
}
if (response->getResponseId() != cmsisDapCommand.getCommandId()) {
// This response is not what we were expecting
throw DeviceCommunicationFailure("Unexpected response to CMSIS-DAP command.");
return response;
}
return response;
}

View File

@@ -1,11 +1,12 @@
#include "Command.hpp"
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap;
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());
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;
return rawCommand;
}
}

View File

@@ -2,13 +2,14 @@
#include "src/Exceptions/Exception.hpp"
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap;
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");
}
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()));
}
this->setResponseId(rawResponse[0]);
this->setData(std::vector<unsigned char>(rawResponse.begin() + 1, rawResponse.end()));
}

View File

@@ -1,22 +1,23 @@
#include "AvrCommand.hpp"
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr;
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();
data.resize(3 + commandPacketSize);
// FragmentInfo byte
data[0] = static_cast<unsigned char>((this->getFragmentNumber() << 4) | this->getFragmentCount());
std::vector<unsigned char> AvrCommand::getData() const {
std::vector<unsigned char> data;
auto commandPacket = this->getCommandPacket();
std::size_t commandPacketSize = commandPacket.size();
data.resize(3 + commandPacketSize);
// FragmentInfo byte
data[0] = static_cast<unsigned char>((this->getFragmentNumber() << 4) | this->getFragmentCount());
// Size byte
data[1] = static_cast<unsigned char>(commandPacketSize >> 8);
data[2] = static_cast<unsigned char>(commandPacketSize & 0xFF);
// Size byte
data[1] = (unsigned char) (commandPacketSize >> 8);
data[2] = (unsigned char) (commandPacketSize & 0xFF);
if (commandPacketSize > 0) {
data.insert(data.begin() + 3, commandPacket.begin(), commandPacket.end());
}
if (commandPacketSize > 0) {
data.insert(data.begin() + 3, commandPacket.begin(), commandPacket.end());
return data;
}
return data;
}

View File

@@ -2,48 +2,50 @@
#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) {
Response::init(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.");
}
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)
throw Exception("Failed to construct AvrEvent object - AVR_EVT response "
"returned no additional data.");
}
if (responseData.size() < 2) {
// All AVR_EVT responses should consist of at least two bytes (excluding the AVR_EVT ID)
throw Exception("Failed to construct AvrEvent object - AVR_EVT response "
"returned no additional data.");
}
// Response size is two bytes, MSB
auto responsePacketSize = static_cast<std::size_t>((responseData[0] << 8) | responseData[1]);
// Response size is two bytes, MSB
auto responsePacketSize = static_cast<std::size_t>((responseData[0] << 8) | responseData[1]);
if (responseData.size() < 2) {
// All AVR_EVT responses should consist of at least two bytes (excluding the AVR_EVT ID)
throw Exception("Failed to construct AvrEvent object - AVR_EVT response "
"contained invalid event data size.");
}
if (responseData.size() < 2) {
// All AVR_EVT responses should consist of at least two bytes (excluding the AVR_EVT ID)
throw Exception("Failed to construct AvrEvent object - AVR_EVT response "
"contained invalid event data size.");
}
auto eventData = std::vector<unsigned char>();
auto eventData = std::vector<unsigned char>();
/*
* Ignore the SOF, protocol version &handler id and sequence ID (with all make up 5 bytes in total, 7 when
* you include the two size bytes)
*/
eventData.insert(
eventData.end(),
responseData.begin() + 7,
responseData.begin() + 7 + static_cast<long>(responsePacketSize)
);
/*
* Ignore the SOF, protocol version &handler id and sequence ID (with all make up 5 bytes in total, 7 when
* you include the two size bytes)
*/
eventData.insert(
eventData.end(),
responseData.begin() + 7,
responseData.begin() + 7 + static_cast<long>(responsePacketSize)
);
this->setEventData(eventData);
this->setEventData(eventData);
if (!eventData.empty()) {
this->eventId = eventData[0];
if (!eventData.empty()) {
this->eventId = eventData[0];
}
}
}

View File

@@ -2,40 +2,42 @@
#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) {
Response::init(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.");
if (this->getResponseId() != 0x81) {
throw Exception("Failed to construct AvrResponse object - invalid response ID.");
}
const auto& responseData = this->getData();
if (responseData.empty()) {
// All AVR responses should contain at least one byte (the fragment info byte)
throw Exception("Failed to construct AvrResponse object - AVR_RSP response "
"returned no additional data");
}
if (responseData[0] == 0x00) {
// This AVR Response contains no data (the device had no data to send), so we can stop here.
return;
}
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
const auto responsePacketSize = static_cast<std::size_t>((responseData[1] << 8U) + responseData[2]);
std::vector<unsigned char> responsePacket;
responsePacket.resize(responsePacketSize);
for (std::size_t i = 0; i < responsePacketSize; i++) {
responsePacket[i] = responseData[i + 3];
}
this->setResponsePacket(responsePacket);
}
auto& responseData = this->getData();
if (responseData.empty()) {
// All AVR responses should contain at least one byte (the fragment info byte)
throw Exception("Failed to construct AvrResponse object - AVR_RSP response "
"returned no additional data");
}
if (responseData[0] == 0x00) {
// This AVR Response contains no data (the device had no data to send), so we can stop here.
return;
}
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]);
std::vector<unsigned char> responsePacket;
responsePacket.resize(responsePacketSize);
for (std::size_t i = 0; i < responsePacketSize; i++) {
responsePacket[i] = responseData[i + 3];
}
this->setResponsePacket(responsePacket);
}

View File

@@ -3,54 +3,55 @@
#include <bitset>
#include <cmath>
using namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr::CommandFrames::Avr8Generic;
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)
* 2. Version (0x00)
* 3. Memory type (Avr8MemoryType)
* 4. Start address (4 bytes)
* 5. Number of bytes to read (4 bytes)
* 6. Mask to apply (this->bytes / 8) - only required if we're using the masked read command (command ID 0x22).
*/
auto output = std::vector<unsigned char>(11, 0x00);
output[0] = this->excludedAddresses.empty() ? 0x21 : 0x22;
output[1] = 0x00;
output[2] = static_cast<unsigned char>(this->type);
output[3] = static_cast<unsigned char>(this->address);
output[4] = static_cast<unsigned char>(this->address >> 8);
output[5] = static_cast<unsigned char>(this->address >> 16);
output[6] = static_cast<unsigned char>(this->address >> 24);
output[7] = static_cast<unsigned char>(this->bytes);
output[8] = static_cast<unsigned char>(this->bytes >> 8);
output[9] = static_cast<unsigned char>(this->bytes >> 16);
output[10] = static_cast<unsigned char>(this->bytes >> 24);
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)
* 2. Version (0x00)
* 3. Memory type (Avr8MemoryType)
* 4. Start address (4 bytes)
* 5. Number of bytes to read (4 bytes)
* 6. Mask to apply (this->bytes / 8) - only required if we're using the masked read command (command ID 0x22).
*/
auto output = std::vector<unsigned char>(11, 0x00);
output[0] = this->excludedAddresses.empty() ? 0x21 : 0x22;
output[1] = 0x00;
output[2] = static_cast<unsigned char>(this->type);
output[3] = static_cast<unsigned char>(this->address);
output[4] = static_cast<unsigned char>(this->address >> 8);
output[5] = static_cast<unsigned char>(this->address >> 16);
output[6] = static_cast<unsigned char>(this->address >> 24);
output[7] = static_cast<unsigned char>(this->bytes);
output[8] = static_cast<unsigned char>(this->bytes >> 8);
output[9] = static_cast<unsigned char>(this->bytes >> 16);
output[10] = static_cast<unsigned char>(this->bytes >> 24);
if (!this->excludedAddresses.empty()) {
const auto endAddress = this->address + (this->bytes - 1);
if (!this->excludedAddresses.empty()) {
const auto endAddress = this->address + (this->bytes - 1);
constexpr auto byteBitSize = std::numeric_limits<unsigned char>::digits;
auto byteBitset = std::bitset<byteBitSize>();
byteBitset.reset();
constexpr auto byteBitSize = std::numeric_limits<unsigned char>::digits;
auto byteBitset = std::bitset<byteBitSize>();
byteBitset.reset();
for (std::uint32_t address = this->address; address <= endAddress; address++) {
auto addressIndex = address - this->address;
auto bitIndex = static_cast<std::size_t>(
addressIndex - (std::floor(addressIndex / byteBitSize) * byteBitSize)
);
for (std::uint32_t address = this->address; address <= endAddress; address++) {
auto addressIndex = address - this->address;
auto bitIndex = static_cast<std::size_t>(
addressIndex - (std::floor(addressIndex / byteBitSize) * byteBitSize)
);
if (!this->excludedAddresses.contains(address)) {
byteBitset[bitIndex] = 1;
}
if (!this->excludedAddresses.contains(address)) {
byteBitset[bitIndex] = 1;
}
if (address > 0 && (bitIndex == 7 || address == endAddress)) {
output.emplace_back(byteBitset.to_ulong());
byteBitset.reset();
if (address > 0 && (bitIndex == 7 || address == endAddress)) {
output.emplace_back(byteBitset.to_ulong());
byteBitset.reset();
}
}
}
}
return output;
return output;
}
}

View File

@@ -2,62 +2,63 @@
#include <math.h>
using 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>(
ceil(static_cast<float>(commandFrameSize) / static_cast<float>(maximumCommandPacketSize))
);
std::vector<AvrCommand> avrCommands;
std::size_t copiedPacketSize = 0;
for (std::size_t i = 0; i < commandsRequired; i++) {
AvrCommand avrCommand;
avrCommand.setFragmentCount(commandsRequired);
avrCommand.setFragmentNumber(i + 1);
auto commandPacket = avrCommand.getCommandPacket();
// If we're on the last packet, the packet size will be what ever is left of the AvrCommandFrame
std::size_t commandPacketSize = ((i + 1) != commandsRequired) ? maximumCommandPacketSize
: (commandFrameSize - (maximumCommandPacketSize * i));
commandPacket.insert(
commandPacket.end(),
rawCommandFrame.begin() + static_cast<long>(copiedPacketSize),
rawCommandFrame.begin() + static_cast<long>(copiedPacketSize + commandPacketSize)
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>(
ceil(static_cast<float>(commandFrameSize) / static_cast<float>(maximumCommandPacketSize))
);
avrCommand.setCommandPacket(commandPacket);
avrCommands.push_back(avrCommand);
copiedPacketSize += commandPacketSize;
std::vector<AvrCommand> avrCommands;
std::size_t copiedPacketSize = 0;
for (std::size_t i = 0; i < commandsRequired; i++) {
AvrCommand avrCommand;
avrCommand.setFragmentCount(commandsRequired);
avrCommand.setFragmentNumber(i + 1);
auto commandPacket = avrCommand.getCommandPacket();
// If we're on the last packet, the packet size will be what ever is left of the AvrCommandFrame
std::size_t commandPacketSize = ((i + 1) != commandsRequired) ? maximumCommandPacketSize
: (commandFrameSize - (maximumCommandPacketSize * i));
commandPacket.insert(
commandPacket.end(),
rawCommandFrame.begin() + static_cast<long>(copiedPacketSize),
rawCommandFrame.begin() + static_cast<long>(copiedPacketSize + commandPacketSize)
);
avrCommand.setCommandPacket(commandPacket);
avrCommands.push_back(avrCommand);
copiedPacketSize += commandPacketSize;
}
return avrCommands;
}
return avrCommands;
}
AvrCommandFrame::operator std::vector<unsigned char>() const {
auto data = this->getPayload();
auto dataSize = data.size();
AvrCommandFrame::operator std::vector<unsigned char> () const {
auto data = this->getPayload();
auto dataSize = data.size();
auto rawCommand = std::vector<unsigned char>(5);
auto rawCommand = std::vector<unsigned char>(5);
rawCommand[0] = this->SOF;
rawCommand[1] = this->getProtocolVersion();
rawCommand[0] = this->SOF;
rawCommand[1] = this->getProtocolVersion();
rawCommand[2] = static_cast<unsigned char>(this->getSequenceId());
rawCommand[3] = static_cast<unsigned char>(this->getSequenceId() >> 8);
rawCommand[2] = static_cast<unsigned char>(this->getSequenceId());
rawCommand[3] = static_cast<unsigned char>(this->getSequenceId() >> 8);
rawCommand[4] = static_cast<unsigned char>(this->getProtocolHandlerId());
rawCommand[4] = static_cast<unsigned char>(this->getProtocolHandlerId());
if (dataSize > 0) {
rawCommand.insert(
rawCommand.end(),
data.begin(),
data.end()
);
}
if (dataSize > 0) {
rawCommand.insert(
rawCommand.end(),
data.begin(),
data.end()
);
return rawCommand;
}
return rawCommand;
}

View File

@@ -2,28 +2,33 @@
#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) {
AvrEvent::init(event);
auto& data = this->getEventData();
using Bloom::Targets::TargetBreakCause;
if (data.size() < 8) {
/*
* All BreakEvent packets must consist of at least 9 bytes:
* 1 byte for event ID
* 4 bytes for program counter
* 1 byte for break cause
* 2 bytes for extended info
*/
throw Exception("Failed to process BreakEvent from AvrEvent - unexpected packet size.");
void BreakEvent::init(const AvrEvent& event) {
AvrEvent::init(event);
const auto& data = this->getEventData();
if (data.size() < 8) {
/*
* All BreakEvent packets must consist of at least 9 bytes:
* 1 byte for event ID
* 4 bytes for program counter
* 1 byte for break cause
* 2 bytes for extended info
*/
throw Exception("Failed to process BreakEvent from AvrEvent - unexpected packet size.");
}
// 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;
// Break cause is 1 byte, where 0x01 is 'program breakpoint' and 0x00 'unspecified'
this->breakCause = data[7] == 0x01 ? TargetBreakCause::BREAKPOINT : TargetBreakCause::UNKNOWN;
}
// 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;
// Break cause is 1 byte, where 0x01 is 'program breakpoint' and 0x00 'unspecified'
this->breakCause = data[7] == 0x01 ? TargetBreakCause::BREAKPOINT : TargetBreakCause::UNKNOWN;
}

View File

@@ -2,36 +2,38 @@
#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) {
// Build a raw frame buffer from the AVRResponse objects and just call initFromRawFrame()
std::vector<unsigned char> rawFrame;
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) {
auto responsePacket = avrResponse.getResponsePacket();
rawFrame.insert(rawFrame.end(), responsePacket.begin(), responsePacket.end());
for (const auto& avrResponse : avrResponses) {
auto responsePacket = avrResponse.getResponsePacket();
rawFrame.insert(rawFrame.end(), responsePacket.begin(), responsePacket.end());
}
return this->initFromRawFrame(rawFrame);
}
return this->initFromRawFrame(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)
throw Exception("Failed to construct AvrResponseFrame - unexpected end to raw frame");
}
if (rawFrame[0] != 0x0E) {
// The SOF field must always be 0x0E
throw Exception("Failed to construct AvrResponseFrame - unexpected SOF field value in raw frame");
}
this->setSequenceId(static_cast<std::uint16_t>((rawFrame[2] << 8) + rawFrame[1]));
this->setProtocolHandlerId(rawFrame[3]);
auto& payload = this->getPayload();
payload.insert(payload.begin(), rawFrame.begin() + 4, rawFrame.end());
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)
throw Exception("Failed to construct AvrResponseFrame - unexpected end to raw frame");
}
if (rawFrame[0] != 0x0E) {
// The SOF field must always be 0x0E
throw Exception("Failed to construct AvrResponseFrame - unexpected SOF field value in raw frame");
}
this->setSequenceId(static_cast<std::uint16_t>((rawFrame[2] << 8) + rawFrame[1]));
this->setProtocolHandlerId(rawFrame[3]);
auto& payload = this->getPayload();
payload.insert(payload.begin(), rawFrame.begin() + 4, rawFrame.end());
}
}

View File

@@ -4,95 +4,99 @@
#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(
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.
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.
// Minus 3 to accommodate AVR command meta data
std::size_t maximumCommandPacketSize = (this->getUsbHidInputReportSize() - 3);
// Minus 3 to accommodate AVR command meta data
std::size_t maximumCommandPacketSize = (this->getUsbHidInputReportSize() - 3);
auto avrCommands = avrCommandFrame.generateAvrCommands(maximumCommandPacketSize);
auto avrCommands = avrCommandFrame.generateAvrCommands(maximumCommandPacketSize);
for (auto& avrCommand : avrCommands) {
// Send command to device
auto response = this->sendCommandAndWaitForResponse(avrCommand);
for (auto& avrCommand : avrCommands) {
// Send command to device
auto response = this->sendCommandAndWaitForResponse(avrCommand);
if (&avrCommand ==& avrCommands.back()) {
return* response;
if (&avrCommand == &avrCommands.back()) {
return *response;
}
}
// This should never happen
throw DeviceCommunicationFailure(
"Cannot send AVR command frame - failed to generate CMSIS-DAP Vendor (AVR) commands"
);
}
// This should never happen
throw DeviceCommunicationFailure(
"Cannot send AVR command frame - failed to generate CMSIS-DAP Vendor (AVR) commands"
);
}
Protocols::CmsisDap::Edbg::Avr::AvrResponse EdbgInterface::getAvrResponse() {
auto cmsisResponse = this->getResponse();
Protocols::CmsisDap::Edbg::Avr::AvrResponse EdbgInterface::getAvrResponse() {
auto cmsisResponse = this->getResponse();
if (cmsisResponse->getResponseId() == 0x81) {
// This is an AVR_RSP response
auto avrResponse = Protocols::CmsisDap::Edbg::Avr::AvrResponse();
avrResponse.init(*cmsisResponse);
return avrResponse;
}
if (cmsisResponse->getResponseId() == 0x81) {
// This is an AVR_RSP response
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() {
this->sendCommand(AvrEventCommand());
auto cmsisResponse = this->getResponse();
std::optional<Protocols::CmsisDap::Edbg::Avr::AvrEvent> EdbgInterface::requestAvrEvent() {
this->sendCommand(AvrEventCommand());
auto cmsisResponse = this->getResponse();
if (cmsisResponse->getResponseId() == 0x82) {
// 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;
}
if (cmsisResponse->getResponseId() == 0x82) {
// 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 {
throw DeviceCommunicationFailure("Unexpected response to AvrEventCommand from device");
}
}
std::vector<Protocols::CmsisDap::Edbg::Avr::AvrResponse> EdbgInterface::requestAvrResponses() {
std::vector<Protocols::CmsisDap::Edbg::Avr::AvrResponse> responses;
AvrResponseCommand responseCommand;
std::vector<Protocols::CmsisDap::Edbg::Avr::AvrResponse> EdbgInterface::requestAvrResponses() {
using Protocols::CmsisDap::Edbg::Avr::AvrResponseCommand;
this->sendCommand(responseCommand);
auto response = this->getAvrResponse();
responses.push_back(response);
int fragmentCount = response.getFragmentCount();
std::vector<Protocols::CmsisDap::Edbg::Avr::AvrResponse> responses;
AvrResponseCommand responseCommand;
while (responses.size() < fragmentCount) {
// There are more response packets
this->sendCommand(responseCommand);
response = this->getAvrResponse();
if (response.getFragmentCount() != fragmentCount) {
throw DeviceCommunicationFailure(
"Failed to fetch AVRResponse objects - invalid fragment count returned."
);
}
if (response.getFragmentCount() == 0 && response.getFragmentNumber() == 0) {
throw DeviceCommunicationFailure("Failed to fetch AVRResponse objects - unexpected empty response");
} else if (response.getFragmentNumber() == 0) {
// End of response data ( &this packet can be ignored)
break;
}
auto response = this->getAvrResponse();
responses.push_back(response);
}
int fragmentCount = response.getFragmentCount();
return responses;
while (responses.size() < fragmentCount) {
// There are more response packets
this->sendCommand(responseCommand);
response = this->getAvrResponse();
if (response.getFragmentCount() != fragmentCount) {
throw DeviceCommunicationFailure(
"Failed to fetch AVRResponse objects - invalid fragment count returned."
);
}
if (response.getFragmentCount() == 0 && response.getFragmentNumber() == 0) {
throw DeviceCommunicationFailure(
"Failed to fetch AVRResponse objects - unexpected empty response"
);
}
if (response.getFragmentNumber() == 0) {
// End of response data ( &this packet can be ignored)
break;
}
responses.push_back(response);
}
return responses;
}
}

View File

@@ -5,127 +5,133 @@
#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() {
if (this->libUsbDevice == nullptr) {
throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer.");
}
hid_init();
hid_device* hidDevice = nullptr;
std::string hidInterfacePath = this->getDevicePathByInterfaceNumber(this->getNumber());
Logger::debug("HID device path: " + hidInterfacePath);
if ((hidDevice = hid_open_path(hidInterfacePath.c_str())) == nullptr) {
throw DeviceInitializationFailure("Failed to open HID device via hidapi.");
}
if (hidDevice->input_ep_max_packet_size < 1) {
throw DeviceInitializationFailure(
"Invalid max packet size for USB endpoint, on interface " + std::to_string(this->getNumber())
);
}
this->setHidDevice(hidDevice);
this->setInputReportSize(static_cast<std::size_t>(hidDevice->input_ep_max_packet_size));
this->libUsbDeviceHandle = hidDevice->device_handle;
this->initialised = true;
}
void HidInterface::close() {
auto* hidDevice = this->getHidDevice();
if (hidDevice != nullptr) {
this->libUsbDeviceHandle = nullptr;
hid_close(hidDevice);
// hid_close() releases the interface
this->claimed = false;
}
hid_exit();
Interface::close();
}
std::vector<unsigned char> HidInterface::read(unsigned int timeout) {
std::vector<unsigned char> output;
auto readSize = this->getInputReportSize();
// Attempt to read the first HID report packet, and whatever is left after that.
output.resize(readSize);
auto transferredByteCount = this->read(output.data(), readSize, timeout);
auto totalByteCount = transferredByteCount;
while (transferredByteCount >= readSize) {
output.resize(totalByteCount + readSize);
transferredByteCount = this->read(output.data() + totalByteCount, readSize, 1);
totalByteCount += transferredByteCount;
}
output.resize(totalByteCount);
return output;
}
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."
);
}
if (buffer.size() < this->getInputReportSize()) {
/*
* Every report we send via the USB HID interface should be of a fixed size.
* In the event of a report being too small, we just fill the buffer vector with 0.
*/
buffer.resize(this->getInputReportSize(), 0);
}
int transferred = 0;
auto length = buffer.size();
if ((transferred = hid_write(this->getHidDevice(), buffer.data(), length)) != length) {
Logger::debug("Attempted to write " + std::to_string(length)
+ " 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) {
int transferred;
if ((transferred = hid_read_timeout(
this->hidDevice,
buffer,
maxLength,
timeout == 0 ? -1 : static_cast<int>(timeout))
) == -1
) {
throw DeviceCommunicationFailure("Failed to read from HID device.");
}
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());
while (hidDeviceInfoList != nullptr) {
if (hidDeviceInfoList->interface_number == interfaceNumber) {
break;
void HidInterface::init() {
if (this->libUsbDevice == nullptr) {
throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer.");
}
hidDeviceInfoList = hidDeviceInfoList->next;
hid_init();
hid_device* hidDevice = nullptr;
std::string hidInterfacePath = this->getDevicePathByInterfaceNumber(this->getNumber());
Logger::debug("HID device path: " + hidInterfacePath);
if ((hidDevice = hid_open_path(hidInterfacePath.c_str())) == nullptr) {
throw DeviceInitializationFailure("Failed to open HID device via hidapi.");
}
if (hidDevice->input_ep_max_packet_size < 1) {
throw DeviceInitializationFailure(
"Invalid max packet size for USB endpoint, on interface "
+ std::to_string(this->getNumber())
);
}
this->setHidDevice(hidDevice);
this->setInputReportSize(static_cast<std::size_t>(hidDevice->input_ep_max_packet_size));
this->libUsbDeviceHandle = hidDevice->device_handle;
this->initialised = true;
}
if (hidDeviceInfoList == nullptr) {
throw DeviceInitializationFailure("Failed to match interface number with HID interface.");
void HidInterface::close() {
auto* hidDevice = this->getHidDevice();
if (hidDevice != nullptr) {
this->libUsbDeviceHandle = nullptr;
hid_close(hidDevice);
// hid_close() releases the interface
this->claimed = false;
}
hid_exit();
Interface::close();
}
auto path = std::string(hidDeviceInfoList->path);
hid_free_enumeration(hidDeviceInfoList);
return path;
std::vector<unsigned char> HidInterface::read(unsigned int timeout) {
std::vector<unsigned char> output;
auto readSize = this->getInputReportSize();
// Attempt to read the first HID report packet, and whatever is left after that.
output.resize(readSize);
auto transferredByteCount = this->read(output.data(), readSize, timeout);
auto totalByteCount = transferredByteCount;
while (transferredByteCount >= readSize) {
output.resize(totalByteCount + readSize);
transferredByteCount = this->read(output.data() + totalByteCount, readSize, 1);
totalByteCount += transferredByteCount;
}
output.resize(totalByteCount);
return output;
}
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."
);
}
if (buffer.size() < this->getInputReportSize()) {
/*
* Every report we send via the USB HID interface should be of a fixed size.
* In the event of a report being too small, we just fill the buffer vector with 0.
*/
buffer.resize(this->getInputReportSize(), 0);
}
int transferred = 0;
auto length = buffer.size();
if ((transferred = hid_write(this->getHidDevice(), buffer.data(), length)) != length) {
Logger::debug("Attempted to write " + std::to_string(length)
+ " 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) {
int transferred;
if ((transferred = hid_read_timeout(
this->hidDevice,
buffer,
maxLength,
timeout == 0 ? -1 : static_cast<int>(timeout))
) == -1
) {
throw DeviceCommunicationFailure("Failed to read from HID device.");
}
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()
);
while (hidDeviceInfoList != nullptr) {
if (hidDeviceInfoList->interface_number == interfaceNumber) {
break;
}
hidDeviceInfoList = hidDeviceInfoList->next;
}
if (hidDeviceInfoList == nullptr) {
throw DeviceInitializationFailure("Failed to match interface number with HID interface.");
}
auto path = std::string(hidDeviceInfoList->path);
hid_free_enumeration(hidDeviceInfoList);
return path;
}
}

View File

@@ -1,121 +1,123 @@
#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() {
if (this->libUsbDevice == nullptr) {
throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer.");
}
if (this->libUsbDeviceHandle == nullptr) {
throw DeviceInitializationFailure("Cannot initialise interface without libusb device handle.");
}
this->initialised = true;
}
void Interface::close() {
if (this->libUsbDeviceHandle != nullptr) {
this->release();
}
this->initialised = false;
}
void Interface::claim() {
int interfaceNumber = this->getNumber();
this->detachKernelDriver();
if (libusb_claim_interface(this->libUsbDeviceHandle, interfaceNumber) != 0) {
throw DeviceInitializationFailure(
"Failed to claim interface {" + std::to_string(interfaceNumber) + "} on USB device\n"
);
}
this->claimed = true;
}
void Interface::detachKernelDriver() {
int interfaceNumber = this->getNumber();
int libUsbStatusCode;
if ((libUsbStatusCode = libusb_kernel_driver_active(this->libUsbDeviceHandle, interfaceNumber)) != 0) {
if (libUsbStatusCode == 1) {
// A kernel driver is active on this interface. Attempt to detach it
if (libusb_detach_kernel_driver(this->libUsbDeviceHandle, interfaceNumber) != 0) {
throw DeviceInitializationFailure("Failed to detach kernel driver from interface " +
std::to_string(interfaceNumber) + "\n");
}
} else {
throw DeviceInitializationFailure("Failed to check for active kernel driver on USB interface.");
void Interface::init() {
if (this->libUsbDevice == nullptr) {
throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer.");
}
}
}
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"
if (this->libUsbDeviceHandle == nullptr) {
throw DeviceInitializationFailure("Cannot initialise interface without libusb device handle.");
}
this->initialised = true;
}
void Interface::close() {
if (this->libUsbDeviceHandle != nullptr) {
this->release();
}
this->initialised = false;
}
void Interface::claim() {
int interfaceNumber = this->getNumber();
this->detachKernelDriver();
if (libusb_claim_interface(this->libUsbDeviceHandle, interfaceNumber) != 0) {
throw DeviceInitializationFailure(
"Failed to claim interface {" + std::to_string(interfaceNumber) + "} on USB device\n"
);
}
this->claimed = false;
this->claimed = true;
}
}
int Interface::read(unsigned char* buffer, unsigned char endPoint, size_t length, size_t timeout) {
int totalTransferred = 0;
int transferred = 0;
int libUsbStatusCode = 0;
void Interface::detachKernelDriver() {
int interfaceNumber = this->getNumber();
int libUsbStatusCode;
if ((libUsbStatusCode = libusb_kernel_driver_active(this->libUsbDeviceHandle, interfaceNumber)) != 0) {
if (libUsbStatusCode == 1) {
// A kernel driver is active on this interface. Attempt to detach it
if (libusb_detach_kernel_driver(this->libUsbDeviceHandle, interfaceNumber) != 0) {
throw DeviceInitializationFailure("Failed to detach kernel driver from interface " +
std::to_string(interfaceNumber) + "\n");
}
} else {
throw DeviceInitializationFailure("Failed to check for active kernel driver on USB interface.");
}
}
}
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"
);
}
this->claimed = false;
}
}
int Interface::read(unsigned char* buffer, unsigned char endPoint, size_t length, size_t timeout) {
int totalTransferred = 0;
int transferred = 0;
int libUsbStatusCode = 0;
while (length > totalTransferred) {
libUsbStatusCode = libusb_interrupt_transfer(
this->libUsbDeviceHandle,
endPoint,
buffer,
static_cast<int>(length),
&transferred,
static_cast<unsigned int>(timeout)
);
if (libUsbStatusCode != 0 && libUsbStatusCode != -7) {
throw DeviceCommunicationFailure(
"Failed to read from USB device. Error code returned: " + std::to_string(libUsbStatusCode)
);
}
totalTransferred += transferred;
}
return transferred;
}
void Interface::write(unsigned char* buffer, unsigned char endPoint, int length) {
int transferred = 0;
int libUsbStatusCode = 0;
while (length > totalTransferred) {
libUsbStatusCode = libusb_interrupt_transfer(
this->libUsbDeviceHandle,
endPoint,
buffer,
static_cast<int>(length),
length,
&transferred,
static_cast<unsigned int>(timeout)
0
);
if (libUsbStatusCode != 0 && libUsbStatusCode != -7) {
if (libUsbStatusCode != 0) {
throw DeviceCommunicationFailure(
"Failed to read from USB device. Error code returned: " + std::to_string(libUsbStatusCode)
);
}
totalTransferred += transferred;
}
return transferred;
}
void Interface::write(unsigned char* buffer, unsigned char endPoint, int length) {
int transferred = 0;
int libUsbStatusCode = 0;
libUsbStatusCode = libusb_interrupt_transfer(
this->libUsbDeviceHandle,
endPoint,
buffer,
length,
&transferred,
0
);
if (libUsbStatusCode != 0) {
throw DeviceCommunicationFailure(
"Failed to read from USB device. Error code returned: " + std::to_string(libUsbStatusCode)
);
}
}

View File

@@ -3,102 +3,107 @@
#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() {
libusb_init(&this->libUsbContext);
// libusb_set_option(this->libUsbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE);
auto devices = this->findMatchingDevices();
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) {
// TODO: implement support for multiple devices (maybe via serial number?)
throw DeviceInitializationFailure(
"Numerous devices of matching vendor & product ID found.\n"
"Please ensure that only one debug tool is connected and then try again."
);
}
// For now, just use the first device found.
auto device = devices.front();
this->setLibUsbDevice(device);
int libUsbStatusCode;
// Obtain a device handle from libusb
if ((libUsbStatusCode = libusb_open(libUsbDevice, &this->libUsbDeviceHandle)) < 0) {
throw DeviceInitializationFailure(
"Failed to open USB device - error code " + std::to_string(libUsbStatusCode) + " returned."
);
}
}
void UsbDevice::setConfiguration(int configIndex) {
libusb_config_descriptor* configDescriptor = {};
int libUsbStatusCode;
if ((libUsbStatusCode = libusb_get_config_descriptor(this->libUsbDevice, 0, &configDescriptor))) {
throw DeviceInitializationFailure(
"Failed to obtain USB configuration descriptor - error code " + std::to_string(libUsbStatusCode)
+ " returned."
);
}
if ((libUsbStatusCode = libusb_set_configuration(this->libUsbDeviceHandle, configDescriptor->bConfigurationValue))) {
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::optional<std::uint16_t> vendorId, std::optional<std::uint16_t> productId
) {
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) {
throw DeviceInitializationFailure(
"Failed to retrieve USB devices - return code: '" + std::to_string(libUsbStatusCode) + "'"
);
}
while ((device = devices[i++]) != nullptr) {
struct libusb_device_descriptor desc = {};
if ((libUsbStatusCode = libusb_get_device_descriptor(device, &desc)) < 0) {
Logger::warning("Failed to retrieve USB device descriptor - return code: '"
+ std::to_string(libUsbStatusCode) + "'");
continue;
if (devices.empty()) {
throw DeviceInitializationFailure("Failed to find USB device with matching vendor & product ID.");
}
if (desc.idVendor == vendorIdToMatch && desc.idProduct == productIdToMatch) {
matchedDevices.push_back(device);
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"
"Please ensure that only one debug tool is connected and then try again."
);
}
// For now, just use the first device found.
auto* device = devices.front();
this->setLibUsbDevice(device);
const int libUsbStatusCode = libusb_open(libUsbDevice, &this->libUsbDeviceHandle);
// Obtain a device handle from libusb
if (libUsbStatusCode < 0) {
throw DeviceInitializationFailure(
"Failed to open USB device - error code " + std::to_string(libUsbStatusCode) + " returned."
);
}
}
libusb_free_device_list(devices, 1);
return matchedDevices;
}
void UsbDevice::setConfiguration(int configIndex) {
libusb_config_descriptor* configDescriptor = {};
int libUsbStatusCode = libusb_get_config_descriptor(this->libUsbDevice, 0, &configDescriptor);
void UsbDevice::close() {
if (this->libUsbDeviceHandle != nullptr) {
libusb_close(this->libUsbDeviceHandle);
this->libUsbDeviceHandle = nullptr;
if (libUsbStatusCode < 0) {
throw DeviceInitializationFailure(
"Failed to obtain USB configuration descriptor - error code " + std::to_string(libUsbStatusCode)
+ " returned."
);
}
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);
}
if (this->libUsbContext != nullptr) {
libusb_exit(this->libUsbContext);
std::vector<libusb_device*> UsbDevice::findMatchingDevices(
std::optional<std::uint16_t> vendorId, std::optional<std::uint16_t> productId
) {
auto* libUsbContext = this->libUsbContext;
libusb_device** devices = nullptr;
libusb_device* device;
std::vector<libusb_device*> matchedDevices;
auto vendorIdToMatch = vendorId.value_or(this->vendorId);
auto productIdToMatch = productId.value_or(this->productId);
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 = {};
if ((libUsbStatusCode = libusb_get_device_descriptor(device, &desc)) < 0) {
Logger::warning("Failed to retrieve USB device descriptor - return code: '"
+ std::to_string(libUsbStatusCode) + "'");
continue;
}
if (desc.idVendor == vendorIdToMatch && desc.idProduct == productIdToMatch) {
matchedDevices.push_back(device);
}
}
libusb_free_device_list(devices, 1);
return matchedDevices;
}
void UsbDevice::close() {
if (this->libUsbDeviceHandle != nullptr) {
libusb_close(this->libUsbDeviceHandle);
this->libUsbDeviceHandle = nullptr;
}
if (this->libUsbContext != nullptr) {
libusb_exit(this->libUsbContext);
}
}
}