Tidying low-level debug tool driver code:
- Use automatic objects for libusb/hidapi resources, where possible (to reduce manual resource management) - Removed unused/redundant code - Tidied HidInterface class - Tidied debug tool initialisation code - Other bits of tidying
This commit is contained in:
@@ -2,7 +2,6 @@ target_sources(
|
|||||||
Bloom
|
Bloom
|
||||||
PRIVATE
|
PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/USB/UsbDevice.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/USB/UsbDevice.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/USB/Interface.cpp
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/USB/HID/HidInterface.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/USB/HID/HidInterface.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AtmelICE/AtmelIce.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AtmelICE/AtmelIce.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/PowerDebugger/PowerDebugger.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/PowerDebugger/PowerDebugger.cpp
|
||||||
|
|||||||
@@ -8,22 +8,23 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
using Protocols::CmsisDap::Edbg::EdbgInterface;
|
||||||
|
|
||||||
|
AtmelIce::AtmelIce()
|
||||||
|
: UsbDevice(AtmelIce::USB_VENDOR_ID, AtmelIce::USB_PRODUCT_ID)
|
||||||
|
{}
|
||||||
|
|
||||||
void AtmelIce::init() {
|
void AtmelIce::init() {
|
||||||
UsbDevice::init();
|
UsbDevice::init();
|
||||||
|
|
||||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||||
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
|
auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId);
|
||||||
usbHidInterface.setNumber(0);
|
|
||||||
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
|
|
||||||
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
|
|
||||||
usbHidInterface.setVendorId(this->vendorId);
|
|
||||||
usbHidInterface.setProductId(this->productId);
|
|
||||||
|
|
||||||
if (!usbHidInterface.isInitialised()) {
|
this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber);
|
||||||
usbHidInterface.detachKernelDriver();
|
this->setConfiguration(0);
|
||||||
this->setConfiguration(0);
|
usbHidInterface.init();
|
||||||
usbHidInterface.init();
|
|
||||||
}
|
this->edbgInterface = std::make_unique<EdbgInterface>(std::move(usbHidInterface));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The Atmel-ICE EDBG/CMSIS-DAP interface doesn't operate properly when sending commands too quickly.
|
* The Atmel-ICE EDBG/CMSIS-DAP interface doesn't operate properly when sending commands too quickly.
|
||||||
@@ -31,15 +32,15 @@ namespace Bloom::DebugToolDrivers
|
|||||||
* Because of this, we have to enforce a minimum time gap between commands. See comment
|
* Because of this, we have to enforce a minimum time gap between commands. See comment
|
||||||
* in CmsisDapInterface class declaration for more info.
|
* in CmsisDapInterface class declaration for more info.
|
||||||
*/
|
*/
|
||||||
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
||||||
|
|
||||||
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
|
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
|
||||||
if (!this->sessionStarted) {
|
if (!this->sessionStarted) {
|
||||||
this->startSession();
|
this->startSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface.get());
|
||||||
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface);
|
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface.get());
|
||||||
|
|
||||||
this->setInitialised(true);
|
this->setInitialised(true);
|
||||||
}
|
}
|
||||||
@@ -49,7 +50,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
this->endSession();
|
this->endSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->getEdbgInterface().getUsbHidInterface().close();
|
this->edbgInterface->getUsbHidInterface().close();
|
||||||
UsbDevice::close();
|
UsbDevice::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::Discovery;
|
using namespace CommandFrames::Discovery;
|
||||||
using ResponseFrames::Discovery::ResponseId;
|
using ResponseFrames::Discovery::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Query(QueryContext::SERIAL_NUMBER)
|
Query(QueryContext::SERIAL_NUMBER)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = response.getPayloadData();
|
const auto data = response.getPayloadData();
|
||||||
return std::string(data.begin(), data.end());
|
return std::string(data.begin(), data.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
StartSession()
|
StartSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -91,7 +92,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
EndSession()
|
EndSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -45,16 +45,12 @@ namespace Bloom::DebugToolDrivers
|
|||||||
static const std::uint16_t USB_VENDOR_ID = 1003;
|
static const std::uint16_t USB_VENDOR_ID = 1003;
|
||||||
static const std::uint16_t USB_PRODUCT_ID = 8513;
|
static const std::uint16_t USB_PRODUCT_ID = 8513;
|
||||||
|
|
||||||
AtmelIce(): UsbDevice(AtmelIce::USB_VENDOR_ID, AtmelIce::USB_PRODUCT_ID) {}
|
AtmelIce();
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() {
|
|
||||||
return this->edbgInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override {
|
TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override {
|
||||||
return this->edbgAvr8Interface.get();
|
return this->edbgAvr8Interface.get();
|
||||||
}
|
}
|
||||||
@@ -65,7 +61,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
|
|
||||||
std::string getName() override {
|
std::string getName() override {
|
||||||
return "Atmel-ICE";
|
return "Atmel-ICE";
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the device serial number via the Discovery Protocol.
|
* Retrieves the device serial number via the Discovery Protocol.
|
||||||
@@ -93,7 +89,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
* Any non-EDBG CMSIS-DAP commands for the Atmel-ICE can be sent through the EdbgInterface (as the
|
* Any non-EDBG CMSIS-DAP commands for the Atmel-ICE can be sent through the EdbgInterface (as the
|
||||||
* EdbgInterface extends the CmsisDapInterface).
|
* EdbgInterface extends the CmsisDapInterface).
|
||||||
*/
|
*/
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
std::unique_ptr<Protocols::CmsisDap::Edbg::EdbgInterface> edbgInterface = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Atmel-ICE employs the EDBG AVR8 Generic protocol, for debugging AVR8 targets. This protocol is
|
* The Atmel-ICE employs the EDBG AVR8 Generic protocol, for debugging AVR8 targets. This protocol is
|
||||||
|
|||||||
@@ -8,36 +8,36 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
using Protocols::CmsisDap::Edbg::EdbgInterface;
|
||||||
using Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface;
|
using Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface;
|
||||||
|
|
||||||
|
CuriosityNano::CuriosityNano()
|
||||||
|
: UsbDevice(CuriosityNano::USB_VENDOR_ID, CuriosityNano::USB_PRODUCT_ID)
|
||||||
|
{}
|
||||||
|
|
||||||
void CuriosityNano::init() {
|
void CuriosityNano::init() {
|
||||||
UsbDevice::init();
|
UsbDevice::init();
|
||||||
|
|
||||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||||
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
|
auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId);
|
||||||
usbHidInterface.setNumber(0);
|
|
||||||
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
|
|
||||||
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
|
|
||||||
usbHidInterface.setVendorId(this->vendorId);
|
|
||||||
usbHidInterface.setProductId(this->productId);
|
|
||||||
|
|
||||||
if (!usbHidInterface.isInitialised()) {
|
this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber);
|
||||||
usbHidInterface.detachKernelDriver();
|
usbHidInterface.init();
|
||||||
usbHidInterface.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
this->edbgInterface = std::make_unique<EdbgInterface>(std::move(usbHidInterface));
|
||||||
|
|
||||||
|
this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
||||||
|
|
||||||
if (!this->sessionStarted) {
|
if (!this->sessionStarted) {
|
||||||
this->startSession();
|
this->startSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->targetPowerManagementInterface = std::make_unique<EdbgTargetPowerManagementInterface>(
|
this->targetPowerManagementInterface = std::make_unique<EdbgTargetPowerManagementInterface>(
|
||||||
this->edbgInterface
|
this->edbgInterface.get()
|
||||||
);
|
);
|
||||||
|
|
||||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface.get());
|
||||||
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface);
|
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface.get());
|
||||||
|
|
||||||
this->setInitialised(true);
|
this->setInitialised(true);
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
this->endSession();
|
this->endSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->getEdbgInterface().getUsbHidInterface().close();
|
this->edbgInterface->getUsbHidInterface().close();
|
||||||
UsbDevice::close();
|
UsbDevice::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::Discovery;
|
using namespace CommandFrames::Discovery;
|
||||||
using ResponseFrames::Discovery::ResponseId;
|
using ResponseFrames::Discovery::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Query(QueryContext::SERIAL_NUMBER)
|
Query(QueryContext::SERIAL_NUMBER)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = response.getPayloadData();
|
const auto data = response.getPayloadData();
|
||||||
return std::string(data.begin(), data.end());
|
return std::string(data.begin(), data.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
StartSession()
|
StartSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
EndSession()
|
EndSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -35,16 +35,12 @@ namespace Bloom::DebugToolDrivers
|
|||||||
static const std::uint16_t USB_VENDOR_ID = 1003;
|
static const std::uint16_t USB_VENDOR_ID = 1003;
|
||||||
static const std::uint16_t USB_PRODUCT_ID = 8565;
|
static const std::uint16_t USB_PRODUCT_ID = 8565;
|
||||||
|
|
||||||
CuriosityNano(): UsbDevice(CuriosityNano::USB_VENDOR_ID, CuriosityNano::USB_PRODUCT_ID) {}
|
CuriosityNano();
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() {
|
|
||||||
return this->edbgInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* getTargetPowerManagementInterface() override {
|
DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* getTargetPowerManagementInterface() override {
|
||||||
return this->targetPowerManagementInterface.get();
|
return this->targetPowerManagementInterface.get();
|
||||||
}
|
}
|
||||||
@@ -59,7 +55,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
|
|
||||||
std::string getName() override {
|
std::string getName() override {
|
||||||
return "Curiosity Nano";
|
return "Curiosity Nano";
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the device serial number via the Discovery Protocol.
|
* Retrieves the device serial number via the Discovery Protocol.
|
||||||
@@ -79,7 +75,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
void endSession();
|
void endSession();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
std::unique_ptr<Protocols::CmsisDap::Edbg::EdbgInterface> edbgInterface = nullptr;
|
||||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
||||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvrIspInterface> edbgAvrIspInterface = nullptr;
|
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvrIspInterface> edbgAvrIspInterface = nullptr;
|
||||||
std::unique_ptr<
|
std::unique_ptr<
|
||||||
|
|||||||
@@ -8,32 +8,33 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
using Protocols::CmsisDap::Edbg::EdbgInterface;
|
||||||
|
|
||||||
|
JtagIce3::JtagIce3()
|
||||||
|
: UsbDevice(JtagIce3::USB_VENDOR_ID, JtagIce3::USB_PRODUCT_ID)
|
||||||
|
{}
|
||||||
|
|
||||||
void JtagIce3::init() {
|
void JtagIce3::init() {
|
||||||
UsbDevice::init();
|
UsbDevice::init();
|
||||||
|
|
||||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||||
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
|
auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId);
|
||||||
usbHidInterface.setNumber(0);
|
|
||||||
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
|
|
||||||
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
|
|
||||||
usbHidInterface.setVendorId(this->vendorId);
|
|
||||||
usbHidInterface.setProductId(this->productId);
|
|
||||||
|
|
||||||
if (!usbHidInterface.isInitialised()) {
|
this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber);
|
||||||
usbHidInterface.detachKernelDriver();
|
this->setConfiguration(0);
|
||||||
this->setConfiguration(0);
|
usbHidInterface.init();
|
||||||
usbHidInterface.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
this->edbgInterface = std::make_unique<EdbgInterface>(std::move(usbHidInterface));
|
||||||
|
|
||||||
|
this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
||||||
|
|
||||||
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
|
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
|
||||||
if (!this->sessionStarted) {
|
if (!this->sessionStarted) {
|
||||||
this->startSession();
|
this->startSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface.get());
|
||||||
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface);
|
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface.get());
|
||||||
|
|
||||||
this->setInitialised(true);
|
this->setInitialised(true);
|
||||||
}
|
}
|
||||||
@@ -43,7 +44,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
this->endSession();
|
this->endSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->getEdbgInterface().getUsbHidInterface().close();
|
this->edbgInterface->getUsbHidInterface().close();
|
||||||
UsbDevice::close();
|
UsbDevice::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::Discovery;
|
using namespace CommandFrames::Discovery;
|
||||||
using ResponseFrames::Discovery::ResponseId;
|
using ResponseFrames::Discovery::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Query(QueryContext::SERIAL_NUMBER)
|
Query(QueryContext::SERIAL_NUMBER)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = response.getPayloadData();
|
const auto data = response.getPayloadData();
|
||||||
return std::string(data.begin(), data.end());
|
return std::string(data.begin(), data.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
StartSession()
|
StartSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
EndSession()
|
EndSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -21,16 +21,12 @@ namespace Bloom::DebugToolDrivers
|
|||||||
static const std::uint16_t USB_VENDOR_ID = 1003;
|
static const std::uint16_t USB_VENDOR_ID = 1003;
|
||||||
static const std::uint16_t USB_PRODUCT_ID = 8512;
|
static const std::uint16_t USB_PRODUCT_ID = 8512;
|
||||||
|
|
||||||
JtagIce3(): UsbDevice(JtagIce3::USB_VENDOR_ID, JtagIce3::USB_PRODUCT_ID) {}
|
JtagIce3();
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() {
|
|
||||||
return this->edbgInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override {
|
TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override {
|
||||||
return this->edbgAvr8Interface.get();
|
return this->edbgAvr8Interface.get();
|
||||||
}
|
}
|
||||||
@@ -41,7 +37,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
|
|
||||||
std::string getName() override {
|
std::string getName() override {
|
||||||
return "JTAGICE3";
|
return "JTAGICE3";
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the device serial number via the Discovery Protocol.
|
* Retrieves the device serial number via the Discovery Protocol.
|
||||||
@@ -61,7 +57,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
void endSession();
|
void endSession();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
std::unique_ptr<Protocols::CmsisDap::Edbg::EdbgInterface> edbgInterface = nullptr;
|
||||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
||||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvrIspInterface> edbgAvrIspInterface = nullptr;
|
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvrIspInterface> edbgAvrIspInterface = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -8,30 +8,32 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
using Protocols::CmsisDap::Edbg::EdbgInterface;
|
||||||
|
|
||||||
|
MplabPickit4::MplabPickit4()
|
||||||
|
: UsbDevice(MplabPickit4::USB_VENDOR_ID, MplabPickit4::USB_PRODUCT_ID)
|
||||||
|
{}
|
||||||
|
|
||||||
void MplabPickit4::init() {
|
void MplabPickit4::init() {
|
||||||
UsbDevice::init();
|
UsbDevice::init();
|
||||||
|
|
||||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||||
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
|
auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId);
|
||||||
usbHidInterface.setNumber(0);
|
|
||||||
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
|
|
||||||
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
|
|
||||||
usbHidInterface.setVendorId(this->vendorId);
|
|
||||||
usbHidInterface.setProductId(this->productId);
|
|
||||||
|
|
||||||
if (!usbHidInterface.isInitialised()) {
|
this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber);
|
||||||
usbHidInterface.init();
|
usbHidInterface.init();
|
||||||
}
|
|
||||||
|
|
||||||
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
this->edbgInterface = std::make_unique<EdbgInterface>(std::move(usbHidInterface));
|
||||||
|
|
||||||
|
this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
||||||
|
|
||||||
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
|
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
|
||||||
if (!this->sessionStarted) {
|
if (!this->sessionStarted) {
|
||||||
this->startSession();
|
this->startSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface.get());
|
||||||
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface);
|
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface.get());
|
||||||
|
|
||||||
this->setInitialised(true);
|
this->setInitialised(true);
|
||||||
}
|
}
|
||||||
@@ -41,7 +43,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
this->endSession();
|
this->endSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->getEdbgInterface().getUsbHidInterface().close();
|
this->edbgInterface->getUsbHidInterface().close();
|
||||||
UsbDevice::close();
|
UsbDevice::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::Discovery;
|
using namespace CommandFrames::Discovery;
|
||||||
using ResponseFrames::Discovery::ResponseId;
|
using ResponseFrames::Discovery::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Query(QueryContext::SERIAL_NUMBER)
|
Query(QueryContext::SERIAL_NUMBER)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -59,7 +61,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = response.getPayloadData();
|
const auto data = response.getPayloadData();
|
||||||
return std::string(data.begin(), data.end());
|
return std::string(data.begin(), data.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +69,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
StartSession()
|
StartSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -83,7 +85,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
EndSession()
|
EndSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -33,16 +33,12 @@ namespace Bloom::DebugToolDrivers
|
|||||||
static const std::uint16_t USB_VENDOR_ID = 1003;
|
static const std::uint16_t USB_VENDOR_ID = 1003;
|
||||||
static const std::uint16_t USB_PRODUCT_ID = 8567;
|
static const std::uint16_t USB_PRODUCT_ID = 8567;
|
||||||
|
|
||||||
MplabPickit4(): UsbDevice(MplabPickit4::USB_VENDOR_ID, MplabPickit4::USB_PRODUCT_ID) {}
|
MplabPickit4();
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() {
|
|
||||||
return this->edbgInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override {
|
TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override {
|
||||||
return this->edbgAvr8Interface.get();
|
return this->edbgAvr8Interface.get();
|
||||||
}
|
}
|
||||||
@@ -53,7 +49,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
|
|
||||||
std::string getName() override {
|
std::string getName() override {
|
||||||
return "MPLAB PICkit 4";
|
return "MPLAB PICkit 4";
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the device serial number via the Discovery Protocol.
|
* Retrieves the device serial number via the Discovery Protocol.
|
||||||
@@ -73,7 +69,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
void endSession();
|
void endSession();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
std::unique_ptr<Protocols::CmsisDap::Edbg::EdbgInterface> edbgInterface = nullptr;
|
||||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
||||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvrIspInterface> edbgAvrIspInterface = nullptr;
|
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvrIspInterface> edbgAvrIspInterface = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -8,30 +8,32 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
using Protocols::CmsisDap::Edbg::EdbgInterface;
|
||||||
|
|
||||||
|
MplabSnap::MplabSnap()
|
||||||
|
: UsbDevice(MplabSnap::USB_VENDOR_ID, MplabSnap::USB_PRODUCT_ID)
|
||||||
|
{}
|
||||||
|
|
||||||
void MplabSnap::init() {
|
void MplabSnap::init() {
|
||||||
UsbDevice::init();
|
UsbDevice::init();
|
||||||
|
|
||||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||||
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
|
auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId);
|
||||||
usbHidInterface.setNumber(0);
|
|
||||||
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
|
|
||||||
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
|
|
||||||
usbHidInterface.setVendorId(this->vendorId);
|
|
||||||
usbHidInterface.setProductId(this->productId);
|
|
||||||
|
|
||||||
if (!usbHidInterface.isInitialised()) {
|
this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber);
|
||||||
usbHidInterface.init();
|
usbHidInterface.init();
|
||||||
}
|
|
||||||
|
|
||||||
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
this->edbgInterface = std::make_unique<EdbgInterface>(std::move(usbHidInterface));
|
||||||
|
|
||||||
|
this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
||||||
|
|
||||||
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
|
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
|
||||||
if (!this->sessionStarted) {
|
if (!this->sessionStarted) {
|
||||||
this->startSession();
|
this->startSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface.get());
|
||||||
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface);
|
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface.get());
|
||||||
|
|
||||||
this->setInitialised(true);
|
this->setInitialised(true);
|
||||||
}
|
}
|
||||||
@@ -41,7 +43,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
this->endSession();
|
this->endSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->getEdbgInterface().getUsbHidInterface().close();
|
this->edbgInterface->getUsbHidInterface().close();
|
||||||
UsbDevice::close();
|
UsbDevice::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::Discovery;
|
using namespace CommandFrames::Discovery;
|
||||||
using ResponseFrames::Discovery::ResponseId;
|
using ResponseFrames::Discovery::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Query(QueryContext::SERIAL_NUMBER)
|
Query(QueryContext::SERIAL_NUMBER)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -59,7 +61,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = response.getPayloadData();
|
const auto data = response.getPayloadData();
|
||||||
return std::string(data.begin(), data.end());
|
return std::string(data.begin(), data.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +69,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
StartSession()
|
StartSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -83,7 +85,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
EndSession()
|
EndSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -39,16 +39,12 @@ namespace Bloom::DebugToolDrivers
|
|||||||
static const std::uint16_t USB_VENDOR_ID = 1003;
|
static const std::uint16_t USB_VENDOR_ID = 1003;
|
||||||
static const std::uint16_t USB_PRODUCT_ID = 8576;
|
static const std::uint16_t USB_PRODUCT_ID = 8576;
|
||||||
|
|
||||||
MplabSnap(): UsbDevice(MplabSnap::USB_VENDOR_ID, MplabSnap::USB_PRODUCT_ID) {}
|
MplabSnap();
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() {
|
|
||||||
return this->edbgInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override {
|
TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override {
|
||||||
return this->edbgAvr8Interface.get();
|
return this->edbgAvr8Interface.get();
|
||||||
}
|
}
|
||||||
@@ -59,7 +55,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
|
|
||||||
std::string getName() override {
|
std::string getName() override {
|
||||||
return "MPLAB Snap";
|
return "MPLAB Snap";
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the device serial number via the Discovery Protocol.
|
* Retrieves the device serial number via the Discovery Protocol.
|
||||||
@@ -79,7 +75,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
void endSession();
|
void endSession();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
std::unique_ptr<Protocols::CmsisDap::Edbg::EdbgInterface> edbgInterface = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The MPLAB Snap employs the EDBG AVR8 Generic protocol, for debugging AVR8 targets. This protocol is
|
* The MPLAB Snap employs the EDBG AVR8 Generic protocol, for debugging AVR8 targets. This protocol is
|
||||||
|
|||||||
@@ -8,36 +8,32 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
using Protocols::CmsisDap::Edbg::EdbgInterface;
|
||||||
|
|
||||||
|
PowerDebugger::PowerDebugger()
|
||||||
|
: UsbDevice(PowerDebugger::USB_VENDOR_ID, PowerDebugger::USB_PRODUCT_ID)
|
||||||
|
{}
|
||||||
|
|
||||||
void PowerDebugger::init() {
|
void PowerDebugger::init() {
|
||||||
UsbDevice::init();
|
UsbDevice::init();
|
||||||
|
|
||||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||||
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
|
auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId);
|
||||||
usbHidInterface.setNumber(0);
|
|
||||||
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
|
|
||||||
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
|
|
||||||
usbHidInterface.setVendorId(this->vendorId);
|
|
||||||
usbHidInterface.setProductId(this->productId);
|
|
||||||
|
|
||||||
if (!usbHidInterface.isInitialised()) {
|
this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber);
|
||||||
usbHidInterface.init();
|
usbHidInterface.init();
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
this->edbgInterface = std::make_unique<EdbgInterface>(std::move(usbHidInterface));
|
||||||
* The Power Debugger EDBG/CMSIS-DAP interface doesn't operate properly when sending commands too quickly.
|
|
||||||
*
|
this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
||||||
* 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.
|
// We don't need to claim the CMSISDAP interface here as the HIDAPI will have already done so.
|
||||||
if (!this->sessionStarted) {
|
if (!this->sessionStarted) {
|
||||||
this->startSession();
|
this->startSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface.get());
|
||||||
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface);
|
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface.get());
|
||||||
|
|
||||||
this->setInitialised(true);
|
this->setInitialised(true);
|
||||||
}
|
}
|
||||||
@@ -47,7 +43,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
this->endSession();
|
this->endSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->getEdbgInterface().getUsbHidInterface().close();
|
this->edbgInterface->getUsbHidInterface().close();
|
||||||
UsbDevice::close();
|
UsbDevice::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +51,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::Discovery;
|
using namespace CommandFrames::Discovery;
|
||||||
using ResponseFrames::Discovery::ResponseId;
|
using ResponseFrames::Discovery::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Query(QueryContext::SERIAL_NUMBER)
|
Query(QueryContext::SERIAL_NUMBER)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -65,7 +61,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = response.getPayloadData();
|
const auto data = response.getPayloadData();
|
||||||
return std::string(data.begin(), data.end());
|
return std::string(data.begin(), data.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +69,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
StartSession()
|
StartSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -91,7 +87,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
EndSession()
|
EndSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -32,16 +32,12 @@ namespace Bloom::DebugToolDrivers
|
|||||||
static const std::uint16_t USB_VENDOR_ID = 1003;
|
static const std::uint16_t USB_VENDOR_ID = 1003;
|
||||||
static const std::uint16_t USB_PRODUCT_ID = 8516;
|
static const std::uint16_t USB_PRODUCT_ID = 8516;
|
||||||
|
|
||||||
PowerDebugger(): UsbDevice(PowerDebugger::USB_VENDOR_ID, PowerDebugger::USB_PRODUCT_ID) {}
|
PowerDebugger();
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() {
|
|
||||||
return this->edbgInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override {
|
TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override {
|
||||||
return this->edbgAvr8Interface.get();
|
return this->edbgAvr8Interface.get();
|
||||||
}
|
}
|
||||||
@@ -52,7 +48,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
|
|
||||||
std::string getName() override {
|
std::string getName() override {
|
||||||
return "Power Debugger";
|
return "Power Debugger";
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the device serial number via the Discovery Protocol.
|
* Retrieves the device serial number via the Discovery Protocol.
|
||||||
@@ -80,7 +76,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
* Any non-EDBG CMSIS-DAP commands for the Power Debugger can be sent through the EDBGInterface (as the
|
* Any non-EDBG CMSIS-DAP commands for the Power Debugger can be sent through the EDBGInterface (as the
|
||||||
* EdbgInterface extends the CmsisDapInterface).
|
* EdbgInterface extends the CmsisDapInterface).
|
||||||
*/
|
*/
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
std::unique_ptr<Protocols::CmsisDap::Edbg::EdbgInterface> edbgInterface = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Power Debugger employs the EDBG AVR8Generic protocol for interfacing with AVR8 targets.
|
* The Power Debugger employs the EDBG AVR8Generic protocol for interfacing with AVR8 targets.
|
||||||
|
|||||||
@@ -8,36 +8,36 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
using Protocols::CmsisDap::Edbg::EdbgInterface;
|
||||||
using Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface;
|
using Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface;
|
||||||
|
|
||||||
|
XplainedMini::XplainedMini()
|
||||||
|
: UsbDevice(XplainedMini::USB_VENDOR_ID, XplainedMini::USB_PRODUCT_ID)
|
||||||
|
{}
|
||||||
|
|
||||||
void XplainedMini::init() {
|
void XplainedMini::init() {
|
||||||
UsbDevice::init();
|
UsbDevice::init();
|
||||||
|
|
||||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||||
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
|
auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId);
|
||||||
usbHidInterface.setNumber(0);
|
|
||||||
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
|
|
||||||
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
|
|
||||||
usbHidInterface.setVendorId(this->vendorId);
|
|
||||||
usbHidInterface.setProductId(this->productId);
|
|
||||||
|
|
||||||
if (!usbHidInterface.isInitialised()) {
|
this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber);
|
||||||
usbHidInterface.detachKernelDriver();
|
usbHidInterface.init();
|
||||||
usbHidInterface.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
this->edbgInterface = std::make_unique<EdbgInterface>(std::move(usbHidInterface));
|
||||||
|
|
||||||
|
this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
||||||
|
|
||||||
if (!this->sessionStarted) {
|
if (!this->sessionStarted) {
|
||||||
this->startSession();
|
this->startSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->targetPowerManagementInterface = std::make_unique<EdbgTargetPowerManagementInterface>(
|
this->targetPowerManagementInterface = std::make_unique<EdbgTargetPowerManagementInterface>(
|
||||||
this->edbgInterface
|
this->edbgInterface.get()
|
||||||
);
|
);
|
||||||
|
|
||||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface.get());
|
||||||
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface);
|
this->edbgAvrIspInterface = std::make_unique<EdbgAvrIspInterface>(this->edbgInterface.get());
|
||||||
|
|
||||||
this->setInitialised(true);
|
this->setInitialised(true);
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
this->endSession();
|
this->endSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->getEdbgInterface().getUsbHidInterface().close();
|
this->edbgInterface->getUsbHidInterface().close();
|
||||||
UsbDevice::close();
|
UsbDevice::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::Discovery;
|
using namespace CommandFrames::Discovery;
|
||||||
using ResponseFrames::Discovery::ResponseId;
|
using ResponseFrames::Discovery::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Query(QueryContext::SERIAL_NUMBER)
|
Query(QueryContext::SERIAL_NUMBER)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
StartSession()
|
StartSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
EndSession()
|
EndSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -35,16 +35,12 @@ namespace Bloom::DebugToolDrivers
|
|||||||
static const std::uint16_t USB_VENDOR_ID = 1003;
|
static const std::uint16_t USB_VENDOR_ID = 1003;
|
||||||
static const std::uint16_t USB_PRODUCT_ID = 8517;
|
static const std::uint16_t USB_PRODUCT_ID = 8517;
|
||||||
|
|
||||||
XplainedMini(): UsbDevice(XplainedMini::USB_VENDOR_ID, XplainedMini::USB_PRODUCT_ID) {}
|
XplainedMini();
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() {
|
|
||||||
return this->edbgInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* getTargetPowerManagementInterface() override {
|
DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* getTargetPowerManagementInterface() override {
|
||||||
return this->targetPowerManagementInterface.get();
|
return this->targetPowerManagementInterface.get();
|
||||||
}
|
}
|
||||||
@@ -59,7 +55,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
|
|
||||||
std::string getName() override {
|
std::string getName() override {
|
||||||
return "Xplained Mini";
|
return "Xplained Mini";
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the device serial number via the Discovery Protocol.
|
* Retrieves the device serial number via the Discovery Protocol.
|
||||||
@@ -79,7 +75,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
void endSession();
|
void endSession();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
std::unique_ptr<Protocols::CmsisDap::Edbg::EdbgInterface> edbgInterface = nullptr;
|
||||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
||||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvrIspInterface> edbgAvrIspInterface = nullptr;
|
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvrIspInterface> edbgAvrIspInterface = nullptr;
|
||||||
std::unique_ptr<
|
std::unique_ptr<
|
||||||
|
|||||||
@@ -8,35 +8,35 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
using Protocols::CmsisDap::Edbg::EdbgInterface;
|
||||||
using Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface;
|
using Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface;
|
||||||
|
|
||||||
|
XplainedNano::XplainedNano()
|
||||||
|
: UsbDevice(XplainedNano::USB_VENDOR_ID, XplainedNano::USB_PRODUCT_ID)
|
||||||
|
{}
|
||||||
|
|
||||||
void XplainedNano::init() {
|
void XplainedNano::init() {
|
||||||
UsbDevice::init();
|
UsbDevice::init();
|
||||||
|
|
||||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||||
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
|
auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId);
|
||||||
usbHidInterface.setNumber(0);
|
|
||||||
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
|
|
||||||
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
|
|
||||||
usbHidInterface.setVendorId(this->vendorId);
|
|
||||||
usbHidInterface.setProductId(this->productId);
|
|
||||||
|
|
||||||
if (!usbHidInterface.isInitialised()) {
|
this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber);
|
||||||
usbHidInterface.detachKernelDriver();
|
usbHidInterface.init();
|
||||||
usbHidInterface.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
this->edbgInterface = std::make_unique<EdbgInterface>(std::move(usbHidInterface));
|
||||||
|
|
||||||
|
this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
||||||
|
|
||||||
if (!this->sessionStarted) {
|
if (!this->sessionStarted) {
|
||||||
this->startSession();
|
this->startSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->targetPowerManagementInterface = std::make_unique<EdbgTargetPowerManagementInterface>(
|
this->targetPowerManagementInterface = std::make_unique<EdbgTargetPowerManagementInterface>(
|
||||||
this->edbgInterface
|
this->edbgInterface.get()
|
||||||
);
|
);
|
||||||
|
|
||||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface.get());
|
||||||
this->setInitialised(true);
|
this->setInitialised(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
this->endSession();
|
this->endSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->getEdbgInterface().getUsbHidInterface().close();
|
this->edbgInterface->getUsbHidInterface().close();
|
||||||
UsbDevice::close();
|
UsbDevice::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::Discovery;
|
using namespace CommandFrames::Discovery;
|
||||||
using ResponseFrames::Discovery::ResponseId;
|
using ResponseFrames::Discovery::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Query(QueryContext::SERIAL_NUMBER)
|
Query(QueryContext::SERIAL_NUMBER)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = response.getPayloadData();
|
const auto data = response.getPayloadData();
|
||||||
return std::string(data.begin(), data.end());
|
return std::string(data.begin(), data.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
StartSession()
|
StartSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
EndSession()
|
EndSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -34,16 +34,12 @@ namespace Bloom::DebugToolDrivers
|
|||||||
static const std::uint16_t USB_VENDOR_ID = 1003;
|
static const std::uint16_t USB_VENDOR_ID = 1003;
|
||||||
static const std::uint16_t USB_PRODUCT_ID = 8517;
|
static const std::uint16_t USB_PRODUCT_ID = 8517;
|
||||||
|
|
||||||
XplainedNano(): UsbDevice(XplainedNano::USB_VENDOR_ID, XplainedNano::USB_PRODUCT_ID) {}
|
XplainedNano();
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() {
|
|
||||||
return this->edbgInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* getTargetPowerManagementInterface() override {
|
DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* getTargetPowerManagementInterface() override {
|
||||||
return this->targetPowerManagementInterface.get();
|
return this->targetPowerManagementInterface.get();
|
||||||
}
|
}
|
||||||
@@ -54,7 +50,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
|
|
||||||
std::string getName() override {
|
std::string getName() override {
|
||||||
return "Xplained Nano";
|
return "Xplained Nano";
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the device serial number via the Discovery Protocol.
|
* Retrieves the device serial number via the Discovery Protocol.
|
||||||
@@ -74,7 +70,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
void endSession();
|
void endSession();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
std::unique_ptr<Protocols::CmsisDap::Edbg::EdbgInterface> edbgInterface = nullptr;
|
||||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
||||||
std::unique_ptr<
|
std::unique_ptr<
|
||||||
Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface
|
Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface
|
||||||
|
|||||||
@@ -8,35 +8,35 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace Protocols::CmsisDap::Edbg::Avr;
|
using namespace Protocols::CmsisDap::Edbg::Avr;
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
using Protocols::CmsisDap::Edbg::EdbgInterface;
|
||||||
using Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface;
|
using Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface;
|
||||||
|
|
||||||
|
XplainedPro::XplainedPro()
|
||||||
|
: UsbDevice(XplainedPro::USB_VENDOR_ID, XplainedPro::USB_PRODUCT_ID)
|
||||||
|
{}
|
||||||
|
|
||||||
void XplainedPro::init() {
|
void XplainedPro::init() {
|
||||||
UsbDevice::init();
|
UsbDevice::init();
|
||||||
|
|
||||||
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
// TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number
|
||||||
auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface();
|
auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId);
|
||||||
usbHidInterface.setNumber(0);
|
|
||||||
usbHidInterface.setLibUsbDevice(this->libUsbDevice);
|
|
||||||
usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle);
|
|
||||||
usbHidInterface.setVendorId(this->vendorId);
|
|
||||||
usbHidInterface.setProductId(this->productId);
|
|
||||||
|
|
||||||
if (!usbHidInterface.isInitialised()) {
|
this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber);
|
||||||
usbHidInterface.detachKernelDriver();
|
usbHidInterface.init();
|
||||||
usbHidInterface.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
this->edbgInterface = std::make_unique<EdbgInterface>(std::move(usbHidInterface));
|
||||||
|
|
||||||
|
this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35));
|
||||||
|
|
||||||
if (!this->sessionStarted) {
|
if (!this->sessionStarted) {
|
||||||
this->startSession();
|
this->startSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->targetPowerManagementInterface = std::make_unique<EdbgTargetPowerManagementInterface>(
|
this->targetPowerManagementInterface = std::make_unique<EdbgTargetPowerManagementInterface>(
|
||||||
this->edbgInterface
|
this->edbgInterface.get()
|
||||||
);
|
);
|
||||||
|
|
||||||
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface);
|
this->edbgAvr8Interface = std::make_unique<EdbgAvr8Interface>(this->edbgInterface.get());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The Xplained Pro debug tool returns incorrect data for any read memory command that exceeds 256 bytes in the
|
* The Xplained Pro debug tool returns incorrect data for any read memory command that exceeds 256 bytes in the
|
||||||
@@ -54,7 +54,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
this->endSession();
|
this->endSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->getEdbgInterface().getUsbHidInterface().close();
|
this->edbgInterface->getUsbHidInterface().close();
|
||||||
UsbDevice::close();
|
UsbDevice::close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::Discovery;
|
using namespace CommandFrames::Discovery;
|
||||||
using ResponseFrames::Discovery::ResponseId;
|
using ResponseFrames::Discovery::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Query(QueryContext::SERIAL_NUMBER)
|
Query(QueryContext::SERIAL_NUMBER)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
StartSession()
|
StartSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
using namespace CommandFrames::HouseKeeping;
|
using namespace CommandFrames::HouseKeeping;
|
||||||
using ResponseFrames::HouseKeeping::ResponseId;
|
using ResponseFrames::HouseKeeping::ResponseId;
|
||||||
|
|
||||||
auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
EndSession()
|
EndSession()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -34,16 +34,12 @@ namespace Bloom::DebugToolDrivers
|
|||||||
static const std::uint16_t USB_VENDOR_ID = 1003;
|
static const std::uint16_t USB_VENDOR_ID = 1003;
|
||||||
static const std::uint16_t USB_PRODUCT_ID = 8465;
|
static const std::uint16_t USB_PRODUCT_ID = 8465;
|
||||||
|
|
||||||
XplainedPro(): UsbDevice(XplainedPro::USB_VENDOR_ID, XplainedPro::USB_PRODUCT_ID) {}
|
XplainedPro();
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() {
|
|
||||||
return this->edbgInterface;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* getTargetPowerManagementInterface() override {
|
DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* getTargetPowerManagementInterface() override {
|
||||||
return this->targetPowerManagementInterface.get();
|
return this->targetPowerManagementInterface.get();
|
||||||
}
|
}
|
||||||
@@ -54,7 +50,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
|
|
||||||
std::string getName() override {
|
std::string getName() override {
|
||||||
return "Xplained Pro";
|
return "Xplained Pro";
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the device serial number via the Discovery Protocol.
|
* Retrieves the device serial number via the Discovery Protocol.
|
||||||
@@ -74,7 +70,7 @@ namespace Bloom::DebugToolDrivers
|
|||||||
void endSession();
|
void endSession();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface();
|
std::unique_ptr<Protocols::CmsisDap::Edbg::EdbgInterface> edbgInterface = nullptr;
|
||||||
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
std::unique_ptr<Protocols::CmsisDap::Edbg::Avr::EdbgAvr8Interface> edbgAvr8Interface = nullptr;
|
||||||
|
|
||||||
std::unique_ptr<
|
std::unique_ptr<
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
|||||||
{
|
{
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
CmsisDapInterface::CmsisDapInterface(Usb::HidInterface&& usbHidInterface)
|
||||||
|
: usbHidInterface(std::move(usbHidInterface))
|
||||||
|
{}
|
||||||
|
|
||||||
void CmsisDapInterface::sendCommand(const Command& cmsisDapCommand) {
|
void CmsisDapInterface::sendCommand(const Command& cmsisDapCommand) {
|
||||||
if (this->msSendCommandDelay.count() > 0) {
|
if (this->msSendCommandDelay.count() > 0) {
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|||||||
@@ -21,14 +21,14 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
|||||||
class CmsisDapInterface
|
class CmsisDapInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CmsisDapInterface() = default;
|
explicit CmsisDapInterface(Usb::HidInterface&& usbHidInterface);
|
||||||
|
|
||||||
virtual ~CmsisDapInterface() = default;
|
virtual ~CmsisDapInterface() = default;
|
||||||
|
|
||||||
CmsisDapInterface(const CmsisDapInterface& other) = default;
|
CmsisDapInterface(const CmsisDapInterface& other) = delete;
|
||||||
CmsisDapInterface(CmsisDapInterface&& other) = default;
|
CmsisDapInterface(CmsisDapInterface&& other) = delete;
|
||||||
|
CmsisDapInterface& operator = (const CmsisDapInterface& other) = delete;
|
||||||
CmsisDapInterface& operator = (const CmsisDapInterface& other) = default;
|
CmsisDapInterface& operator = (CmsisDapInterface&& other) = delete;
|
||||||
CmsisDapInterface& operator = (CmsisDapInterface&& other) = default;
|
|
||||||
|
|
||||||
Usb::HidInterface& getUsbHidInterface() {
|
Usb::HidInterface& getUsbHidInterface() {
|
||||||
return this->usbHidInterface;
|
return this->usbHidInterface;
|
||||||
@@ -65,7 +65,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
|||||||
"CMSIS Response type must be derived from the Response class."
|
"CMSIS Response type must be derived from the Response class."
|
||||||
);
|
);
|
||||||
|
|
||||||
const auto rawResponse = this->getUsbHidInterface().read(15000);
|
const auto rawResponse = this->getUsbHidInterface().read(std::chrono::milliseconds(15000));
|
||||||
|
|
||||||
if (rawResponse.empty()) {
|
if (rawResponse.empty()) {
|
||||||
throw Exceptions::DeviceCommunicationFailure("Empty CMSIS-DAP response received");
|
throw Exceptions::DeviceCommunicationFailure("Empty CMSIS-DAP response received");
|
||||||
@@ -113,7 +113,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap
|
|||||||
* amongst devices, so we'll need to be able to preActivationConfigure the CMSISDAPInterface from a
|
* amongst devices, so we'll need to be able to preActivationConfigure the CMSISDAPInterface from a
|
||||||
* higher level. For an example, see the constructor of the AtmelIce device class.
|
* higher level. For an example, see the constructor of the AtmelIce device class.
|
||||||
*/
|
*/
|
||||||
Usb::HidInterface usbHidInterface = Usb::HidInterface();
|
Usb::HidInterface usbHidInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some CMSIS-DAP debug tools fail to operate properly when we send commands too quickly. Even if we've
|
* Some CMSIS-DAP debug tools fail to operate properly when we send commands too quickly. Even if we've
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#include "EdbgControlCommandFrame.hpp"
|
#include "EdbgControlCommandFrame.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
using Bloom::Targets::TargetRegisterType;
|
using Bloom::Targets::TargetRegisterType;
|
||||||
using Bloom::Targets::TargetRegisters;
|
using Bloom::Targets::TargetRegisters;
|
||||||
|
|
||||||
EdbgAvr8Interface::EdbgAvr8Interface(EdbgInterface& edbgInterface)
|
EdbgAvr8Interface::EdbgAvr8Interface(EdbgInterface* edbgInterface)
|
||||||
: edbgInterface(edbgInterface)
|
: edbgInterface(edbgInterface)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::stop() {
|
void EdbgAvr8Interface::stop() {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Stop()
|
Stop()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -210,7 +210,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
|
|
||||||
void EdbgAvr8Interface::run() {
|
void EdbgAvr8Interface::run() {
|
||||||
this->clearEvents();
|
this->clearEvents();
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Run()
|
Run()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
|
|
||||||
void EdbgAvr8Interface::runTo(TargetProgramCounter address) {
|
void EdbgAvr8Interface::runTo(TargetProgramCounter address) {
|
||||||
this->clearEvents();
|
this->clearEvents();
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
RunTo(address)
|
RunTo(address)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::step() {
|
void EdbgAvr8Interface::step() {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Step()
|
Step()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -247,7 +247,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::reset() {
|
void EdbgAvr8Interface::reset() {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Reset()
|
Reset()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -335,7 +335,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
this->stop();
|
this->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
GetProgramCounter()
|
GetProgramCounter()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -355,7 +355,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
* The program counter will be given in byte address form, but the EDBG tool will be expecting it in word
|
* The program counter will be given in byte address form, but the EDBG tool will be expecting it in word
|
||||||
* address (16-bit) form. This is why we divide it by 2.
|
* address (16-bit) form. This is why we divide it by 2.
|
||||||
*/
|
*/
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
SetProgramCounter(programCounter / 2)
|
SetProgramCounter(programCounter / 2)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -390,7 +390,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
return TargetSignature(signatureMemory[0], signatureMemory[1], signatureMemory[2]);
|
return TargetSignature(signatureMemory[0], signatureMemory[1], signatureMemory[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
GetDeviceId()
|
GetDeviceId()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::setBreakpoint(TargetMemoryAddress address) {
|
void EdbgAvr8Interface::setBreakpoint(TargetMemoryAddress address) {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
SetSoftwareBreakpoints({address})
|
SetSoftwareBreakpoints({address})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -412,7 +412,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::clearBreakpoint(TargetMemoryAddress address) {
|
void EdbgAvr8Interface::clearBreakpoint(TargetMemoryAddress address) {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
ClearSoftwareBreakpoints({address})
|
ClearSoftwareBreakpoints({address})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -422,7 +422,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::clearAllBreakpoints() {
|
void EdbgAvr8Interface::clearAllBreakpoints() {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
ClearAllSoftwareBreakpoints()
|
ClearAllSoftwareBreakpoints()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -750,7 +750,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
throw Exception("AVR8 erase command not supported for debugWire config variant.");
|
throw Exception("AVR8 erase command not supported for debugWire config variant.");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
EraseMemory(
|
EraseMemory(
|
||||||
section.has_value()
|
section.has_value()
|
||||||
? section == ProgramMemorySection::BOOT
|
? section == ProgramMemorySection::BOOT
|
||||||
@@ -785,7 +785,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
EnterProgrammingMode()
|
EnterProgrammingMode()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -801,7 +801,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
LeaveProgrammingMode()
|
LeaveProgrammingMode()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -909,7 +909,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::setParameter(const Avr8EdbgParameter& parameter, const std::vector<unsigned char>& value) {
|
void EdbgAvr8Interface::setParameter(const Avr8EdbgParameter& parameter, const std::vector<unsigned char>& value) {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
SetParameter(parameter, value)
|
SetParameter(parameter, value)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -919,7 +919,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> EdbgAvr8Interface::getParameter(const Avr8EdbgParameter& parameter, std::uint8_t size) {
|
std::vector<unsigned char> EdbgAvr8Interface::getParameter(const Avr8EdbgParameter& parameter, std::uint8_t size) {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
GetParameter(parameter, size)
|
GetParameter(parameter, size)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1371,7 +1371,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::activatePhysical(bool applyExternalReset) {
|
void EdbgAvr8Interface::activatePhysical(bool applyExternalReset) {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
ActivatePhysical(applyExternalReset)
|
ActivatePhysical(applyExternalReset)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1390,7 +1390,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::deactivatePhysical() {
|
void EdbgAvr8Interface::deactivatePhysical() {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
DeactivatePhysical()
|
DeactivatePhysical()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1410,7 +1410,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
* value of the breakAfterAttach flag. So we still expect a stop event to be received shortly after issuing
|
* value of the breakAfterAttach flag. So we still expect a stop event to be received shortly after issuing
|
||||||
* the attach command.
|
* the attach command.
|
||||||
*/
|
*/
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Attach(
|
Attach(
|
||||||
this->configVariant != Avr8ConfigVariant::MEGAJTAG
|
this->configVariant != Avr8ConfigVariant::MEGAJTAG
|
||||||
)
|
)
|
||||||
@@ -1434,7 +1434,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::detach() {
|
void EdbgAvr8Interface::detach() {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
Detach()
|
Detach()
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1684,7 +1684,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
* that isn't actually the memory data (like the command ID, version bytes, etc). I could have sought the
|
* that isn't actually the memory data (like the command ID, version bytes, etc). I could have sought the
|
||||||
* actual value but who has the time. It won't exceed 20 bytes. Bite me.
|
* actual value but who has the time. It won't exceed 20 bytes. Bite me.
|
||||||
*/
|
*/
|
||||||
auto singlePacketSize = static_cast<std::uint32_t>(this->edbgInterface.getUsbHidInputReportSize() - 20);
|
auto singlePacketSize = static_cast<std::uint32_t>(this->edbgInterface->getUsbHidInputReportSize() - 20);
|
||||||
auto totalResponsePackets = std::ceil(static_cast<float>(bytes) / static_cast<float>(singlePacketSize));
|
auto totalResponsePackets = std::ceil(static_cast<float>(bytes) / static_cast<float>(singlePacketSize));
|
||||||
auto totalReadsRequired = std::ceil(static_cast<float>(totalResponsePackets) / 2);
|
auto totalReadsRequired = std::ceil(static_cast<float>(totalResponsePackets) / 2);
|
||||||
|
|
||||||
@@ -1713,7 +1713,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
ReadMemory(
|
ReadMemory(
|
||||||
type,
|
type,
|
||||||
startAddress,
|
startAddress,
|
||||||
@@ -1780,7 +1780,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
WriteMemory(
|
WriteMemory(
|
||||||
type,
|
type,
|
||||||
startAddress,
|
startAddress,
|
||||||
@@ -1811,7 +1811,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvr8Interface::disableDebugWire() {
|
void EdbgAvr8Interface::disableDebugWire() {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
DisableDebugWire()
|
DisableDebugWire()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
class EdbgAvr8Interface: public TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface
|
class EdbgAvr8Interface: public TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit EdbgAvr8Interface(EdbgInterface& edbgInterface);
|
explicit EdbgAvr8Interface(EdbgInterface* edbgInterface);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some EDBG devices don't seem to operate correctly when actioning the masked memory read EDBG command. The
|
* Some EDBG devices don't seem to operate correctly when actioning the masked memory read EDBG command. The
|
||||||
@@ -276,7 +276,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
*
|
*
|
||||||
* Every EDBG based debug tool that utilises this implementation must provide access to its EDBG interface.
|
* Every EDBG based debug tool that utilises this implementation must provide access to its EDBG interface.
|
||||||
*/
|
*/
|
||||||
EdbgInterface& edbgInterface;
|
EdbgInterface* edbgInterface = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project's AVR8 target configuration.
|
* Project's AVR8 target configuration.
|
||||||
|
|||||||
@@ -26,12 +26,16 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
|
|
||||||
using Exceptions::TargetOperationFailure;
|
using Exceptions::TargetOperationFailure;
|
||||||
|
|
||||||
|
EdbgAvrIspInterface::EdbgAvrIspInterface(EdbgInterface* edbgInterface)
|
||||||
|
: edbgInterface(edbgInterface)
|
||||||
|
{}
|
||||||
|
|
||||||
void EdbgAvrIspInterface::setIspParameters(const Targets::Microchip::Avr::IspParameters& ispParameters) {
|
void EdbgAvrIspInterface::setIspParameters(const Targets::Microchip::Avr::IspParameters& ispParameters) {
|
||||||
this->ispParameters = ispParameters;
|
this->ispParameters = ispParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvrIspInterface::activate() {
|
void EdbgAvrIspInterface::activate() {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
EnterProgrammingMode(
|
EnterProgrammingMode(
|
||||||
this->ispParameters.programModeTimeout,
|
this->ispParameters.programModeTimeout,
|
||||||
this->ispParameters.programModeStabilizationDelay,
|
this->ispParameters.programModeStabilizationDelay,
|
||||||
@@ -52,7 +56,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvrIspInterface::deactivate() {
|
void EdbgAvrIspInterface::deactivate() {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
LeaveProgrammingMode(
|
LeaveProgrammingMode(
|
||||||
this->ispParameters.programModePreDelay,
|
this->ispParameters.programModePreDelay,
|
||||||
this->ispParameters.programModePostDelay
|
this->ispParameters.programModePostDelay
|
||||||
@@ -74,7 +78,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
Fuse EdbgAvrIspInterface::readFuse(FuseType fuseType) {
|
Fuse EdbgAvrIspInterface::readFuse(FuseType fuseType) {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
ReadFuse(fuseType, this->ispParameters.readFusePollIndex)
|
ReadFuse(fuseType, this->ispParameters.readFusePollIndex)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -93,7 +97,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned char EdbgAvrIspInterface::readLockBitByte() {
|
unsigned char EdbgAvrIspInterface::readLockBitByte() {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
ReadLock(this->ispParameters.readLockPollIndex)
|
ReadLock(this->ispParameters.readLockPollIndex)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -112,7 +116,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgAvrIspInterface::programFuse(Targets::Microchip::Avr::Fuse fuse) {
|
void EdbgAvrIspInterface::programFuse(Targets::Microchip::Avr::Fuse fuse) {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
ProgramFuse(fuse.type, fuse.value)
|
ProgramFuse(fuse.type, fuse.value)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -125,7 +129,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned char EdbgAvrIspInterface::readSignatureByte(std::uint8_t signatureByteAddress) {
|
unsigned char EdbgAvrIspInterface::readSignatureByte(std::uint8_t signatureByteAddress) {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
ReadSignature(signatureByteAddress, this->ispParameters.readSignaturePollIndex)
|
ReadSignature(signatureByteAddress, this->ispParameters.readSignaturePollIndex)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
class EdbgAvrIspInterface: public TargetInterfaces::Microchip::Avr::AvrIspInterface
|
class EdbgAvrIspInterface: public TargetInterfaces::Microchip::Avr::AvrIspInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit EdbgAvrIspInterface(EdbgInterface& edbgInterface)
|
explicit EdbgAvrIspInterface(EdbgInterface* edbgInterface);
|
||||||
: edbgInterface(edbgInterface)
|
|
||||||
{};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The EdbgAvrIspInterface doesn't actually require any config from the user, at this point in time. So this
|
* The EdbgAvrIspInterface doesn't actually require any config from the user, at this point in time. So this
|
||||||
@@ -89,7 +87,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr
|
|||||||
*
|
*
|
||||||
* Every EDBG based debug tool that utilises this implementation must provide access to its EDBG interface.
|
* Every EDBG based debug tool that utilises this implementation must provide access to its EDBG interface.
|
||||||
*/
|
*/
|
||||||
EdbgInterface& edbgInterface;
|
EdbgInterface* edbgInterface;
|
||||||
|
|
||||||
Targets::Microchip::Avr::IspParameters ispParameters;
|
Targets::Microchip::Avr::IspParameters ispParameters;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
|
|||||||
{
|
{
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
EdbgInterface::EdbgInterface(Usb::HidInterface&& usbHidInterface)
|
||||||
|
: CmsisDapInterface(std::move(usbHidInterface))
|
||||||
|
{}
|
||||||
|
|
||||||
Protocols::CmsisDap::Response EdbgInterface::sendAvrCommandsAndWaitForResponse(
|
Protocols::CmsisDap::Response EdbgInterface::sendAvrCommandsAndWaitForResponse(
|
||||||
const std::vector<Avr::AvrCommand>& avrCommands
|
const std::vector<Avr::AvrCommand>& avrCommands
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
|
|||||||
class EdbgInterface: public CmsisDapInterface
|
class EdbgInterface: public CmsisDapInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit EdbgInterface() = default;
|
explicit EdbgInterface(Usb::HidInterface&& usbHidInterface);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send an AvrCommandFrame to the debug tool and wait for a response.
|
* Send an AvrCommandFrame to the debug tool and wait for a response.
|
||||||
|
|||||||
@@ -12,8 +12,12 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
|
|||||||
using Protocols::CmsisDap::Edbg::Avr::CommandFrames::EdbgControl::GetParameter;
|
using Protocols::CmsisDap::Edbg::Avr::CommandFrames::EdbgControl::GetParameter;
|
||||||
using Protocols::CmsisDap::Edbg::Avr::CommandFrames::EdbgControl::SetParameter;
|
using Protocols::CmsisDap::Edbg::Avr::CommandFrames::EdbgControl::SetParameter;
|
||||||
|
|
||||||
|
EdbgTargetPowerManagementInterface::EdbgTargetPowerManagementInterface(EdbgInterface* edbgInterface)
|
||||||
|
: edbgInterface(edbgInterface)
|
||||||
|
{}
|
||||||
|
|
||||||
void EdbgTargetPowerManagementInterface::enableTargetPower() {
|
void EdbgTargetPowerManagementInterface::enableTargetPower() {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
SetParameter(EdbgParameters::CONTROL_TARGET_POWER, 0x01)
|
SetParameter(EdbgParameters::CONTROL_TARGET_POWER, 0x01)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -23,7 +27,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EdbgTargetPowerManagementInterface::disableTargetPower() {
|
void EdbgTargetPowerManagementInterface::disableTargetPower() {
|
||||||
auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame(
|
auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame(
|
||||||
SetParameter(EdbgParameters::CONTROL_TARGET_POWER, 0x00)
|
SetParameter(EdbgParameters::CONTROL_TARGET_POWER, 0x00)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
|
|||||||
class EdbgTargetPowerManagementInterface: public TargetInterfaces::TargetPowerManagementInterface
|
class EdbgTargetPowerManagementInterface: public TargetInterfaces::TargetPowerManagementInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit EdbgTargetPowerManagementInterface(EdbgInterface& edbgInterface)
|
explicit EdbgTargetPowerManagementInterface(EdbgInterface* edbgInterface);
|
||||||
: edbgInterface(edbgInterface) {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Issues a Set Parameter command to the EDBG tool, to enable the target power.
|
* Issues a Set Parameter command to the EDBG tool, to enable the target power.
|
||||||
@@ -24,6 +23,6 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg
|
|||||||
void disableTargetPower() override;
|
void disableTargetPower() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EdbgInterface& edbgInterface;
|
EdbgInterface* edbgInterface;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,65 +9,71 @@ namespace Bloom::Usb
|
|||||||
{
|
{
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
HidInterface::HidInterface(std::uint8_t interfaceNumber, std::uint16_t vendorId, std::uint16_t productId)
|
||||||
|
: interfaceNumber(interfaceNumber)
|
||||||
|
, vendorId(vendorId)
|
||||||
|
, productId(productId)
|
||||||
|
{}
|
||||||
|
|
||||||
void HidInterface::init() {
|
void HidInterface::init() {
|
||||||
if (this->libUsbDevice == nullptr) {
|
::hid_init();
|
||||||
throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer.");
|
::hid_device* hidDevice = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
hid_init();
|
const auto hidInterfacePath = this->getHidDevicePath();
|
||||||
hid_device* hidDevice = nullptr;
|
|
||||||
|
|
||||||
std::string hidInterfacePath = this->getDevicePathByInterfaceNumber(this->getNumber());
|
|
||||||
Logger::debug("HID device path: " + hidInterfacePath);
|
Logger::debug("HID device path: " + hidInterfacePath);
|
||||||
|
|
||||||
if ((hidDevice = hid_open_path(hidInterfacePath.c_str())) == nullptr) {
|
if ((hidDevice = ::hid_open_path(hidInterfacePath.c_str())) == nullptr) {
|
||||||
throw DeviceInitializationFailure("Failed to open HID device via hidapi.");
|
throw DeviceInitializationFailure("Failed to open HID device via hidapi.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hidDevice->input_ep_max_packet_size < 1) {
|
this->hidDevice.reset(hidDevice);
|
||||||
|
|
||||||
|
if (this->hidDevice->input_ep_max_packet_size < 1) {
|
||||||
throw DeviceInitializationFailure(
|
throw DeviceInitializationFailure(
|
||||||
"Invalid max packet size for USB endpoint, on interface "
|
"Invalid max packet size for USB endpoint, on interface "
|
||||||
+ std::to_string(this->getNumber())
|
+ std::to_string(this->interfaceNumber)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->setHidDevice(hidDevice);
|
this->inputReportSize = static_cast<std::size_t>(this->hidDevice->input_ep_max_packet_size);
|
||||||
this->setInputReportSize(static_cast<std::size_t>(hidDevice->input_ep_max_packet_size));
|
|
||||||
this->libUsbDeviceHandle = hidDevice->device_handle;
|
|
||||||
this->initialised = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HidInterface::close() {
|
void HidInterface::close() {
|
||||||
auto* hidDevice = this->getHidDevice();
|
this->hidDevice.reset();
|
||||||
|
::hid_exit();
|
||||||
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> HidInterface::read(std::optional<std::chrono::milliseconds> timeout) {
|
||||||
std::vector<unsigned char> output;
|
auto output = std::vector<unsigned char>();
|
||||||
auto readSize = this->getInputReportSize();
|
|
||||||
|
|
||||||
// Attempt to read the first HID report packet, and whatever is left after that.
|
const auto readSize = this->inputReportSize;
|
||||||
output.resize(readSize);
|
auto transferredByteCount = int(0);
|
||||||
auto transferredByteCount = this->read(output.data(), readSize, timeout);
|
auto totalByteCount = std::size_t(0);
|
||||||
auto totalByteCount = transferredByteCount;
|
|
||||||
|
|
||||||
while (transferredByteCount >= readSize) {
|
do {
|
||||||
output.resize(totalByteCount + readSize);
|
output.resize(totalByteCount + readSize, 0x00);
|
||||||
|
|
||||||
transferredByteCount = this->read(output.data() + totalByteCount, readSize, 1);
|
transferredByteCount = ::hid_read_timeout(
|
||||||
totalByteCount += transferredByteCount;
|
this->hidDevice.get(),
|
||||||
}
|
output.data() + totalByteCount,
|
||||||
|
readSize,
|
||||||
|
timeout.has_value() ? static_cast<int>(timeout->count()) : -1
|
||||||
|
);
|
||||||
|
|
||||||
output.resize(totalByteCount);
|
if (transferredByteCount == -1) {
|
||||||
|
throw DeviceCommunicationFailure("Failed to read from HID device.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalByteCount == 0) {
|
||||||
|
// After the first read, set the timeout to 1 millisecond, as we don't want to wait for subsequent data
|
||||||
|
timeout = std::chrono::milliseconds(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
totalByteCount += static_cast<std::size_t>(transferredByteCount);
|
||||||
|
|
||||||
|
} while (transferredByteCount >= readSize);
|
||||||
|
|
||||||
|
output.resize(totalByteCount, 0x00);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,49 +95,35 @@ namespace Bloom::Usb
|
|||||||
int transferred = 0;
|
int transferred = 0;
|
||||||
const auto length = buffer.size();
|
const auto length = buffer.size();
|
||||||
|
|
||||||
if ((transferred = hid_write(this->getHidDevice(), buffer.data(), length)) != length) {
|
if ((transferred = ::hid_write(this->hidDevice.get(), buffer.data(), length)) != length) {
|
||||||
Logger::debug("Attempted to write " + std::to_string(length)
|
Logger::debug("Attempted to write " + std::to_string(length)
|
||||||
+ " bytes to HID interface. Bytes written: " + std::to_string(transferred));
|
+ " bytes to HID interface. Bytes written: " + std::to_string(transferred));
|
||||||
throw DeviceCommunicationFailure("Failed to write data to HID interface.");
|
throw DeviceCommunicationFailure("Failed to write data to HID interface.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t HidInterface::read(unsigned char* buffer, std::size_t maxLength, unsigned int timeout) {
|
std::string HidInterface::getHidDevicePath() {
|
||||||
int transferred;
|
const auto hidDeviceInfoList = std::unique_ptr<::hid_device_info, decltype(&::hid_free_enumeration)>(
|
||||||
|
::hid_enumerate(this->vendorId, this->productId),
|
||||||
if ((transferred = hid_read_timeout(
|
::hid_free_enumeration
|
||||||
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) {
|
auto matchedDevice = std::optional<::hid_device_info*>();
|
||||||
if (hidDeviceInfoList->interface_number == interfaceNumber) {
|
|
||||||
|
auto* hidDeviceInfo = hidDeviceInfoList.get();
|
||||||
|
while (hidDeviceInfo != nullptr) {
|
||||||
|
if (hidDeviceInfo->interface_number == this->interfaceNumber) {
|
||||||
|
matchedDevice = hidDeviceInfo;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
hidDeviceInfoList = hidDeviceInfoList->next;
|
hidDeviceInfo = hidDeviceInfoList->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hidDeviceInfoList == nullptr) {
|
if (!matchedDevice.has_value()) {
|
||||||
throw DeviceInitializationFailure("Failed to match interface number with HID interface.");
|
throw DeviceInitializationFailure("Failed to match interface number with HID interface.");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto path = std::string(hidDeviceInfoList->path);
|
return std::string(matchedDevice.value()->path);
|
||||||
hid_free_enumeration(hidDeviceInfoList);
|
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <optional>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#include "hidapi.hpp"
|
#include "hidapi.hpp"
|
||||||
#include "src/DebugToolDrivers/USB/Interface.hpp"
|
|
||||||
|
|
||||||
namespace Bloom::Usb
|
namespace Bloom::Usb
|
||||||
{
|
{
|
||||||
@@ -15,35 +17,46 @@ namespace Bloom::Usb
|
|||||||
* Currently, this interface only supports single-report HID implementations. HID interfaces with
|
* Currently, this interface only supports single-report HID implementations. HID interfaces with
|
||||||
* multiple reports will be supported as-and-when we need it.
|
* multiple reports will be supported as-and-when we need it.
|
||||||
*/
|
*/
|
||||||
class HidInterface: public Interface
|
class HidInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
std::uint8_t interfaceNumber = 0;
|
||||||
|
|
||||||
|
HidInterface(
|
||||||
|
std::uint8_t interfaceNumber,
|
||||||
|
std::uint16_t vendorId,
|
||||||
|
std::uint16_t productId
|
||||||
|
);
|
||||||
|
|
||||||
|
HidInterface(const HidInterface& other) = delete;
|
||||||
|
HidInterface& operator = (const HidInterface& other) = delete;
|
||||||
|
|
||||||
|
HidInterface(HidInterface&& other) = default;
|
||||||
|
HidInterface& operator = (HidInterface&& other) = default;
|
||||||
|
|
||||||
std::size_t getInputReportSize() const {
|
std::size_t getInputReportSize() const {
|
||||||
return this->inputReportSize;
|
return this->inputReportSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Claims the USB HID interface and obtains a hid_device instance
|
* Obtains a hid_device instance and claims the HID interface on the device.
|
||||||
*/
|
*/
|
||||||
void init() override;
|
void init();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the hid_device and releases any claimed interfaces (via hid_close())
|
* Releases any claimed interfaces and closes the hid_device.
|
||||||
*/
|
*/
|
||||||
void close() override;
|
void close();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads as much data as the device has to offer, into a vector.
|
* Reads as much data as the device has to offer, into a vector.
|
||||||
*
|
*
|
||||||
* If `timeout` is set to 0, this method will block until at least one HID report
|
|
||||||
* packet is received.
|
|
||||||
*
|
|
||||||
* @param timeout
|
* @param timeout
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* A vector of the data received from the device.
|
* A vector of the data received from the device.
|
||||||
*/
|
*/
|
||||||
std::vector<unsigned char> read(unsigned int timeout = 0);
|
std::vector<unsigned char> read(std::optional<std::chrono::milliseconds> timeout = std::nullopt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes buffer to HID output endpoint.
|
* Writes buffer to HID output endpoint.
|
||||||
@@ -52,59 +65,20 @@ namespace Bloom::Usb
|
|||||||
*/
|
*/
|
||||||
void write(std::vector<unsigned char>&& buffer);
|
void write(std::vector<unsigned char>&& buffer);
|
||||||
|
|
||||||
/**
|
std::string getHidDevicePath();
|
||||||
* Resolves a device path from a USB interface number.
|
|
||||||
*
|
|
||||||
* @param interfaceNumber
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string getDevicePathByInterfaceNumber(const std::uint16_t& interfaceNumber);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
hid_device* getHidDevice() const {
|
|
||||||
return this->hidDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
using HidDeviceType = std::unique_ptr<::hid_device, decltype(&::hid_close)>;
|
||||||
* The HIDAPI library provides a hid_device data structure to represent a USB HID interface.
|
|
||||||
*
|
HidDeviceType hidDevice = HidDeviceType(nullptr, ::hid_close);
|
||||||
* @see hidapi.hpp or the HIDAPI documentation for more on this.
|
|
||||||
*/
|
|
||||||
hid_device* hidDevice = nullptr;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All HID reports have a fixed report length. This means that every packet
|
* All HID reports have a fixed report length. This means that every packet we send or receive to/from an HID
|
||||||
* we send or receive to/from an HID endpoint must be equal to the report length in size.
|
* endpoint must be equal (in size) to the report length.
|
||||||
*
|
|
||||||
* The default input report size is 64 bytes, but this is overridden at interface initialisation.
|
|
||||||
* @see definition of init() for more on this.
|
|
||||||
*/
|
*/
|
||||||
std::size_t inputReportSize = 64;
|
std::size_t inputReportSize = 64;
|
||||||
|
|
||||||
void setHidDevice(hid_device* hidDevice) {
|
std::uint16_t vendorId = 0;
|
||||||
this->hidDevice = hidDevice;
|
std::uint16_t productId = 0;
|
||||||
}
|
|
||||||
|
|
||||||
void setInputReportSize(const std::size_t& inputReportSize) {
|
|
||||||
this->inputReportSize = inputReportSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a maximum of `maxLength` bytes into `buffer`, from the HID input endpoint.
|
|
||||||
*
|
|
||||||
* Keeping this in the private scope to enforce use of vector<unsigned char>. See read()
|
|
||||||
* method in public scope.
|
|
||||||
*
|
|
||||||
* @TODO: Do we really need this? Why not just have the one that accepts the vector. Review
|
|
||||||
*
|
|
||||||
* @param buffer
|
|
||||||
* @param maxLength
|
|
||||||
* @param timeout
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* Number of bytes read.
|
|
||||||
*/
|
|
||||||
std::size_t read(unsigned char* buffer, std::size_t maxLength, unsigned int timeout);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,123 +0,0 @@
|
|||||||
#include "Interface.hpp"
|
|
||||||
|
|
||||||
#include <libusb-1.0/libusb.h>
|
|
||||||
|
|
||||||
#include "src/TargetController/Exceptions/DeviceFailure.hpp"
|
|
||||||
#include "src/TargetController/Exceptions/DeviceCommunicationFailure.hpp"
|
|
||||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
|
||||||
|
|
||||||
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::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;
|
|
||||||
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <libusb-1.0/libusb.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "UsbDevice.hpp"
|
|
||||||
|
|
||||||
namespace Bloom::Usb
|
|
||||||
{
|
|
||||||
class Interface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Interface(const std::uint8_t& interfaceNumber = 0) {
|
|
||||||
this->setNumber(interfaceNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~Interface() = default;
|
|
||||||
|
|
||||||
Interface(const Interface& other) = default;
|
|
||||||
Interface(Interface&& other) = default;
|
|
||||||
|
|
||||||
Interface& operator = (const Interface& other) = default;
|
|
||||||
Interface& operator = (Interface&& other) = default;
|
|
||||||
|
|
||||||
void setLibUsbDevice(libusb_device* libUsbDevice) {
|
|
||||||
this->libUsbDevice = libUsbDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLibUsbDeviceHandle(libusb_device_handle* libUsbDeviceHandle) {
|
|
||||||
this->libUsbDeviceHandle = libUsbDeviceHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint8_t getNumber() const {
|
|
||||||
return this->number;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setNumber(std::uint8_t number) {
|
|
||||||
this->number = number;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string& getName() const {
|
|
||||||
return this->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setName(const std::string& name) {
|
|
||||||
this->name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isClaimed() const {
|
|
||||||
return this->claimed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isInitialised() const {
|
|
||||||
return this->initialised;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint16_t getVendorId() const {
|
|
||||||
return this->vendorId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setVendorId(std::uint16_t vendorId) {
|
|
||||||
this->vendorId = vendorId;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint16_t getProductId() const {
|
|
||||||
return this->productId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setProductId(std::uint16_t productId) {
|
|
||||||
this->productId = productId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to obtain a device descriptor and device handle via libusb.
|
|
||||||
*/
|
|
||||||
virtual void init();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Releases the interface and closes the device descriptor.
|
|
||||||
*/
|
|
||||||
virtual void close();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to claim the interface
|
|
||||||
*/
|
|
||||||
void claim();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If a kernel driver is attached to the interface, this method will detach it.
|
|
||||||
*/
|
|
||||||
void detachKernelDriver();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Releases the interface, if claimed.
|
|
||||||
*/
|
|
||||||
void release();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @TODO Remove or refactor these (read() and write()) - they're not currently used
|
|
||||||
*
|
|
||||||
* @param buffer
|
|
||||||
* @param endPoint
|
|
||||||
* @param length
|
|
||||||
* @param timeout
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
virtual int read(unsigned char* buffer, unsigned char endPoint, std::size_t length, std::size_t timeout);
|
|
||||||
virtual void write(unsigned char* buffer, unsigned char endPoint, int length);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
libusb_device* libUsbDevice = nullptr;
|
|
||||||
libusb_device_handle* libUsbDeviceHandle = nullptr;
|
|
||||||
|
|
||||||
std::uint16_t vendorId = 0;
|
|
||||||
std::uint16_t productId = 0;
|
|
||||||
|
|
||||||
std::uint8_t number = 0;
|
|
||||||
std::string name;
|
|
||||||
|
|
||||||
bool initialised = false;
|
|
||||||
bool claimed = false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "UsbDevice.hpp"
|
#include "UsbDevice.hpp"
|
||||||
|
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
#include "src/Logger/Logger.hpp"
|
#include "src/Logger/Logger.hpp"
|
||||||
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
#include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp"
|
||||||
|
|
||||||
@@ -7,103 +9,134 @@ namespace Bloom::Usb
|
|||||||
{
|
{
|
||||||
using namespace Bloom::Exceptions;
|
using namespace Bloom::Exceptions;
|
||||||
|
|
||||||
|
UsbDevice::UsbDevice(std::uint16_t vendorId, std::uint16_t productId)
|
||||||
|
: vendorId(vendorId)
|
||||||
|
, productId(productId)
|
||||||
|
{
|
||||||
|
if (!UsbDevice::libusbContext) {
|
||||||
|
::libusb_context* libusbContext = nullptr;
|
||||||
|
::libusb_init(&libusbContext);
|
||||||
|
UsbDevice::libusbContext.reset(libusbContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UsbDevice::init() {
|
void UsbDevice::init() {
|
||||||
libusb_init(&this->libUsbContext);
|
// ::libusb_set_option(this->libusbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE);
|
||||||
// libusb_set_option(this->libUsbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE);
|
auto devices = this->findMatchingDevices(this->vendorId, this->productId);
|
||||||
auto devices = this->findMatchingDevices();
|
|
||||||
|
|
||||||
if (devices.empty()) {
|
if (devices.empty()) {
|
||||||
throw DeviceInitializationFailure("Failed to find USB device with matching vendor & product ID.");
|
throw DeviceInitializationFailure(
|
||||||
|
"Failed to find USB device with matching vendor and product ID. Please examine the debug tool's USB "
|
||||||
|
"connection, as well as the selected environment's debug tool configuration in bloom.yaml"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (devices.size() > 1) {
|
if (devices.size() > 1) {
|
||||||
// TODO: implement support for multiple devices (maybe via serial number?)
|
// TODO: implement support for multiple devices via serial number matching?
|
||||||
throw DeviceInitializationFailure(
|
throw DeviceInitializationFailure(
|
||||||
"Numerous devices of matching vendor & product ID found.\n"
|
"Numerous devices of matching vendor and product ID found.\n"
|
||||||
"Please ensure that only one debug tool is connected and then try again."
|
"Please ensure that only one debug tool is connected and then try again."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now, just use the first device found.
|
// For now, just use the first device found.
|
||||||
auto* device = devices.front();
|
this->libusbDevice.swap(devices.front());
|
||||||
this->setLibUsbDevice(device);
|
::libusb_device_handle* deviceHandle = nullptr;
|
||||||
|
|
||||||
const int libUsbStatusCode = libusb_open(libUsbDevice, &this->libUsbDeviceHandle);
|
const int libusbStatusCode = ::libusb_open(this->libusbDevice.get(), &deviceHandle);
|
||||||
|
|
||||||
// Obtain a device handle from libusb
|
if (libusbStatusCode < 0) {
|
||||||
if (libUsbStatusCode < 0) {
|
// Failed to a device handle from libusb
|
||||||
throw DeviceInitializationFailure(
|
throw DeviceInitializationFailure(
|
||||||
"Failed to open USB device - error code " + std::to_string(libUsbStatusCode) + " returned."
|
"Failed to open USB device - error code " + std::to_string(libusbStatusCode) + " returned."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->libusbDeviceHandle.reset(deviceHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UsbDevice::setConfiguration(int configIndex) {
|
void UsbDevice::setConfiguration(int configIndex) {
|
||||||
libusb_config_descriptor* configDescriptor = {};
|
::libusb_config_descriptor* configDescriptor = {};
|
||||||
int libUsbStatusCode = libusb_get_config_descriptor(this->libUsbDevice, 0, &configDescriptor);
|
int libusbStatusCode = ::libusb_get_config_descriptor(this->libusbDevice.get(), 0, &configDescriptor);
|
||||||
|
|
||||||
if (libUsbStatusCode < 0) {
|
if (libusbStatusCode < 0) {
|
||||||
throw DeviceInitializationFailure(
|
throw DeviceInitializationFailure(
|
||||||
"Failed to obtain USB configuration descriptor - error code " + std::to_string(libUsbStatusCode)
|
"Failed to obtain USB configuration descriptor - error code " + std::to_string(libusbStatusCode)
|
||||||
+ " returned."
|
+ " returned."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
libUsbStatusCode = libusb_set_configuration(this->libUsbDeviceHandle, configDescriptor->bConfigurationValue);
|
libusbStatusCode = ::libusb_set_configuration(
|
||||||
if (libUsbStatusCode < 0) {
|
this->libusbDeviceHandle.get(),
|
||||||
|
configDescriptor->bConfigurationValue
|
||||||
|
);
|
||||||
|
|
||||||
|
if (libusbStatusCode < 0) {
|
||||||
throw DeviceInitializationFailure(
|
throw DeviceInitializationFailure(
|
||||||
"Failed to set USB configuration - error code " + std::to_string(libUsbStatusCode) + " returned."
|
"Failed to set USB configuration - error code " + std::to_string(libusbStatusCode) + " returned."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
libusb_free_config_descriptor(configDescriptor);
|
::libusb_free_config_descriptor(configDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<libusb_device*> UsbDevice::findMatchingDevices(
|
std::vector<LibusbDeviceType> UsbDevice::findMatchingDevices(
|
||||||
std::optional<std::uint16_t> vendorId, std::optional<std::uint16_t> productId
|
std::uint16_t vendorId, std::uint16_t productId
|
||||||
) {
|
) {
|
||||||
auto* libUsbContext = this->libUsbContext;
|
::libusb_device** devices = nullptr;
|
||||||
libusb_device** devices = nullptr;
|
::libusb_device* device;
|
||||||
libusb_device* device;
|
std::vector<LibusbDeviceType> matchedDevices;
|
||||||
std::vector<libusb_device*> matchedDevices;
|
|
||||||
|
|
||||||
auto vendorIdToMatch = vendorId.value_or(this->vendorId);
|
auto libusbStatusCode = ::libusb_get_device_list(UsbDevice::libusbContext.get(), &devices);
|
||||||
auto productIdToMatch = productId.value_or(this->productId);
|
if (libusbStatusCode < 0) {
|
||||||
|
|
||||||
ssize_t libUsbStatusCode = libusb_get_device_list(libUsbContext, &devices);
|
|
||||||
if (libUsbStatusCode < 0) {
|
|
||||||
throw DeviceInitializationFailure(
|
throw DeviceInitializationFailure(
|
||||||
"Failed to retrieve USB devices - return code: '" + std::to_string(libUsbStatusCode) + "'"
|
"Failed to retrieve USB devices - return code: '" + std::to_string(libusbStatusCode) + "'"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t i = 0;
|
ssize_t i = 0;
|
||||||
while ((device = devices[i++]) != nullptr) {
|
while ((device = devices[i++]) != nullptr) {
|
||||||
struct libusb_device_descriptor desc = {};
|
auto libusbDevice = LibusbDeviceType(device, ::libusb_unref_device);
|
||||||
|
struct ::libusb_device_descriptor desc = {};
|
||||||
|
|
||||||
if ((libUsbStatusCode = libusb_get_device_descriptor(device, &desc)) < 0) {
|
if ((libusbStatusCode = ::libusb_get_device_descriptor(device, &desc)) < 0) {
|
||||||
Logger::warning("Failed to retrieve USB device descriptor - return code: '"
|
Logger::warning("Failed to retrieve USB device descriptor - return code: '"
|
||||||
+ std::to_string(libUsbStatusCode) + "'");
|
+ std::to_string(libusbStatusCode) + "'");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc.idVendor == vendorIdToMatch && desc.idProduct == productIdToMatch) {
|
if (desc.idVendor != vendorId || desc.idProduct != productId) {
|
||||||
matchedDevices.push_back(device);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matchedDevices.emplace_back(std::move(libusbDevice));
|
||||||
}
|
}
|
||||||
|
|
||||||
libusb_free_device_list(devices, 1);
|
::libusb_free_device_list(devices, 0);
|
||||||
return matchedDevices;
|
return matchedDevices;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UsbDevice::close() {
|
void UsbDevice::detachKernelDriverFromInterface(std::uint8_t interfaceNumber) {
|
||||||
if (this->libUsbDeviceHandle != nullptr) {
|
const auto libusbStatusCode = ::libusb_kernel_driver_active(this->libusbDeviceHandle.get(), interfaceNumber);
|
||||||
libusb_close(this->libUsbDeviceHandle);
|
|
||||||
this->libUsbDeviceHandle = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->libUsbContext != nullptr) {
|
if (libusbStatusCode == 1) {
|
||||||
libusb_exit(this->libUsbContext);
|
// A kernel driver is active on this interface. Attempt to detach it
|
||||||
|
if (::libusb_detach_kernel_driver(this->libusbDeviceHandle.get(), interfaceNumber) != 0) {
|
||||||
|
throw DeviceInitializationFailure("Failed to detach kernel driver from interface " +
|
||||||
|
std::to_string(interfaceNumber) + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (libusbStatusCode != 0) {
|
||||||
|
throw DeviceInitializationFailure("Failed to check for active kernel driver on USB interface.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UsbDevice::close() {
|
||||||
|
this->libusbDeviceHandle.reset();
|
||||||
|
this->libusbDevice.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
UsbDevice::~UsbDevice() {
|
||||||
|
this->close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,37 +10,26 @@
|
|||||||
|
|
||||||
namespace Bloom::Usb
|
namespace Bloom::Usb
|
||||||
{
|
{
|
||||||
|
using LibusbContextType = std::unique_ptr<::libusb_context, decltype(&::libusb_exit)>;
|
||||||
|
using LibusbDeviceType = std::unique_ptr<::libusb_device, decltype(&::libusb_unref_device)>;
|
||||||
|
using LibusbDeviceHandleType = std::unique_ptr<::libusb_device_handle, decltype(&::libusb_close)>;
|
||||||
|
|
||||||
class UsbDevice
|
class UsbDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UsbDevice(std::uint16_t vendorId, std::uint16_t productId): vendorId(vendorId), productId(productId) {};
|
std::uint16_t vendorId;
|
||||||
|
std::uint16_t productId;
|
||||||
|
|
||||||
virtual ~UsbDevice() = default;
|
UsbDevice(std::uint16_t vendorId, std::uint16_t productId);
|
||||||
|
|
||||||
|
UsbDevice(const UsbDevice& other) = delete;
|
||||||
|
UsbDevice& operator = (const UsbDevice& other) = delete;
|
||||||
|
|
||||||
UsbDevice(const UsbDevice& other) = default;
|
|
||||||
UsbDevice(UsbDevice&& other) = default;
|
UsbDevice(UsbDevice&& other) = default;
|
||||||
|
|
||||||
UsbDevice& operator = (const UsbDevice& other) = default;
|
|
||||||
UsbDevice& operator = (UsbDevice&& other) = default;
|
UsbDevice& operator = (UsbDevice&& other) = default;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
[[nodiscard]] libusb_device* getLibUsbDevice() const {
|
|
||||||
return this->libUsbDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLibUsbDevice(libusb_device* libUsbDevice) {
|
|
||||||
this->libUsbDevice = libUsbDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::uint16_t getVendorId() const {
|
|
||||||
return this->vendorId;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] std::uint16_t getProductId() const {
|
|
||||||
return this->productId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects a specific configuration on the device, using the configuration index.
|
* Selects a specific configuration on the device, using the configuration index.
|
||||||
*
|
*
|
||||||
@@ -48,16 +37,17 @@ namespace Bloom::Usb
|
|||||||
*/
|
*/
|
||||||
virtual void setConfiguration(int configIndex);
|
virtual void setConfiguration(int configIndex);
|
||||||
|
|
||||||
protected:
|
virtual ~UsbDevice();
|
||||||
libusb_context* libUsbContext = nullptr;
|
|
||||||
libusb_device* libUsbDevice = nullptr;
|
|
||||||
libusb_device_handle* libUsbDeviceHandle = nullptr;
|
|
||||||
std::uint16_t vendorId;
|
|
||||||
std::uint16_t productId;
|
|
||||||
|
|
||||||
std::vector<libusb_device*> findMatchingDevices(
|
protected:
|
||||||
std::optional<std::uint16_t> vendorId = std::nullopt, std::optional<std::uint16_t> productId = std::nullopt
|
static inline LibusbContextType libusbContext = LibusbContextType(nullptr, ::libusb_exit);
|
||||||
);
|
|
||||||
|
LibusbDeviceType libusbDevice = LibusbDeviceType(nullptr, ::libusb_unref_device);
|
||||||
|
LibusbDeviceHandleType libusbDeviceHandle = LibusbDeviceHandleType(nullptr, ::libusb_close);
|
||||||
|
|
||||||
|
std::vector<LibusbDeviceType> findMatchingDevices(std::uint16_t vendorId, std::uint16_t productId);
|
||||||
|
|
||||||
|
void detachKernelDriverFromInterface(std::uint8_t interfaceNumber);
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user