diff --git a/src/DebugToolDrivers/CMakeLists.txt b/src/DebugToolDrivers/CMakeLists.txt index 7fcfcd5c..a9d1b31b 100755 --- a/src/DebugToolDrivers/CMakeLists.txt +++ b/src/DebugToolDrivers/CMakeLists.txt @@ -2,7 +2,6 @@ target_sources( Bloom PRIVATE ${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}/Microchip/AtmelICE/AtmelIce.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Microchip/PowerDebugger/PowerDebugger.cpp diff --git a/src/DebugToolDrivers/Microchip/AtmelICE/AtmelIce.cpp b/src/DebugToolDrivers/Microchip/AtmelICE/AtmelIce.cpp index 0a17e6e3..2f42be42 100644 --- a/src/DebugToolDrivers/Microchip/AtmelICE/AtmelIce.cpp +++ b/src/DebugToolDrivers/Microchip/AtmelICE/AtmelIce.cpp @@ -8,22 +8,23 @@ namespace Bloom::DebugToolDrivers using namespace Protocols::CmsisDap::Edbg::Avr; using namespace Bloom::Exceptions; + using Protocols::CmsisDap::Edbg::EdbgInterface; + + AtmelIce::AtmelIce() + : UsbDevice(AtmelIce::USB_VENDOR_ID, AtmelIce::USB_PRODUCT_ID) + {} + void AtmelIce::init() { UsbDevice::init(); // TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number - auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface(); - usbHidInterface.setNumber(0); - usbHidInterface.setLibUsbDevice(this->libUsbDevice); - usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle); - usbHidInterface.setVendorId(this->vendorId); - usbHidInterface.setProductId(this->productId); + auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId); - if (!usbHidInterface.isInitialised()) { - usbHidInterface.detachKernelDriver(); - this->setConfiguration(0); - usbHidInterface.init(); - } + this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber); + this->setConfiguration(0); + usbHidInterface.init(); + + this->edbgInterface = std::make_unique(std::move(usbHidInterface)); /* * 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 * 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. if (!this->sessionStarted) { this->startSession(); } - this->edbgAvr8Interface = std::make_unique(this->edbgInterface); - this->edbgAvrIspInterface = std::make_unique(this->edbgInterface); + this->edbgAvr8Interface = std::make_unique(this->edbgInterface.get()); + this->edbgAvrIspInterface = std::make_unique(this->edbgInterface.get()); this->setInitialised(true); } @@ -49,7 +50,7 @@ namespace Bloom::DebugToolDrivers this->endSession(); } - this->getEdbgInterface().getUsbHidInterface().close(); + this->edbgInterface->getUsbHidInterface().close(); UsbDevice::close(); } @@ -57,7 +58,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::Discovery; using ResponseFrames::Discovery::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( 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()); } @@ -75,7 +76,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( StartSession() ); @@ -91,7 +92,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( EndSession() ); diff --git a/src/DebugToolDrivers/Microchip/AtmelICE/AtmelIce.hpp b/src/DebugToolDrivers/Microchip/AtmelICE/AtmelIce.hpp index cd43e03c..c9b3f7e3 100644 --- a/src/DebugToolDrivers/Microchip/AtmelICE/AtmelIce.hpp +++ b/src/DebugToolDrivers/Microchip/AtmelICE/AtmelIce.hpp @@ -45,16 +45,12 @@ namespace Bloom::DebugToolDrivers static const std::uint16_t USB_VENDOR_ID = 1003; static const std::uint16_t USB_PRODUCT_ID = 8513; - AtmelIce(): UsbDevice(AtmelIce::USB_VENDOR_ID, AtmelIce::USB_PRODUCT_ID) {} + AtmelIce(); void init() override; void close() override; - Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() { - return this->edbgInterface; - } - TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override { return this->edbgAvr8Interface.get(); } @@ -65,7 +61,7 @@ namespace Bloom::DebugToolDrivers std::string getName() override { return "Atmel-ICE"; - }; + } /** * 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 * EdbgInterface extends the CmsisDapInterface). */ - Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface(); + std::unique_ptr edbgInterface = nullptr; /** * The Atmel-ICE employs the EDBG AVR8 Generic protocol, for debugging AVR8 targets. This protocol is diff --git a/src/DebugToolDrivers/Microchip/CuriosityNano/CuriosityNano.cpp b/src/DebugToolDrivers/Microchip/CuriosityNano/CuriosityNano.cpp index 1e5a90b4..3ad42b17 100644 --- a/src/DebugToolDrivers/Microchip/CuriosityNano/CuriosityNano.cpp +++ b/src/DebugToolDrivers/Microchip/CuriosityNano/CuriosityNano.cpp @@ -8,36 +8,36 @@ namespace Bloom::DebugToolDrivers using namespace Protocols::CmsisDap::Edbg::Avr; using namespace Bloom::Exceptions; + using Protocols::CmsisDap::Edbg::EdbgInterface; using Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface; + CuriosityNano::CuriosityNano() + : UsbDevice(CuriosityNano::USB_VENDOR_ID, CuriosityNano::USB_PRODUCT_ID) + {} + void CuriosityNano::init() { UsbDevice::init(); // TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number - auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface(); - usbHidInterface.setNumber(0); - usbHidInterface.setLibUsbDevice(this->libUsbDevice); - usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle); - usbHidInterface.setVendorId(this->vendorId); - usbHidInterface.setProductId(this->productId); + auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId); - if (!usbHidInterface.isInitialised()) { - usbHidInterface.detachKernelDriver(); - usbHidInterface.init(); - } + this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber); + usbHidInterface.init(); - this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35)); + this->edbgInterface = std::make_unique(std::move(usbHidInterface)); + + this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35)); if (!this->sessionStarted) { this->startSession(); } this->targetPowerManagementInterface = std::make_unique( - this->edbgInterface + this->edbgInterface.get() ); - this->edbgAvr8Interface = std::make_unique(this->edbgInterface); - this->edbgAvrIspInterface = std::make_unique(this->edbgInterface); + this->edbgAvr8Interface = std::make_unique(this->edbgInterface.get()); + this->edbgAvrIspInterface = std::make_unique(this->edbgInterface.get()); this->setInitialised(true); } @@ -47,7 +47,7 @@ namespace Bloom::DebugToolDrivers this->endSession(); } - this->getEdbgInterface().getUsbHidInterface().close(); + this->edbgInterface->getUsbHidInterface().close(); UsbDevice::close(); } @@ -55,7 +55,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::Discovery; using ResponseFrames::Discovery::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( 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()); } @@ -73,7 +73,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( StartSession() ); @@ -89,7 +89,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( EndSession() ); diff --git a/src/DebugToolDrivers/Microchip/CuriosityNano/CuriosityNano.hpp b/src/DebugToolDrivers/Microchip/CuriosityNano/CuriosityNano.hpp index c97c324a..f80fbafa 100644 --- a/src/DebugToolDrivers/Microchip/CuriosityNano/CuriosityNano.hpp +++ b/src/DebugToolDrivers/Microchip/CuriosityNano/CuriosityNano.hpp @@ -35,16 +35,12 @@ namespace Bloom::DebugToolDrivers static const std::uint16_t USB_VENDOR_ID = 1003; static const std::uint16_t USB_PRODUCT_ID = 8565; - CuriosityNano(): UsbDevice(CuriosityNano::USB_VENDOR_ID, CuriosityNano::USB_PRODUCT_ID) {} + CuriosityNano(); void init() override; void close() override; - Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() { - return this->edbgInterface; - } - DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* getTargetPowerManagementInterface() override { return this->targetPowerManagementInterface.get(); } @@ -59,7 +55,7 @@ namespace Bloom::DebugToolDrivers std::string getName() override { return "Curiosity Nano"; - }; + } /** * Retrieves the device serial number via the Discovery Protocol. @@ -79,7 +75,7 @@ namespace Bloom::DebugToolDrivers void endSession(); private: - Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface(); + std::unique_ptr edbgInterface = nullptr; std::unique_ptr edbgAvr8Interface = nullptr; std::unique_ptr edbgAvrIspInterface = nullptr; std::unique_ptr< diff --git a/src/DebugToolDrivers/Microchip/JtagIce3/JtagIce3.cpp b/src/DebugToolDrivers/Microchip/JtagIce3/JtagIce3.cpp index de7e562b..8012fe11 100644 --- a/src/DebugToolDrivers/Microchip/JtagIce3/JtagIce3.cpp +++ b/src/DebugToolDrivers/Microchip/JtagIce3/JtagIce3.cpp @@ -8,32 +8,33 @@ namespace Bloom::DebugToolDrivers using namespace Protocols::CmsisDap::Edbg::Avr; using namespace Bloom::Exceptions; + using Protocols::CmsisDap::Edbg::EdbgInterface; + + JtagIce3::JtagIce3() + : UsbDevice(JtagIce3::USB_VENDOR_ID, JtagIce3::USB_PRODUCT_ID) + {} + void JtagIce3::init() { UsbDevice::init(); // TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number - auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface(); - usbHidInterface.setNumber(0); - usbHidInterface.setLibUsbDevice(this->libUsbDevice); - usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle); - usbHidInterface.setVendorId(this->vendorId); - usbHidInterface.setProductId(this->productId); + auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId); - if (!usbHidInterface.isInitialised()) { - usbHidInterface.detachKernelDriver(); - this->setConfiguration(0); - usbHidInterface.init(); - } + this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber); + this->setConfiguration(0); + usbHidInterface.init(); - this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35)); + this->edbgInterface = std::make_unique(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. if (!this->sessionStarted) { this->startSession(); } - this->edbgAvr8Interface = std::make_unique(this->edbgInterface); - this->edbgAvrIspInterface = std::make_unique(this->edbgInterface); + this->edbgAvr8Interface = std::make_unique(this->edbgInterface.get()); + this->edbgAvrIspInterface = std::make_unique(this->edbgInterface.get()); this->setInitialised(true); } @@ -43,7 +44,7 @@ namespace Bloom::DebugToolDrivers this->endSession(); } - this->getEdbgInterface().getUsbHidInterface().close(); + this->edbgInterface->getUsbHidInterface().close(); UsbDevice::close(); } @@ -51,7 +52,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::Discovery; using ResponseFrames::Discovery::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( 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()); } @@ -69,7 +70,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( StartSession() ); @@ -85,7 +86,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( EndSession() ); diff --git a/src/DebugToolDrivers/Microchip/JtagIce3/JtagIce3.hpp b/src/DebugToolDrivers/Microchip/JtagIce3/JtagIce3.hpp index ea659005..66119834 100644 --- a/src/DebugToolDrivers/Microchip/JtagIce3/JtagIce3.hpp +++ b/src/DebugToolDrivers/Microchip/JtagIce3/JtagIce3.hpp @@ -21,16 +21,12 @@ namespace Bloom::DebugToolDrivers static const std::uint16_t USB_VENDOR_ID = 1003; static const std::uint16_t USB_PRODUCT_ID = 8512; - JtagIce3(): UsbDevice(JtagIce3::USB_VENDOR_ID, JtagIce3::USB_PRODUCT_ID) {} + JtagIce3(); void init() override; void close() override; - Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() { - return this->edbgInterface; - } - TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override { return this->edbgAvr8Interface.get(); } @@ -41,7 +37,7 @@ namespace Bloom::DebugToolDrivers std::string getName() override { return "JTAGICE3"; - }; + } /** * Retrieves the device serial number via the Discovery Protocol. @@ -61,7 +57,7 @@ namespace Bloom::DebugToolDrivers void endSession(); private: - Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface(); + std::unique_ptr edbgInterface = nullptr; std::unique_ptr edbgAvr8Interface = nullptr; std::unique_ptr edbgAvrIspInterface = nullptr; diff --git a/src/DebugToolDrivers/Microchip/MplabPickit4/MplabPickit4.cpp b/src/DebugToolDrivers/Microchip/MplabPickit4/MplabPickit4.cpp index 2323f2f1..e8ca5874 100644 --- a/src/DebugToolDrivers/Microchip/MplabPickit4/MplabPickit4.cpp +++ b/src/DebugToolDrivers/Microchip/MplabPickit4/MplabPickit4.cpp @@ -8,30 +8,32 @@ namespace Bloom::DebugToolDrivers using namespace Protocols::CmsisDap::Edbg::Avr; using namespace Bloom::Exceptions; + using Protocols::CmsisDap::Edbg::EdbgInterface; + + MplabPickit4::MplabPickit4() + : UsbDevice(MplabPickit4::USB_VENDOR_ID, MplabPickit4::USB_PRODUCT_ID) + {} + void MplabPickit4::init() { UsbDevice::init(); // TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number - auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface(); - usbHidInterface.setNumber(0); - usbHidInterface.setLibUsbDevice(this->libUsbDevice); - usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle); - usbHidInterface.setVendorId(this->vendorId); - usbHidInterface.setProductId(this->productId); + auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId); - if (!usbHidInterface.isInitialised()) { - usbHidInterface.init(); - } + this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber); + usbHidInterface.init(); - this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35)); + this->edbgInterface = std::make_unique(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. if (!this->sessionStarted) { this->startSession(); } - this->edbgAvr8Interface = std::make_unique(this->edbgInterface); - this->edbgAvrIspInterface = std::make_unique(this->edbgInterface); + this->edbgAvr8Interface = std::make_unique(this->edbgInterface.get()); + this->edbgAvrIspInterface = std::make_unique(this->edbgInterface.get()); this->setInitialised(true); } @@ -41,7 +43,7 @@ namespace Bloom::DebugToolDrivers this->endSession(); } - this->getEdbgInterface().getUsbHidInterface().close(); + this->edbgInterface->getUsbHidInterface().close(); UsbDevice::close(); } @@ -49,7 +51,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::Discovery; using ResponseFrames::Discovery::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( 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()); } @@ -67,7 +69,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( StartSession() ); @@ -83,7 +85,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( EndSession() ); diff --git a/src/DebugToolDrivers/Microchip/MplabPickit4/MplabPickit4.hpp b/src/DebugToolDrivers/Microchip/MplabPickit4/MplabPickit4.hpp index 4a08ed38..5acb7aed 100644 --- a/src/DebugToolDrivers/Microchip/MplabPickit4/MplabPickit4.hpp +++ b/src/DebugToolDrivers/Microchip/MplabPickit4/MplabPickit4.hpp @@ -33,16 +33,12 @@ namespace Bloom::DebugToolDrivers static const std::uint16_t USB_VENDOR_ID = 1003; static const std::uint16_t USB_PRODUCT_ID = 8567; - MplabPickit4(): UsbDevice(MplabPickit4::USB_VENDOR_ID, MplabPickit4::USB_PRODUCT_ID) {} + MplabPickit4(); void init() override; void close() override; - Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() { - return this->edbgInterface; - } - TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override { return this->edbgAvr8Interface.get(); } @@ -53,7 +49,7 @@ namespace Bloom::DebugToolDrivers std::string getName() override { return "MPLAB PICkit 4"; - }; + } /** * Retrieves the device serial number via the Discovery Protocol. @@ -73,7 +69,7 @@ namespace Bloom::DebugToolDrivers void endSession(); private: - Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface(); + std::unique_ptr edbgInterface = nullptr; std::unique_ptr edbgAvr8Interface = nullptr; std::unique_ptr edbgAvrIspInterface = nullptr; diff --git a/src/DebugToolDrivers/Microchip/MplabSnap/MplabSnap.cpp b/src/DebugToolDrivers/Microchip/MplabSnap/MplabSnap.cpp index d4ece073..916f8aaf 100644 --- a/src/DebugToolDrivers/Microchip/MplabSnap/MplabSnap.cpp +++ b/src/DebugToolDrivers/Microchip/MplabSnap/MplabSnap.cpp @@ -8,30 +8,32 @@ namespace Bloom::DebugToolDrivers using namespace Protocols::CmsisDap::Edbg::Avr; using namespace Bloom::Exceptions; + using Protocols::CmsisDap::Edbg::EdbgInterface; + + MplabSnap::MplabSnap() + : UsbDevice(MplabSnap::USB_VENDOR_ID, MplabSnap::USB_PRODUCT_ID) + {} + void MplabSnap::init() { UsbDevice::init(); // TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number - auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface(); - usbHidInterface.setNumber(0); - usbHidInterface.setLibUsbDevice(this->libUsbDevice); - usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle); - usbHidInterface.setVendorId(this->vendorId); - usbHidInterface.setProductId(this->productId); + auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId); - if (!usbHidInterface.isInitialised()) { - usbHidInterface.init(); - } + this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber); + usbHidInterface.init(); - this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35)); + this->edbgInterface = std::make_unique(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. if (!this->sessionStarted) { this->startSession(); } - this->edbgAvr8Interface = std::make_unique(this->edbgInterface); - this->edbgAvrIspInterface = std::make_unique(this->edbgInterface); + this->edbgAvr8Interface = std::make_unique(this->edbgInterface.get()); + this->edbgAvrIspInterface = std::make_unique(this->edbgInterface.get()); this->setInitialised(true); } @@ -41,7 +43,7 @@ namespace Bloom::DebugToolDrivers this->endSession(); } - this->getEdbgInterface().getUsbHidInterface().close(); + this->edbgInterface->getUsbHidInterface().close(); UsbDevice::close(); } @@ -49,7 +51,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::Discovery; using ResponseFrames::Discovery::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( 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()); } @@ -67,7 +69,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( StartSession() ); @@ -83,7 +85,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( EndSession() ); diff --git a/src/DebugToolDrivers/Microchip/MplabSnap/MplabSnap.hpp b/src/DebugToolDrivers/Microchip/MplabSnap/MplabSnap.hpp index 08d0970d..272281af 100644 --- a/src/DebugToolDrivers/Microchip/MplabSnap/MplabSnap.hpp +++ b/src/DebugToolDrivers/Microchip/MplabSnap/MplabSnap.hpp @@ -39,16 +39,12 @@ namespace Bloom::DebugToolDrivers static const std::uint16_t USB_VENDOR_ID = 1003; static const std::uint16_t USB_PRODUCT_ID = 8576; - MplabSnap(): UsbDevice(MplabSnap::USB_VENDOR_ID, MplabSnap::USB_PRODUCT_ID) {} + MplabSnap(); void init() override; void close() override; - Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() { - return this->edbgInterface; - } - TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override { return this->edbgAvr8Interface.get(); } @@ -59,7 +55,7 @@ namespace Bloom::DebugToolDrivers std::string getName() override { return "MPLAB Snap"; - }; + } /** * Retrieves the device serial number via the Discovery Protocol. @@ -79,7 +75,7 @@ namespace Bloom::DebugToolDrivers void endSession(); private: - Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface(); + std::unique_ptr edbgInterface = nullptr; /** * The MPLAB Snap employs the EDBG AVR8 Generic protocol, for debugging AVR8 targets. This protocol is diff --git a/src/DebugToolDrivers/Microchip/PowerDebugger/PowerDebugger.cpp b/src/DebugToolDrivers/Microchip/PowerDebugger/PowerDebugger.cpp index 07e08c70..6afac156 100644 --- a/src/DebugToolDrivers/Microchip/PowerDebugger/PowerDebugger.cpp +++ b/src/DebugToolDrivers/Microchip/PowerDebugger/PowerDebugger.cpp @@ -8,36 +8,32 @@ namespace Bloom::DebugToolDrivers using namespace Protocols::CmsisDap::Edbg::Avr; using namespace Bloom::Exceptions; + using Protocols::CmsisDap::Edbg::EdbgInterface; + + PowerDebugger::PowerDebugger() + : UsbDevice(PowerDebugger::USB_VENDOR_ID, PowerDebugger::USB_PRODUCT_ID) + {} + void PowerDebugger::init() { UsbDevice::init(); // TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number - auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface(); - usbHidInterface.setNumber(0); - usbHidInterface.setLibUsbDevice(this->libUsbDevice); - usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle); - usbHidInterface.setVendorId(this->vendorId); - usbHidInterface.setProductId(this->productId); + auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId); - if (!usbHidInterface.isInitialised()) { - usbHidInterface.init(); - } + this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber); + usbHidInterface.init(); - /* - * The Power Debugger EDBG/CMSIS-DAP interface doesn't operate properly when sending commands too quickly. - * - * Because of this, we have to enforce a minimum time gap between commands. See comment in - * CmsisDapInterface class declaration for more info. - */ - this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35)); + this->edbgInterface = std::make_unique(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. if (!this->sessionStarted) { this->startSession(); } - this->edbgAvr8Interface = std::make_unique(this->edbgInterface); - this->edbgAvrIspInterface = std::make_unique(this->edbgInterface); + this->edbgAvr8Interface = std::make_unique(this->edbgInterface.get()); + this->edbgAvrIspInterface = std::make_unique(this->edbgInterface.get()); this->setInitialised(true); } @@ -47,7 +43,7 @@ namespace Bloom::DebugToolDrivers this->endSession(); } - this->getEdbgInterface().getUsbHidInterface().close(); + this->edbgInterface->getUsbHidInterface().close(); UsbDevice::close(); } @@ -55,7 +51,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::Discovery; using ResponseFrames::Discovery::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( 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()); } @@ -73,7 +69,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( StartSession() ); @@ -91,7 +87,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( EndSession() ); diff --git a/src/DebugToolDrivers/Microchip/PowerDebugger/PowerDebugger.hpp b/src/DebugToolDrivers/Microchip/PowerDebugger/PowerDebugger.hpp index 573d5e46..bdaf9331 100644 --- a/src/DebugToolDrivers/Microchip/PowerDebugger/PowerDebugger.hpp +++ b/src/DebugToolDrivers/Microchip/PowerDebugger/PowerDebugger.hpp @@ -32,16 +32,12 @@ namespace Bloom::DebugToolDrivers static const std::uint16_t USB_VENDOR_ID = 1003; static const std::uint16_t USB_PRODUCT_ID = 8516; - PowerDebugger(): UsbDevice(PowerDebugger::USB_VENDOR_ID, PowerDebugger::USB_PRODUCT_ID) {} + PowerDebugger(); void init() override; void close() override; - Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() { - return this->edbgInterface; - } - TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface* getAvr8DebugInterface() override { return this->edbgAvr8Interface.get(); } @@ -52,7 +48,7 @@ namespace Bloom::DebugToolDrivers std::string getName() override { return "Power Debugger"; - }; + } /** * 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 * EdbgInterface extends the CmsisDapInterface). */ - Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface(); + std::unique_ptr edbgInterface = nullptr; /** * The Power Debugger employs the EDBG AVR8Generic protocol for interfacing with AVR8 targets. diff --git a/src/DebugToolDrivers/Microchip/XplainedMini/XplainedMini.cpp b/src/DebugToolDrivers/Microchip/XplainedMini/XplainedMini.cpp index b4c21d87..901dfcd6 100644 --- a/src/DebugToolDrivers/Microchip/XplainedMini/XplainedMini.cpp +++ b/src/DebugToolDrivers/Microchip/XplainedMini/XplainedMini.cpp @@ -8,36 +8,36 @@ namespace Bloom::DebugToolDrivers using namespace Protocols::CmsisDap::Edbg::Avr; using namespace Bloom::Exceptions; + using Protocols::CmsisDap::Edbg::EdbgInterface; using Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface; + XplainedMini::XplainedMini() + : UsbDevice(XplainedMini::USB_VENDOR_ID, XplainedMini::USB_PRODUCT_ID) + {} + void XplainedMini::init() { UsbDevice::init(); // TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number - auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface(); - usbHidInterface.setNumber(0); - usbHidInterface.setLibUsbDevice(this->libUsbDevice); - usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle); - usbHidInterface.setVendorId(this->vendorId); - usbHidInterface.setProductId(this->productId); + auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId); - if (!usbHidInterface.isInitialised()) { - usbHidInterface.detachKernelDriver(); - usbHidInterface.init(); - } + this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber); + usbHidInterface.init(); - this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35)); + this->edbgInterface = std::make_unique(std::move(usbHidInterface)); + + this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35)); if (!this->sessionStarted) { this->startSession(); } this->targetPowerManagementInterface = std::make_unique( - this->edbgInterface + this->edbgInterface.get() ); - this->edbgAvr8Interface = std::make_unique(this->edbgInterface); - this->edbgAvrIspInterface = std::make_unique(this->edbgInterface); + this->edbgAvr8Interface = std::make_unique(this->edbgInterface.get()); + this->edbgAvrIspInterface = std::make_unique(this->edbgInterface.get()); this->setInitialised(true); } @@ -47,7 +47,7 @@ namespace Bloom::DebugToolDrivers this->endSession(); } - this->getEdbgInterface().getUsbHidInterface().close(); + this->edbgInterface->getUsbHidInterface().close(); UsbDevice::close(); } @@ -55,7 +55,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::Discovery; using ResponseFrames::Discovery::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( Query(QueryContext::SERIAL_NUMBER) ); @@ -73,7 +73,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( StartSession() ); @@ -89,7 +89,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( EndSession() ); diff --git a/src/DebugToolDrivers/Microchip/XplainedMini/XplainedMini.hpp b/src/DebugToolDrivers/Microchip/XplainedMini/XplainedMini.hpp index d08d0645..28cef731 100644 --- a/src/DebugToolDrivers/Microchip/XplainedMini/XplainedMini.hpp +++ b/src/DebugToolDrivers/Microchip/XplainedMini/XplainedMini.hpp @@ -35,16 +35,12 @@ namespace Bloom::DebugToolDrivers static const std::uint16_t USB_VENDOR_ID = 1003; static const std::uint16_t USB_PRODUCT_ID = 8517; - XplainedMini(): UsbDevice(XplainedMini::USB_VENDOR_ID, XplainedMini::USB_PRODUCT_ID) {} + XplainedMini(); void init() override; void close() override; - Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() { - return this->edbgInterface; - } - DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* getTargetPowerManagementInterface() override { return this->targetPowerManagementInterface.get(); } @@ -59,7 +55,7 @@ namespace Bloom::DebugToolDrivers std::string getName() override { return "Xplained Mini"; - }; + } /** * Retrieves the device serial number via the Discovery Protocol. @@ -79,7 +75,7 @@ namespace Bloom::DebugToolDrivers void endSession(); private: - Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface(); + std::unique_ptr edbgInterface = nullptr; std::unique_ptr edbgAvr8Interface = nullptr; std::unique_ptr edbgAvrIspInterface = nullptr; std::unique_ptr< diff --git a/src/DebugToolDrivers/Microchip/XplainedNano/XplainedNano.cpp b/src/DebugToolDrivers/Microchip/XplainedNano/XplainedNano.cpp index 43be6ecb..a6db6223 100644 --- a/src/DebugToolDrivers/Microchip/XplainedNano/XplainedNano.cpp +++ b/src/DebugToolDrivers/Microchip/XplainedNano/XplainedNano.cpp @@ -8,35 +8,35 @@ namespace Bloom::DebugToolDrivers using namespace Protocols::CmsisDap::Edbg::Avr; using namespace Bloom::Exceptions; + using Protocols::CmsisDap::Edbg::EdbgInterface; using Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface; + XplainedNano::XplainedNano() + : UsbDevice(XplainedNano::USB_VENDOR_ID, XplainedNano::USB_PRODUCT_ID) + {} + void XplainedNano::init() { UsbDevice::init(); // TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number - auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface(); - usbHidInterface.setNumber(0); - usbHidInterface.setLibUsbDevice(this->libUsbDevice); - usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle); - usbHidInterface.setVendorId(this->vendorId); - usbHidInterface.setProductId(this->productId); + auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId); - if (!usbHidInterface.isInitialised()) { - usbHidInterface.detachKernelDriver(); - usbHidInterface.init(); - } + this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber); + usbHidInterface.init(); - this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35)); + this->edbgInterface = std::make_unique(std::move(usbHidInterface)); + + this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35)); if (!this->sessionStarted) { this->startSession(); } this->targetPowerManagementInterface = std::make_unique( - this->edbgInterface + this->edbgInterface.get() ); - this->edbgAvr8Interface = std::make_unique(this->edbgInterface); + this->edbgAvr8Interface = std::make_unique(this->edbgInterface.get()); this->setInitialised(true); } @@ -45,7 +45,7 @@ namespace Bloom::DebugToolDrivers this->endSession(); } - this->getEdbgInterface().getUsbHidInterface().close(); + this->edbgInterface->getUsbHidInterface().close(); UsbDevice::close(); } @@ -53,7 +53,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::Discovery; using ResponseFrames::Discovery::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( 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()); } @@ -71,7 +71,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( StartSession() ); @@ -87,7 +87,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( EndSession() ); diff --git a/src/DebugToolDrivers/Microchip/XplainedNano/XplainedNano.hpp b/src/DebugToolDrivers/Microchip/XplainedNano/XplainedNano.hpp index a09b1f87..4f6bcf0b 100644 --- a/src/DebugToolDrivers/Microchip/XplainedNano/XplainedNano.hpp +++ b/src/DebugToolDrivers/Microchip/XplainedNano/XplainedNano.hpp @@ -34,16 +34,12 @@ namespace Bloom::DebugToolDrivers static const std::uint16_t USB_VENDOR_ID = 1003; static const std::uint16_t USB_PRODUCT_ID = 8517; - XplainedNano(): UsbDevice(XplainedNano::USB_VENDOR_ID, XplainedNano::USB_PRODUCT_ID) {} + XplainedNano(); void init() override; void close() override; - Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() { - return this->edbgInterface; - } - DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* getTargetPowerManagementInterface() override { return this->targetPowerManagementInterface.get(); } @@ -54,7 +50,7 @@ namespace Bloom::DebugToolDrivers std::string getName() override { return "Xplained Nano"; - }; + } /** * Retrieves the device serial number via the Discovery Protocol. @@ -74,7 +70,7 @@ namespace Bloom::DebugToolDrivers void endSession(); private: - Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface(); + std::unique_ptr edbgInterface = nullptr; std::unique_ptr edbgAvr8Interface = nullptr; std::unique_ptr< Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface diff --git a/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.cpp b/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.cpp index 2e60a48f..92543e3a 100644 --- a/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.cpp +++ b/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.cpp @@ -8,35 +8,35 @@ namespace Bloom::DebugToolDrivers using namespace Protocols::CmsisDap::Edbg::Avr; using namespace Bloom::Exceptions; + using Protocols::CmsisDap::Edbg::EdbgInterface; using Protocols::CmsisDap::Edbg::EdbgTargetPowerManagementInterface; + XplainedPro::XplainedPro() + : UsbDevice(XplainedPro::USB_VENDOR_ID, XplainedPro::USB_PRODUCT_ID) + {} + void XplainedPro::init() { UsbDevice::init(); // TODO: Move away from hard-coding the CMSIS-DAP/EDBG interface number - auto& usbHidInterface = this->getEdbgInterface().getUsbHidInterface(); - usbHidInterface.setNumber(0); - usbHidInterface.setLibUsbDevice(this->libUsbDevice); - usbHidInterface.setLibUsbDeviceHandle(this->libUsbDeviceHandle); - usbHidInterface.setVendorId(this->vendorId); - usbHidInterface.setProductId(this->productId); + auto usbHidInterface = Usb::HidInterface(0, this->vendorId, this->productId); - if (!usbHidInterface.isInitialised()) { - usbHidInterface.detachKernelDriver(); - usbHidInterface.init(); - } + this->detachKernelDriverFromInterface(usbHidInterface.interfaceNumber); + usbHidInterface.init(); - this->getEdbgInterface().setMinimumCommandTimeGap(std::chrono::milliseconds(35)); + this->edbgInterface = std::make_unique(std::move(usbHidInterface)); + + this->edbgInterface->setMinimumCommandTimeGap(std::chrono::milliseconds(35)); if (!this->sessionStarted) { this->startSession(); } this->targetPowerManagementInterface = std::make_unique( - this->edbgInterface + this->edbgInterface.get() ); - this->edbgAvr8Interface = std::make_unique(this->edbgInterface); + this->edbgAvr8Interface = std::make_unique(this->edbgInterface.get()); /* * 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->getEdbgInterface().getUsbHidInterface().close(); + this->edbgInterface->getUsbHidInterface().close(); UsbDevice::close(); } @@ -62,7 +62,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::Discovery; using ResponseFrames::Discovery::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( Query(QueryContext::SERIAL_NUMBER) ); @@ -80,7 +80,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( StartSession() ); @@ -96,7 +96,7 @@ namespace Bloom::DebugToolDrivers using namespace CommandFrames::HouseKeeping; using ResponseFrames::HouseKeeping::ResponseId; - auto response = this->getEdbgInterface().sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( EndSession() ); diff --git a/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.hpp b/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.hpp index b1cce95c..0df57601 100644 --- a/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.hpp +++ b/src/DebugToolDrivers/Microchip/XplainedPro/XplainedPro.hpp @@ -34,16 +34,12 @@ namespace Bloom::DebugToolDrivers static const std::uint16_t USB_VENDOR_ID = 1003; static const std::uint16_t USB_PRODUCT_ID = 8465; - XplainedPro(): UsbDevice(XplainedPro::USB_VENDOR_ID, XplainedPro::USB_PRODUCT_ID) {} + XplainedPro(); void init() override; void close() override; - Protocols::CmsisDap::Edbg::EdbgInterface& getEdbgInterface() { - return this->edbgInterface; - } - DebugToolDrivers::TargetInterfaces::TargetPowerManagementInterface* getTargetPowerManagementInterface() override { return this->targetPowerManagementInterface.get(); } @@ -54,7 +50,7 @@ namespace Bloom::DebugToolDrivers std::string getName() override { return "Xplained Pro"; - }; + } /** * Retrieves the device serial number via the Discovery Protocol. @@ -74,7 +70,7 @@ namespace Bloom::DebugToolDrivers void endSession(); private: - Protocols::CmsisDap::Edbg::EdbgInterface edbgInterface = Protocols::CmsisDap::Edbg::EdbgInterface(); + std::unique_ptr edbgInterface = nullptr; std::unique_ptr edbgAvr8Interface = nullptr; std::unique_ptr< diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/CmsisDapInterface.cpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/CmsisDapInterface.cpp index 517bfdce..5ef79492 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/CmsisDapInterface.cpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/CmsisDapInterface.cpp @@ -8,6 +8,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap { using namespace Bloom::Exceptions; + CmsisDapInterface::CmsisDapInterface(Usb::HidInterface&& usbHidInterface) + : usbHidInterface(std::move(usbHidInterface)) + {} + void CmsisDapInterface::sendCommand(const Command& cmsisDapCommand) { if (this->msSendCommandDelay.count() > 0) { using namespace std::chrono; diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/CmsisDapInterface.hpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/CmsisDapInterface.hpp index 67f9789e..cbd1ae67 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/CmsisDapInterface.hpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/CmsisDapInterface.hpp @@ -21,14 +21,14 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap class CmsisDapInterface { public: - explicit CmsisDapInterface() = default; + explicit CmsisDapInterface(Usb::HidInterface&& usbHidInterface); + virtual ~CmsisDapInterface() = default; - CmsisDapInterface(const CmsisDapInterface& other) = default; - CmsisDapInterface(CmsisDapInterface&& other) = default; - - CmsisDapInterface& operator = (const CmsisDapInterface& other) = default; - CmsisDapInterface& operator = (CmsisDapInterface&& other) = default; + CmsisDapInterface(const CmsisDapInterface& other) = delete; + CmsisDapInterface(CmsisDapInterface&& other) = delete; + CmsisDapInterface& operator = (const CmsisDapInterface& other) = delete; + CmsisDapInterface& operator = (CmsisDapInterface&& other) = delete; Usb::HidInterface& getUsbHidInterface() { return this->usbHidInterface; @@ -65,7 +65,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap "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()) { 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 * 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 diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/CommandFrames/EDBGControl/SetParameter.hpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/CommandFrames/EDBGControl/SetParameter.hpp index e70900b6..0e91b177 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/CommandFrames/EDBGControl/SetParameter.hpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/CommandFrames/EDBGControl/SetParameter.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "EdbgControlCommandFrame.hpp" diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.cpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.cpp index 0dc45201..5ca34b96 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.cpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.cpp @@ -82,7 +82,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr using Bloom::Targets::TargetRegisterType; using Bloom::Targets::TargetRegisters; - EdbgAvr8Interface::EdbgAvr8Interface(EdbgInterface& edbgInterface) + EdbgAvr8Interface::EdbgAvr8Interface(EdbgInterface* edbgInterface) : edbgInterface(edbgInterface) {} @@ -195,7 +195,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvr8Interface::stop() { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( Stop() ); @@ -210,7 +210,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr void EdbgAvr8Interface::run() { this->clearEvents(); - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( Run() ); @@ -223,7 +223,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr void EdbgAvr8Interface::runTo(TargetProgramCounter address) { this->clearEvents(); - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( RunTo(address) ); @@ -235,7 +235,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvr8Interface::step() { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( Step() ); @@ -247,7 +247,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvr8Interface::reset() { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( Reset() ); @@ -335,7 +335,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr this->stop(); } - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( 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 * 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) ); @@ -390,7 +390,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr return TargetSignature(signatureMemory[0], signatureMemory[1], signatureMemory[2]); } - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( GetDeviceId() ); @@ -402,7 +402,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvr8Interface::setBreakpoint(TargetMemoryAddress address) { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( SetSoftwareBreakpoints({address}) ); @@ -412,7 +412,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvr8Interface::clearBreakpoint(TargetMemoryAddress address) { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( ClearSoftwareBreakpoints({address}) ); @@ -422,7 +422,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvr8Interface::clearAllBreakpoints() { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( ClearAllSoftwareBreakpoints() ); @@ -750,7 +750,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr throw Exception("AVR8 erase command not supported for debugWire config variant."); } - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( EraseMemory( section.has_value() ? section == ProgramMemorySection::BOOT @@ -785,7 +785,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr return; } - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( EnterProgrammingMode() ); @@ -801,7 +801,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr return; } - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( LeaveProgrammingMode() ); @@ -909,7 +909,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvr8Interface::setParameter(const Avr8EdbgParameter& parameter, const std::vector& value) { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( SetParameter(parameter, value) ); @@ -919,7 +919,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } std::vector EdbgAvr8Interface::getParameter(const Avr8EdbgParameter& parameter, std::uint8_t size) { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( GetParameter(parameter, size) ); @@ -1371,7 +1371,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvr8Interface::activatePhysical(bool applyExternalReset) { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( ActivatePhysical(applyExternalReset) ); @@ -1390,7 +1390,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvr8Interface::deactivatePhysical() { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( 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 * the attach command. */ - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( Attach( this->configVariant != Avr8ConfigVariant::MEGAJTAG ) @@ -1434,7 +1434,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvr8Interface::detach() { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( 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 * actual value but who has the time. It won't exceed 20 bytes. Bite me. */ - auto singlePacketSize = static_cast(this->edbgInterface.getUsbHidInputReportSize() - 20); + auto singlePacketSize = static_cast(this->edbgInterface->getUsbHidInputReportSize() - 20); auto totalResponsePackets = std::ceil(static_cast(bytes) / static_cast(singlePacketSize)); auto totalReadsRequired = std::ceil(static_cast(totalResponsePackets) / 2); @@ -1713,7 +1713,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } } - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( ReadMemory( type, startAddress, @@ -1780,7 +1780,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } } - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( WriteMemory( type, startAddress, @@ -1811,7 +1811,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvr8Interface::disableDebugWire() { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( DisableDebugWire() ); diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.hpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.hpp index a8f8626d..41bf9c28 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.hpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvr8Interface.hpp @@ -27,7 +27,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr class EdbgAvr8Interface: public TargetInterfaces::Microchip::Avr::Avr8::Avr8DebugInterface { 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 @@ -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. */ - EdbgInterface& edbgInterface; + EdbgInterface* edbgInterface = nullptr; /** * Project's AVR8 target configuration. diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvrIspInterface.cpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvrIspInterface.cpp index 0be651dd..031dda16 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvrIspInterface.cpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvrIspInterface.cpp @@ -26,12 +26,16 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr using Exceptions::TargetOperationFailure; + EdbgAvrIspInterface::EdbgAvrIspInterface(EdbgInterface* edbgInterface) + : edbgInterface(edbgInterface) + {} + void EdbgAvrIspInterface::setIspParameters(const Targets::Microchip::Avr::IspParameters& ispParameters) { this->ispParameters = ispParameters; } void EdbgAvrIspInterface::activate() { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( EnterProgrammingMode( this->ispParameters.programModeTimeout, this->ispParameters.programModeStabilizationDelay, @@ -52,7 +56,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvrIspInterface::deactivate() { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( LeaveProgrammingMode( this->ispParameters.programModePreDelay, this->ispParameters.programModePostDelay @@ -74,7 +78,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } Fuse EdbgAvrIspInterface::readFuse(FuseType fuseType) { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( ReadFuse(fuseType, this->ispParameters.readFusePollIndex) ); @@ -93,7 +97,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } unsigned char EdbgAvrIspInterface::readLockBitByte() { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( ReadLock(this->ispParameters.readLockPollIndex) ); @@ -112,7 +116,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } void EdbgAvrIspInterface::programFuse(Targets::Microchip::Avr::Fuse fuse) { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( ProgramFuse(fuse.type, fuse.value) ); @@ -125,7 +129,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr } unsigned char EdbgAvrIspInterface::readSignatureByte(std::uint8_t signatureByteAddress) { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( ReadSignature(signatureByteAddress, this->ispParameters.readSignaturePollIndex) ); diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvrIspInterface.hpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvrIspInterface.hpp index e45f67a9..9cf2374c 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvrIspInterface.hpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/AVR/EdbgAvrIspInterface.hpp @@ -22,9 +22,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg::Avr class EdbgAvrIspInterface: public TargetInterfaces::Microchip::Avr::AvrIspInterface { public: - explicit EdbgAvrIspInterface(EdbgInterface& edbgInterface) - : edbgInterface(edbgInterface) - {}; + explicit EdbgAvrIspInterface(EdbgInterface* edbgInterface); /** * 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. */ - EdbgInterface& edbgInterface; + EdbgInterface* edbgInterface; Targets::Microchip::Avr::IspParameters ispParameters; diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgInterface.cpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgInterface.cpp index 9a9ba5a6..f31c404e 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgInterface.cpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgInterface.cpp @@ -8,6 +8,10 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg { using namespace Bloom::Exceptions; + EdbgInterface::EdbgInterface(Usb::HidInterface&& usbHidInterface) + : CmsisDapInterface(std::move(usbHidInterface)) + {} + Protocols::CmsisDap::Response EdbgInterface::sendAvrCommandsAndWaitForResponse( const std::vector& avrCommands ) { diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgInterface.hpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgInterface.hpp index ef081bde..0fb2214e 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgInterface.hpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgInterface.hpp @@ -22,7 +22,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg class EdbgInterface: public CmsisDapInterface { public: - explicit EdbgInterface() = default; + explicit EdbgInterface(Usb::HidInterface&& usbHidInterface); /** * Send an AvrCommandFrame to the debug tool and wait for a response. diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgTargetPowerManagementInterface.cpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgTargetPowerManagementInterface.cpp index b30847ce..f938687b 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgTargetPowerManagementInterface.cpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgTargetPowerManagementInterface.cpp @@ -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::SetParameter; + EdbgTargetPowerManagementInterface::EdbgTargetPowerManagementInterface(EdbgInterface* edbgInterface) + : edbgInterface(edbgInterface) + {} + void EdbgTargetPowerManagementInterface::enableTargetPower() { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( SetParameter(EdbgParameters::CONTROL_TARGET_POWER, 0x01) ); @@ -23,7 +27,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg } void EdbgTargetPowerManagementInterface::disableTargetPower() { - auto response = this->edbgInterface.sendAvrCommandFrameAndWaitForResponseFrame( + auto response = this->edbgInterface->sendAvrCommandFrameAndWaitForResponseFrame( SetParameter(EdbgParameters::CONTROL_TARGET_POWER, 0x00) ); diff --git a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgTargetPowerManagementInterface.hpp b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgTargetPowerManagementInterface.hpp index 7e2e65f8..37de1fd9 100644 --- a/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgTargetPowerManagementInterface.hpp +++ b/src/DebugToolDrivers/Protocols/CMSIS-DAP/VendorSpecific/EDBG/EdbgTargetPowerManagementInterface.hpp @@ -10,8 +10,7 @@ namespace Bloom::DebugToolDrivers::Protocols::CmsisDap::Edbg class EdbgTargetPowerManagementInterface: public TargetInterfaces::TargetPowerManagementInterface { public: - explicit EdbgTargetPowerManagementInterface(EdbgInterface& edbgInterface) - : edbgInterface(edbgInterface) {}; + explicit EdbgTargetPowerManagementInterface(EdbgInterface* edbgInterface); /** * 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; private: - EdbgInterface& edbgInterface; + EdbgInterface* edbgInterface; }; } diff --git a/src/DebugToolDrivers/USB/HID/HidInterface.cpp b/src/DebugToolDrivers/USB/HID/HidInterface.cpp index 2d33a786..ec9cabcc 100644 --- a/src/DebugToolDrivers/USB/HID/HidInterface.cpp +++ b/src/DebugToolDrivers/USB/HID/HidInterface.cpp @@ -9,65 +9,71 @@ namespace Bloom::Usb { 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() { - if (this->libUsbDevice == nullptr) { - throw DeviceInitializationFailure("Cannot initialise interface without libusb device pointer."); - } + ::hid_init(); + ::hid_device* hidDevice = nullptr; - hid_init(); - hid_device* hidDevice = nullptr; - - std::string hidInterfacePath = this->getDevicePathByInterfaceNumber(this->getNumber()); + const auto hidInterfacePath = this->getHidDevicePath(); 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."); } - if (hidDevice->input_ep_max_packet_size < 1) { + this->hidDevice.reset(hidDevice); + + if (this->hidDevice->input_ep_max_packet_size < 1) { throw DeviceInitializationFailure( "Invalid max packet size for USB endpoint, on interface " - + std::to_string(this->getNumber()) + + std::to_string(this->interfaceNumber) ); } - this->setHidDevice(hidDevice); - this->setInputReportSize(static_cast(hidDevice->input_ep_max_packet_size)); - this->libUsbDeviceHandle = hidDevice->device_handle; - this->initialised = true; + this->inputReportSize = static_cast(this->hidDevice->input_ep_max_packet_size); } void HidInterface::close() { - auto* hidDevice = this->getHidDevice(); - - if (hidDevice != nullptr) { - this->libUsbDeviceHandle = nullptr; - hid_close(hidDevice); - // hid_close() releases the interface - this->claimed = false; - } - - hid_exit(); - Interface::close(); + this->hidDevice.reset(); + ::hid_exit(); } - std::vector HidInterface::read(unsigned int timeout) { - std::vector output; - auto readSize = this->getInputReportSize(); + std::vector HidInterface::read(std::optional timeout) { + auto output = std::vector(); - // Attempt to read the first HID report packet, and whatever is left after that. - output.resize(readSize); - auto transferredByteCount = this->read(output.data(), readSize, timeout); - auto totalByteCount = transferredByteCount; + const auto readSize = this->inputReportSize; + auto transferredByteCount = int(0); + auto totalByteCount = std::size_t(0); - while (transferredByteCount >= readSize) { - output.resize(totalByteCount + readSize); + do { + output.resize(totalByteCount + readSize, 0x00); - transferredByteCount = this->read(output.data() + totalByteCount, readSize, 1); - totalByteCount += transferredByteCount; - } + transferredByteCount = ::hid_read_timeout( + this->hidDevice.get(), + output.data() + totalByteCount, + readSize, + timeout.has_value() ? static_cast(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(transferredByteCount); + + } while (transferredByteCount >= readSize); + + output.resize(totalByteCount, 0x00); return output; } @@ -89,49 +95,35 @@ namespace Bloom::Usb int transferred = 0; 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) + " bytes to HID interface. Bytes written: " + std::to_string(transferred)); throw DeviceCommunicationFailure("Failed to write data to HID interface."); } } - std::size_t HidInterface::read(unsigned char* buffer, std::size_t maxLength, unsigned int timeout) { - int transferred; - - if ((transferred = hid_read_timeout( - this->hidDevice, - buffer, - maxLength, - timeout == 0 ? -1 : static_cast(timeout)) - ) == -1 - ) { - throw DeviceCommunicationFailure("Failed to read from HID device."); - } - - return static_cast(transferred); - } - - std::string HidInterface::getDevicePathByInterfaceNumber(const std::uint16_t& interfaceNumber) { - hid_device_info* hidDeviceInfoList = hid_enumerate( - this->getVendorId(), - this->getProductId() + std::string HidInterface::getHidDevicePath() { + const auto hidDeviceInfoList = std::unique_ptr<::hid_device_info, decltype(&::hid_free_enumeration)>( + ::hid_enumerate(this->vendorId, this->productId), + ::hid_free_enumeration ); - while (hidDeviceInfoList != nullptr) { - if (hidDeviceInfoList->interface_number == interfaceNumber) { + auto matchedDevice = std::optional<::hid_device_info*>(); + + auto* hidDeviceInfo = hidDeviceInfoList.get(); + while (hidDeviceInfo != nullptr) { + if (hidDeviceInfo->interface_number == this->interfaceNumber) { + matchedDevice = hidDeviceInfo; break; } - hidDeviceInfoList = hidDeviceInfoList->next; + hidDeviceInfo = hidDeviceInfoList->next; } - if (hidDeviceInfoList == nullptr) { + if (!matchedDevice.has_value()) { throw DeviceInitializationFailure("Failed to match interface number with HID interface."); } - auto path = std::string(hidDeviceInfoList->path); - hid_free_enumeration(hidDeviceInfoList); - return path; + return std::string(matchedDevice.value()->path); } } diff --git a/src/DebugToolDrivers/USB/HID/HidInterface.hpp b/src/DebugToolDrivers/USB/HID/HidInterface.hpp index 38851145..07894010 100644 --- a/src/DebugToolDrivers/USB/HID/HidInterface.hpp +++ b/src/DebugToolDrivers/USB/HID/HidInterface.hpp @@ -1,11 +1,13 @@ #pragma once #include +#include #include #include +#include +#include #include "hidapi.hpp" -#include "src/DebugToolDrivers/USB/Interface.hpp" namespace Bloom::Usb { @@ -15,35 +17,46 @@ namespace Bloom::Usb * Currently, this interface only supports single-report HID implementations. HID interfaces with * multiple reports will be supported as-and-when we need it. */ - class HidInterface: public Interface + class HidInterface { 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 { 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. * - * If `timeout` is set to 0, this method will block until at least one HID report - * packet is received. - * * @param timeout * * @return * A vector of the data received from the device. */ - std::vector read(unsigned int timeout = 0); + std::vector read(std::optional timeout = std::nullopt); /** * Writes buffer to HID output endpoint. @@ -52,59 +65,20 @@ namespace Bloom::Usb */ void write(std::vector&& buffer); - /** - * 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; - } + std::string getHidDevicePath(); private: - /** - * The HIDAPI library provides a hid_device data structure to represent a USB HID interface. - * - * @see hidapi.hpp or the HIDAPI documentation for more on this. - */ - hid_device* hidDevice = nullptr; + using HidDeviceType = std::unique_ptr<::hid_device, decltype(&::hid_close)>; + + HidDeviceType hidDevice = HidDeviceType(nullptr, ::hid_close); /** - * All HID reports have a fixed report length. This means that every packet - * we send or receive to/from an HID endpoint must be equal to the report length in size. - * - * The default input report size is 64 bytes, but this is overridden at interface initialisation. - * @see definition of init() for more on this. + * All HID reports have a fixed report length. This means that every packet we send or receive to/from an HID + * endpoint must be equal (in size) to the report length. */ std::size_t inputReportSize = 64; - void setHidDevice(hid_device* hidDevice) { - this->hidDevice = hidDevice; - } - - 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. 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); + std::uint16_t vendorId = 0; + std::uint16_t productId = 0; }; } diff --git a/src/DebugToolDrivers/USB/Interface.cpp b/src/DebugToolDrivers/USB/Interface.cpp deleted file mode 100644 index 73445cf9..00000000 --- a/src/DebugToolDrivers/USB/Interface.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include "Interface.hpp" - -#include - -#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(length), - &transferred, - static_cast(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) - ); - } - } -} diff --git a/src/DebugToolDrivers/USB/Interface.hpp b/src/DebugToolDrivers/USB/Interface.hpp deleted file mode 100644 index c646a9c5..00000000 --- a/src/DebugToolDrivers/USB/Interface.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#pragma once - -#include -#include -#include - -#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; - }; -} diff --git a/src/DebugToolDrivers/USB/UsbDevice.cpp b/src/DebugToolDrivers/USB/UsbDevice.cpp index 3080872f..b08d828a 100644 --- a/src/DebugToolDrivers/USB/UsbDevice.cpp +++ b/src/DebugToolDrivers/USB/UsbDevice.cpp @@ -1,5 +1,7 @@ #include "UsbDevice.hpp" +#include + #include "src/Logger/Logger.hpp" #include "src/TargetController/Exceptions/DeviceInitializationFailure.hpp" @@ -7,103 +9,134 @@ namespace Bloom::Usb { 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() { - libusb_init(&this->libUsbContext); -// libusb_set_option(this->libUsbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE); - auto devices = this->findMatchingDevices(); +// ::libusb_set_option(this->libusbContext, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_NONE); + auto devices = this->findMatchingDevices(this->vendorId, this->productId); 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) { - // TODO: implement support for multiple devices (maybe via serial number?) + // TODO: implement support for multiple devices via serial number matching? 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." ); } // For now, just use the first device found. - auto* device = devices.front(); - this->setLibUsbDevice(device); + this->libusbDevice.swap(devices.front()); + ::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( - "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) { - libusb_config_descriptor* configDescriptor = {}; - int libUsbStatusCode = libusb_get_config_descriptor(this->libUsbDevice, 0, &configDescriptor); + ::libusb_config_descriptor* configDescriptor = {}; + int libusbStatusCode = ::libusb_get_config_descriptor(this->libusbDevice.get(), 0, &configDescriptor); - if (libUsbStatusCode < 0) { + if (libusbStatusCode < 0) { 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." ); } - libUsbStatusCode = libusb_set_configuration(this->libUsbDeviceHandle, configDescriptor->bConfigurationValue); - if (libUsbStatusCode < 0) { + libusbStatusCode = ::libusb_set_configuration( + this->libusbDeviceHandle.get(), + configDescriptor->bConfigurationValue + ); + + if (libusbStatusCode < 0) { 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 UsbDevice::findMatchingDevices( - std::optional vendorId, std::optional productId + std::vector UsbDevice::findMatchingDevices( + std::uint16_t vendorId, std::uint16_t productId ) { - auto* libUsbContext = this->libUsbContext; - libusb_device** devices = nullptr; - libusb_device* device; - std::vector matchedDevices; + ::libusb_device** devices = nullptr; + ::libusb_device* device; + std::vector matchedDevices; - auto vendorIdToMatch = vendorId.value_or(this->vendorId); - auto productIdToMatch = productId.value_or(this->productId); - - ssize_t libUsbStatusCode = libusb_get_device_list(libUsbContext, &devices); - if (libUsbStatusCode < 0) { + auto libusbStatusCode = ::libusb_get_device_list(UsbDevice::libusbContext.get(), &devices); + if (libusbStatusCode < 0) { 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; 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: '" - + std::to_string(libUsbStatusCode) + "'"); + + std::to_string(libusbStatusCode) + "'"); continue; } - if (desc.idVendor == vendorIdToMatch && desc.idProduct == productIdToMatch) { - matchedDevices.push_back(device); + if (desc.idVendor != vendorId || desc.idProduct != productId) { + continue; } + + matchedDevices.emplace_back(std::move(libusbDevice)); } - libusb_free_device_list(devices, 1); + ::libusb_free_device_list(devices, 0); return matchedDevices; } - void UsbDevice::close() { - if (this->libUsbDeviceHandle != nullptr) { - libusb_close(this->libUsbDeviceHandle); - this->libUsbDeviceHandle = nullptr; - } + void UsbDevice::detachKernelDriverFromInterface(std::uint8_t interfaceNumber) { + const auto libusbStatusCode = ::libusb_kernel_driver_active(this->libusbDeviceHandle.get(), interfaceNumber); - if (this->libUsbContext != nullptr) { - libusb_exit(this->libUsbContext); + if (libusbStatusCode == 1) { + // 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(); + } } diff --git a/src/DebugToolDrivers/USB/UsbDevice.hpp b/src/DebugToolDrivers/USB/UsbDevice.hpp index f7efb167..9ceb71c3 100644 --- a/src/DebugToolDrivers/USB/UsbDevice.hpp +++ b/src/DebugToolDrivers/USB/UsbDevice.hpp @@ -10,37 +10,26 @@ 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 { 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& operator = (const UsbDevice& other) = default; UsbDevice& operator = (UsbDevice&& other) = default; 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. * @@ -48,16 +37,17 @@ namespace Bloom::Usb */ virtual void setConfiguration(int configIndex); - protected: - libusb_context* libUsbContext = nullptr; - libusb_device* libUsbDevice = nullptr; - libusb_device_handle* libUsbDeviceHandle = nullptr; - std::uint16_t vendorId; - std::uint16_t productId; + virtual ~UsbDevice(); - std::vector findMatchingDevices( - std::optional vendorId = std::nullopt, std::optional productId = std::nullopt - ); + protected: + static inline LibusbContextType libusbContext = LibusbContextType(nullptr, ::libusb_exit); + + LibusbDeviceType libusbDevice = LibusbDeviceType(nullptr, ::libusb_unref_device); + LibusbDeviceHandleType libusbDeviceHandle = LibusbDeviceHandleType(nullptr, ::libusb_close); + + std::vector findMatchingDevices(std::uint16_t vendorId, std::uint16_t productId); + + void detachKernelDriverFromInterface(std::uint8_t interfaceNumber); void close(); };