Removed using namespace directive for class member function definitions in source files
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user