From 17c169143c257a8f9e78a203b515898571208819 Mon Sep 17 00:00:00 2001 From: Dominykas Date: Tue, 11 Jun 2024 10:35:28 +0300 Subject: [PATCH 01/11] First iteration of hot-plug disconnect handling --- GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp | 9 +++++- src/boards/LimeSDR/LimeSDR.cpp | 11 ++++++- src/boards/LimeSDR/LimeSDR.h | 4 ++- src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp | 11 ++++++- src/boards/LimeSDR_Mini/LimeSDR_Mini.h | 5 ++-- src/boards/LimeSDR_X3/LimeSDR_X3.cpp | 4 ++- src/boards/LimeSDR_X3/LimeSDR_X3.h | 4 ++- src/boards/LimeSDR_XTRX/LimeSDR_XTRX.cpp | 4 ++- src/boards/LimeSDR_XTRX/LimeSDR_XTRX.h | 4 ++- src/boards/MMX8/MM_X8.cpp | 4 ++- src/boards/MMX8/MM_X8.h | 4 ++- src/comms/USB/FT601/FT601.cpp | 9 ++++++ src/comms/USB/FT601/FT601.h | 2 ++ src/comms/USB/FX3/FX3.cpp | 21 +++++++++++-- src/comms/USB/FX3/FX3.h | 2 ++ src/comms/USB/IUSB.h | 8 +++++ src/comms/USB/USBGeneric.cpp | 30 +++++++++++++++++++ src/comms/USB/USBGeneric.h | 22 +++++++++++--- src/include/limesuiteng/SDRDevice.h | 15 +++++++++- 19 files changed, 153 insertions(+), 20 deletions(-) diff --git a/GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp b/GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp index 826cf74bf..96861efd1 100644 --- a/GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp +++ b/GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp @@ -465,7 +465,14 @@ void fftviewer_frFFTviewer::StreamingLoop( try { - pthis->device->StreamSetup(config, chipIndex); + pthis->device->StreamSetup(config, + chipIndex, + { [](void* data) { + lime::error("Testing how many times this gets called"); + auto* const viewer = reinterpret_cast(data); + viewer->StopStreaming(); + }, + pthis }); pthis->device->StreamStart(chipIndex); } catch (std::logic_error& e) { diff --git a/src/boards/LimeSDR/LimeSDR.cpp b/src/boards/LimeSDR/LimeSDR.cpp index 149b692fe..b82f1bb13 100644 --- a/src/boards/LimeSDR/LimeSDR.cpp +++ b/src/boards/LimeSDR/LimeSDR.cpp @@ -491,7 +491,8 @@ void LimeSDR::ResetUSBFIFO() } } -OpStatus LimeSDR::StreamSetup(const StreamConfig& config, uint8_t moduleIndex) +OpStatus LimeSDR::StreamSetup( + const StreamConfig& config, uint8_t moduleIndex, const CallbackInfo& hotplugDisconnectCallback) { // Allow multiple setup calls if (mStreamers.at(moduleIndex) != nullptr) @@ -499,6 +500,14 @@ OpStatus LimeSDR::StreamSetup(const StreamConfig& config, uint8_t moduleIndex) delete mStreamers.at(moduleIndex); } + mStreamPort->AddOnHotplugDisconnectCallback( + [&hotplugDisconnectCallback](void* userData) { + hotplugDisconnectCallback.function(hotplugDisconnectCallback.userData); + auto* const sdr = reinterpret_cast(userData); + sdr->StreamStop(0); + }, + this); + constexpr uint8_t rxBulkEndpoint = 0x81; constexpr uint8_t txBulkEndpoint = 0x01; auto rxdma = std::make_shared(mStreamPort, rxBulkEndpoint, DataTransferDirection::DeviceToHost); diff --git a/src/boards/LimeSDR/LimeSDR.h b/src/boards/LimeSDR/LimeSDR.h index 14520e57f..475c6734c 100644 --- a/src/boards/LimeSDR/LimeSDR.h +++ b/src/boards/LimeSDR/LimeSDR.h @@ -36,7 +36,9 @@ class LimeSDR : public LMS7002M_SDRDevice OpStatus SPI(uint32_t chipSelect, const uint32_t* MOSI, uint32_t* MISO, uint32_t count) override; - OpStatus StreamSetup(const StreamConfig& config, uint8_t moduleIndex) override; + OpStatus StreamSetup(const StreamConfig& config, + uint8_t moduleIndex, + const CallbackInfo& hotplugDisconnectCallback) override; void StreamStart(uint8_t moduleIndex) override; void StreamStop(uint8_t moduleIndex) override; diff --git a/src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp b/src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp index fe54303bd..f59867b68 100644 --- a/src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp +++ b/src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp @@ -526,7 +526,8 @@ SDRDescriptor LimeSDR_Mini::GetDeviceInfo(void) return deviceDescriptor; } -OpStatus LimeSDR_Mini::StreamSetup(const StreamConfig& config, uint8_t moduleIndex) +OpStatus LimeSDR_Mini::StreamSetup( + const StreamConfig& config, uint8_t moduleIndex, const CallbackInfo& hotplugDisconnectCallback) { if (moduleIndex != 0) return ReportError(OpStatus::InvalidValue, "StreamSetup: invalid module index"); @@ -540,6 +541,14 @@ OpStatus LimeSDR_Mini::StreamSetup(const StreamConfig& config, uint8_t moduleInd FT601* ftdi = dynamic_cast(mStreamPort.get()); ftdi->ResetStreamBuffers(); + mStreamPort->AddOnHotplugDisconnectCallback( + [&hotplugDisconnectCallback](void* userData) { + hotplugDisconnectCallback.function(hotplugDisconnectCallback.userData); + auto* const mini = reinterpret_cast(userData); + mini->StreamStop(0); + }, + this); + auto rxdma = std::make_shared(mStreamPort, STREAM_BULK_READ_ADDRESS, DataTransferDirection::DeviceToHost); auto txdma = std::make_shared(mStreamPort, STREAM_BULK_WRITE_ADDRESS, DataTransferDirection::HostToDevice); diff --git a/src/boards/LimeSDR_Mini/LimeSDR_Mini.h b/src/boards/LimeSDR_Mini/LimeSDR_Mini.h index 32bb480bf..b6eacb46c 100644 --- a/src/boards/LimeSDR_Mini/LimeSDR_Mini.h +++ b/src/boards/LimeSDR_Mini/LimeSDR_Mini.h @@ -9,7 +9,6 @@ namespace lime { -class USBGeneric; class IComms; class IUSB; @@ -39,7 +38,9 @@ class LimeSDR_Mini : public LMS7002M_SDRDevice OpStatus SPI(uint32_t chipSelect, const uint32_t* MOSI, uint32_t* MISO, uint32_t count) override; - OpStatus StreamSetup(const StreamConfig& config, uint8_t moduleIndex) override; + OpStatus StreamSetup(const StreamConfig& config, + uint8_t moduleIndex, + const CallbackInfo& hotplugDisconnectCallback) override; void StreamStart(uint8_t moduleIndex) override; void StreamStop(uint8_t moduleIndex) override; diff --git a/src/boards/LimeSDR_X3/LimeSDR_X3.cpp b/src/boards/LimeSDR_X3/LimeSDR_X3.cpp index f148029e1..fbb107946 100644 --- a/src/boards/LimeSDR_X3/LimeSDR_X3.cpp +++ b/src/boards/LimeSDR_X3/LimeSDR_X3.cpp @@ -865,7 +865,9 @@ OpStatus LimeSDR_X3::SPI(uint32_t chipSelect, const uint32_t* MOSI, uint32_t* MI } } -OpStatus LimeSDR_X3::StreamSetup(const StreamConfig& config, uint8_t moduleIndex) +OpStatus LimeSDR_X3::StreamSetup(const StreamConfig& config, + uint8_t moduleIndex, + [[maybe_unused]] const CallbackInfo& hotplugDisconnectCallback) { // Allow multiple setup calls if (mStreamers.at(moduleIndex) != nullptr) diff --git a/src/boards/LimeSDR_X3/LimeSDR_X3.h b/src/boards/LimeSDR_X3/LimeSDR_X3.h index 527318e08..3e03590c3 100644 --- a/src/boards/LimeSDR_X3/LimeSDR_X3.h +++ b/src/boards/LimeSDR_X3/LimeSDR_X3.h @@ -41,7 +41,9 @@ class LimeSDR_X3 : public LMS7002M_SDRDevice OpStatus SPI(uint32_t chipSelect, const uint32_t* MOSI, uint32_t* MISO, uint32_t count) override; - OpStatus StreamSetup(const StreamConfig& config, uint8_t moduleIndex) override; + OpStatus StreamSetup(const StreamConfig& config, + uint8_t moduleIndex, + const CallbackInfo& hotplugDisconnectCallback) override; void StreamStop(uint8_t moduleIndex) override; OpStatus CustomParameterWrite(const std::vector& parameters) override; diff --git a/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.cpp b/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.cpp index ee3ff9620..e583e010b 100644 --- a/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.cpp +++ b/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.cpp @@ -364,7 +364,9 @@ OpStatus LimeSDR_XTRX::SPI(uint32_t chipSelect, const uint32_t* MOSI, uint32_t* } } -OpStatus LimeSDR_XTRX::StreamSetup(const StreamConfig& config, uint8_t moduleIndex) +OpStatus LimeSDR_XTRX::StreamSetup(const StreamConfig& config, + uint8_t moduleIndex, + [[maybe_unused]] const CallbackInfo& hotplugDisconnectCallback) { // Allow multiple setup calls if (mStreamers.at(moduleIndex) != nullptr) diff --git a/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.h b/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.h index 9f07d7c4a..a750e46f1 100644 --- a/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.h +++ b/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.h @@ -37,7 +37,9 @@ class LimeSDR_XTRX : public LMS7002M_SDRDevice OpStatus SPI(uint32_t chipSelect, const uint32_t* MOSI, uint32_t* MISO, uint32_t count) override; - OpStatus StreamSetup(const StreamConfig& config, uint8_t moduleIndex) override; + OpStatus StreamSetup(const StreamConfig& config, + uint8_t moduleIndex, + const CallbackInfo& hotplugDisconnectCallback = { 0, nullptr }) override; void StreamStop(uint8_t moduleIndex) override; OpStatus CustomParameterWrite(const std::vector& parameters) override; diff --git a/src/boards/MMX8/MM_X8.cpp b/src/boards/MMX8/MM_X8.cpp index 3a00182ac..2ef9c42e9 100644 --- a/src/boards/MMX8/MM_X8.cpp +++ b/src/boards/MMX8/MM_X8.cpp @@ -611,7 +611,9 @@ ChannelConfig::Direction::TestSignal LimeSDR_MMX8::GetTestSignal(uint8_t moduleI return mSubDevices[moduleIndex]->GetTestSignal(0, direction, channel); } -OpStatus LimeSDR_MMX8::StreamSetup(const StreamConfig& config, uint8_t moduleIndex) +OpStatus LimeSDR_MMX8::StreamSetup(const StreamConfig& config, + uint8_t moduleIndex, + [[maybe_unused]] const CallbackInfo& hotplugDisconnectCallback) { OpStatus ret = mSubDevices[moduleIndex]->StreamSetup(config, 0); if (ret != OpStatus::Success) diff --git a/src/boards/MMX8/MM_X8.h b/src/boards/MMX8/MM_X8.h index 032f870eb..f5de4f0dd 100644 --- a/src/boards/MMX8/MM_X8.h +++ b/src/boards/MMX8/MM_X8.h @@ -117,7 +117,9 @@ class LimeSDR_MMX8 : public SDRDevice uint64_t GetHardwareTimestamp(uint8_t moduleIndex) override; OpStatus SetHardwareTimestamp(uint8_t moduleIndex, const uint64_t now) override; - OpStatus StreamSetup(const StreamConfig& config, uint8_t moduleIndex) override; + OpStatus StreamSetup(const StreamConfig& config, + uint8_t moduleIndex, + const CallbackInfo& hotplugDisconnectCallback) override; void StreamStart(uint8_t moduleIndex) override; void StreamStart(const std::vector moduleIndexes) override; void StreamStop(uint8_t moduleIndex) override; diff --git a/src/comms/USB/FT601/FT601.cpp b/src/comms/USB/FT601/FT601.cpp index 8f68df784..facd77e16 100644 --- a/src/comms/USB/FT601/FT601.cpp +++ b/src/comms/USB/FT601/FT601.cpp @@ -373,4 +373,13 @@ int FT601::FT_SetStreamPipe(unsigned char ep, size_t size) } #endif +void FT601::AddOnHotplugDisconnectCallback(const IUSB::HotplugDisconnectCallbackType& function, void* userData) +{ +#ifdef __unix__ + libusb_impl.AddOnHotplugDisconnectCallback(function, userData); +#else + // TODO: IMPLEMENT +#endif +} + } // namespace lime diff --git a/src/comms/USB/FT601/FT601.h b/src/comms/USB/FT601/FT601.h index 50ab86577..662988f88 100644 --- a/src/comms/USB/FT601/FT601.h +++ b/src/comms/USB/FT601/FT601.h @@ -41,6 +41,8 @@ class FT601 : public IUSB */ OpStatus ResetStreamBuffers(); + void AddOnHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) override; + protected: #ifdef __unix__ USBGeneric libusb_impl; diff --git a/src/comms/USB/FX3/FX3.cpp b/src/comms/USB/FX3/FX3.cpp index 10b08f817..ca59f4263 100644 --- a/src/comms/USB/FX3/FX3.cpp +++ b/src/comms/USB/FX3/FX3.cpp @@ -2,7 +2,6 @@ #include -using namespace lime; using namespace std::literals::string_literals; #ifdef __unix__ @@ -14,13 +13,18 @@ using namespace std::literals::string_literals; #ifdef __GNUC__ #pragma GCC diagnostic pop #endif -const int FX3::CTR_WRITE_REQUEST_VALUE = LIBUSB_REQUEST_TYPE_VENDOR; -const int FX3::CTR_READ_REQUEST_VALUE = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN; #else #include "windows.h" #include "CyAPI.h" #include +#endif + +namespace lime { +#ifdef __unix__ +const int FX3::CTR_WRITE_REQUEST_VALUE = LIBUSB_REQUEST_TYPE_VENDOR; +const int FX3::CTR_READ_REQUEST_VALUE = LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN; +#else class FX3AsyncContext { public: @@ -250,3 +254,14 @@ void FX3::FreeAsyncContext(void* context) delete reinterpret_cast(context); #endif } + +void FX3::AddOnHotplugDisconnectCallback(const IUSB::HotplugDisconnectCallbackType& function, void* userData) +{ +#ifdef __unix__ + libusb_impl.AddOnHotplugDisconnectCallback(function, userData); +#else + // TODO: IMPLEMENT +#endif +} + +} // namespace lime diff --git a/src/comms/USB/FX3/FX3.h b/src/comms/USB/FX3/FX3.h index bc4197b73..ed6335593 100644 --- a/src/comms/USB/FX3/FX3.h +++ b/src/comms/USB/FX3/FX3.h @@ -38,6 +38,8 @@ class FX3 : public IUSB int32_t ControlTransfer( int requestType, int request, int value, int index, uint8_t* data, size_t length, int32_t timeout_ms) override; + void AddOnHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) override; + static const int CTR_WRITE_REQUEST_VALUE; static const int CTR_READ_REQUEST_VALUE; diff --git a/src/comms/USB/IUSB.h b/src/comms/USB/IUSB.h index b7dbf15f4..d3068c8aa 100644 --- a/src/comms/USB/IUSB.h +++ b/src/comms/USB/IUSB.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "limesuiteng/OpStatus.h" namespace lime { @@ -116,6 +117,13 @@ class IUSB @param context Pointer to transfer context (retuned by AllocateAsyncContext). */ virtual void FreeAsyncContext(void* context) = 0; + + typedef std::function HotplugDisconnectCallbackType; + template struct CallbackInfo { + T function; + void* userData; + }; + virtual void AddOnHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) = 0; }; } // namespace lime diff --git a/src/comms/USB/USBGeneric.cpp b/src/comms/USB/USBGeneric.cpp index bf44510a6..8333c8f93 100644 --- a/src/comms/USB/USBGeneric.cpp +++ b/src/comms/USB/USBGeneric.cpp @@ -110,6 +110,19 @@ static void process_libusbtransfer(libusb_transfer* trans) context->cv.notify_one(); } +int USBGeneric::HotplugCallback(libusb_context* ctx, libusb_device* device, libusb_hotplug_event event, void* user_data) +{ + auto* usb = reinterpret_cast(user_data); + + for (const auto& callback : usb->hotplugDisconnectCallbacks) + { + callback.function(callback.userData); + } + + usb->Disconnect(); + return 1; +} + USBGeneric::AsyncContext::AsyncContext() : transfer(libusb_alloc_transfer(0)) , bytesXfered(0) @@ -258,7 +271,19 @@ bool USBGeneric::Connect(uint16_t vid, uint16_t pid, const char* serial) } if (std::string{ serial }.empty() || std::string{ serial } == foundSerial) + { + libusb_hotplug_register_callback(gContextLibUsb, + LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, + 0, + desc.idVendor, + desc.idProduct, + LIBUSB_HOTPLUG_MATCH_ANY, + HotplugCallback, + this, + nullptr); + break; //found it + } libusb_close(dev_handle); dev_handle = nullptr; @@ -409,4 +434,9 @@ OpStatus USBGeneric::ClaimInterface(int32_t interface_number) return OpStatus::Success; } +void USBGeneric::AddOnHotplugDisconnectCallback(const IUSB::HotplugDisconnectCallbackType& function, void* userData) +{ + hotplugDisconnectCallbacks.push_back({ function, userData }); +} + } // namespace lime diff --git a/src/comms/USB/USBGeneric.h b/src/comms/USB/USBGeneric.h index 90a1f988f..0f067fdab 100644 --- a/src/comms/USB/USBGeneric.h +++ b/src/comms/USB/USBGeneric.h @@ -5,8 +5,16 @@ #include #include -struct libusb_device_handle; -struct libusb_transfer; +#ifdef __unix__ + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wpedantic" + #endif + #include + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif +#endif namespace lime { @@ -52,10 +60,16 @@ class USBGeneric : IUSB OpStatus AbortXfer(void* context) override; void FreeAsyncContext(void* context) override; - virtual OpStatus ClaimInterface(int32_t interface_number); + OpStatus ClaimInterface(int32_t interface_number); - protected: + void AddOnHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) override; + + private: libusb_device_handle* dev_handle; //a device handle + + std::vector> hotplugDisconnectCallbacks{}; + + static int HotplugCallback(libusb_context* ctx, libusb_device* device, libusb_hotplug_event event, void* user_data); }; } // namespace lime diff --git a/src/include/limesuiteng/SDRDevice.h b/src/include/limesuiteng/SDRDevice.h index 34dd1e78c..b00667fcc 100644 --- a/src/include/limesuiteng/SDRDevice.h +++ b/src/include/limesuiteng/SDRDevice.h @@ -425,11 +425,24 @@ class LIME_API SDRDevice /// @return The status of the operation. virtual OpStatus SetHardwareTimestamp(uint8_t moduleIndex, const uint64_t now) = 0; + /// @brief The type of the function to call when a disconnect event happens. + typedef std::function HotplugDisconnectCallbackType; + + /// @brief The structure to hold the information for the callback + /// @tparam T The type of function to call + template struct CallbackInfo { + T function; + void* userData; + }; + /// @brief Sets up all the streams on a device. /// @param config The configuration to use for setting the streams up. /// @param moduleIndex The index of the device to set up. + /// @param hotplugDisconnectCallback The function to call if the device gets suddenly disconnected (USB only). /// @return The status code of the operation. - virtual OpStatus StreamSetup(const StreamConfig& config, uint8_t moduleIndex) = 0; + virtual OpStatus StreamSetup(const StreamConfig& config, + uint8_t moduleIndex, + const CallbackInfo& hotplugDisconnectCallback = { 0, nullptr }) = 0; /// @brief Starts all the set up streams on the device. /// @param moduleIndex The index of the device to start the streams on. From a08b4276a49a325e6654baec7ff9d36f9a3bc2f4 Mon Sep 17 00:00:00 2001 From: Dominykas Date: Tue, 11 Jun 2024 11:43:47 +0300 Subject: [PATCH 02/11] Add hotplug callback adding and removal --- GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp | 17 ++++---- src/boards/LMS7002M_SDRDevice.cpp | 10 +++++ src/boards/LMS7002M_SDRDevice.h | 3 ++ src/boards/LimeSDR/LimeSDR.cpp | 40 ++++++++++++++++--- src/boards/LimeSDR/LimeSDR.h | 9 +++-- src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp | 40 ++++++++++++++++--- src/boards/LimeSDR_Mini/LimeSDR_Mini.h | 9 +++-- src/boards/LimeSDR_X3/LimeSDR_X3.cpp | 4 +- src/boards/LimeSDR_X3/LimeSDR_X3.h | 4 +- src/boards/LimeSDR_XTRX/LimeSDR_XTRX.cpp | 4 +- src/boards/LimeSDR_XTRX/LimeSDR_XTRX.h | 4 +- src/boards/MMX8/MM_X8.cpp | 14 +++++-- src/boards/MMX8/MM_X8.h | 7 ++-- src/include/limesuiteng/SDRDevice.h | 38 +++++++++++------- 14 files changed, 147 insertions(+), 56 deletions(-) diff --git a/GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp b/GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp index 96861efd1..e9cc2589f 100644 --- a/GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp +++ b/GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp @@ -463,16 +463,16 @@ void fftviewer_frFFTviewer::StreamingLoop( const lime::complex32f_t* src[2] = { txPattern[0].data(), txPattern[1].data() };*/ + std::size_t callbackId = 0; try { - pthis->device->StreamSetup(config, - chipIndex, - { [](void* data) { - lime::error("Testing how many times this gets called"); - auto* const viewer = reinterpret_cast(data); - viewer->StopStreaming(); - }, - pthis }); + pthis->device->StreamSetup(config, chipIndex); + callbackId = pthis->device->AddHotplugDisconnectCallback( + [](void* data) { + auto* const viewer = reinterpret_cast(data); + viewer->StopStreaming(); + }, + pthis); pthis->device->StreamStart(chipIndex); } catch (std::logic_error& e) { @@ -653,6 +653,7 @@ void fftviewer_frFFTviewer::StreamingLoop( }*/ kiss_fft_free(m_fftCalcPlan); + pthis->device->RemoveHotplugDisconnectCallback(callbackId); pthis->stopProcessing.store(true); pthis->device->StreamStop(chipIndex); diff --git a/src/boards/LMS7002M_SDRDevice.cpp b/src/boards/LMS7002M_SDRDevice.cpp index e30790f4f..554d0d54b 100644 --- a/src/boards/LMS7002M_SDRDevice.cpp +++ b/src/boards/LMS7002M_SDRDevice.cpp @@ -1274,4 +1274,14 @@ OpStatus LMS7002M_SDRDevice::LMS7002TestSignalConfigure(LMS7002M* chip, const Ch return OpStatus::Success; } +std::size_t LMS7002M_SDRDevice::AddHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) +{ + return 0; +} + +void LMS7002M_SDRDevice::RemoveHotplugDisconnectCallback(std::size_t id) +{ + return; +} + } // namespace lime diff --git a/src/boards/LMS7002M_SDRDevice.h b/src/boards/LMS7002M_SDRDevice.h index 477b0bd83..d756975c9 100644 --- a/src/boards/LMS7002M_SDRDevice.h +++ b/src/boards/LMS7002M_SDRDevice.h @@ -125,6 +125,9 @@ class LIME_API LMS7002M_SDRDevice : public SDRDevice /// @copydoc FPGA::WriteRegister() virtual OpStatus WriteFPGARegister(uint32_t address, uint32_t value); + std::size_t AddHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) override; + void RemoveHotplugDisconnectCallback(std::size_t id) override; + protected: static OpStatus UpdateFPGAInterfaceFrequency(LMS7002M& soc, FPGA& fpga, uint8_t chipIndex); void SetGainInformationInDescriptor(RFSOCDescriptor& descriptor); diff --git a/src/boards/LimeSDR/LimeSDR.cpp b/src/boards/LimeSDR/LimeSDR.cpp index b82f1bb13..1a33d257b 100644 --- a/src/boards/LimeSDR/LimeSDR.cpp +++ b/src/boards/LimeSDR/LimeSDR.cpp @@ -24,11 +24,12 @@ #include #include -using namespace lime; using namespace lime::LMS64CProtocol; using namespace lime::LMS7002MCSR_Data; using namespace std::literals::string_literals; +namespace lime { + static const uint8_t SPI_LMS7002M = 0; static const uint8_t SPI_FPGA = 1; static const uint8_t SPI_ADF4002 = 2; @@ -491,8 +492,7 @@ void LimeSDR::ResetUSBFIFO() } } -OpStatus LimeSDR::StreamSetup( - const StreamConfig& config, uint8_t moduleIndex, const CallbackInfo& hotplugDisconnectCallback) +OpStatus LimeSDR::StreamSetup(const StreamConfig& config, uint8_t moduleIndex) { // Allow multiple setup calls if (mStreamers.at(moduleIndex) != nullptr) @@ -501,9 +501,14 @@ OpStatus LimeSDR::StreamSetup( } mStreamPort->AddOnHotplugDisconnectCallback( - [&hotplugDisconnectCallback](void* userData) { - hotplugDisconnectCallback.function(hotplugDisconnectCallback.userData); + [](void* userData) { auto* const sdr = reinterpret_cast(userData); + + for (const auto& callback : sdr->disconnectCallbacks) + { + callback(); + } + sdr->StreamStop(0); }, this); @@ -610,3 +615,28 @@ OpStatus LimeSDR::MemoryRead(std::shared_ptr storage, Region region return OpStatus::Error; return mfpgaPort->MemoryRead(region.address, data, region.size); } + +std::size_t LimeSDR::AddHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) +{ + std::size_t id = 0; + + if (!disconnectCallbacks.empty()) + { + // As long as elements are not out of order this guarantees a unique ID in the array. + id = disconnectCallbacks.back().id + 1; + } + + disconnectCallbacks.push_back({ function, userData, id }); + + return id; +} + +void LimeSDR::RemoveHotplugDisconnectCallback(std::size_t id) +{ + disconnectCallbacks.erase(std::remove_if(disconnectCallbacks.begin(), + disconnectCallbacks.end(), + [&id](const CallbackInfo& info) { return id == info.id; }), + disconnectCallbacks.end()); +} + +} // namespace lime diff --git a/src/boards/LimeSDR/LimeSDR.h b/src/boards/LimeSDR/LimeSDR.h index 475c6734c..6447ff5bf 100644 --- a/src/boards/LimeSDR/LimeSDR.h +++ b/src/boards/LimeSDR/LimeSDR.h @@ -36,9 +36,7 @@ class LimeSDR : public LMS7002M_SDRDevice OpStatus SPI(uint32_t chipSelect, const uint32_t* MOSI, uint32_t* MISO, uint32_t count) override; - OpStatus StreamSetup(const StreamConfig& config, - uint8_t moduleIndex, - const CallbackInfo& hotplugDisconnectCallback) override; + OpStatus StreamSetup(const StreamConfig& config, uint8_t moduleIndex) override; void StreamStart(uint8_t moduleIndex) override; void StreamStop(uint8_t moduleIndex) override; @@ -58,6 +56,9 @@ class LimeSDR : public LMS7002M_SDRDevice OpStatus MemoryWrite(std::shared_ptr storage, Region region, const void* data) override; OpStatus MemoryRead(std::shared_ptr storage, Region region, void* data) override; + std::size_t AddHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) override; + void RemoveHotplugDisconnectCallback(std::size_t id) override; + protected: SDRDescriptor GetDeviceInfo(); void ResetUSBFIFO(); @@ -79,6 +80,8 @@ class LimeSDR : public LMS7002M_SDRDevice std::shared_ptr mlms7002mPort; std::shared_ptr mfpgaPort; bool mConfigInProgress; + + std::vector> disconnectCallbacks; }; } // namespace lime diff --git a/src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp b/src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp index f59867b68..ee1082bd2 100644 --- a/src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp +++ b/src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp @@ -23,12 +23,13 @@ #include #include -using namespace lime; using namespace lime::LMS64CProtocol; using namespace lime::EqualizerCSR; using namespace lime::LMS7002MCSR_Data; using namespace std::literals::string_literals; +namespace lime { + static const int STREAM_BULK_WRITE_ADDRESS = 0x03; static const int STREAM_BULK_READ_ADDRESS = 0x83; @@ -526,8 +527,7 @@ SDRDescriptor LimeSDR_Mini::GetDeviceInfo(void) return deviceDescriptor; } -OpStatus LimeSDR_Mini::StreamSetup( - const StreamConfig& config, uint8_t moduleIndex, const CallbackInfo& hotplugDisconnectCallback) +OpStatus LimeSDR_Mini::StreamSetup(const StreamConfig& config, uint8_t moduleIndex) { if (moduleIndex != 0) return ReportError(OpStatus::InvalidValue, "StreamSetup: invalid module index"); @@ -542,9 +542,14 @@ OpStatus LimeSDR_Mini::StreamSetup( ftdi->ResetStreamBuffers(); mStreamPort->AddOnHotplugDisconnectCallback( - [&hotplugDisconnectCallback](void* userData) { - hotplugDisconnectCallback.function(hotplugDisconnectCallback.userData); + [](void* userData) { auto* const mini = reinterpret_cast(userData); + + for (const auto& callback : mini->disconnectCallbacks) + { + callback(); + } + mini->StreamStop(0); }, this); @@ -669,3 +674,28 @@ void LimeSDR_Mini::SetSerialNumber(const std::string& number) sscanf(number.c_str(), "%16lX", &sn); mDeviceDescriptor.serialNumber = sn; } + +std::size_t LimeSDR_Mini::AddHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) +{ + std::size_t id = 0; + + if (!disconnectCallbacks.empty()) + { + // As long as elements are not out of order this guarantees a unique ID in the array. + id = disconnectCallbacks.back().id + 1; + } + + disconnectCallbacks.push_back({ function, userData, id }); + + return id; +} + +void LimeSDR_Mini::RemoveHotplugDisconnectCallback(std::size_t id) +{ + disconnectCallbacks.erase(std::remove_if(disconnectCallbacks.begin(), + disconnectCallbacks.end(), + [&id](const CallbackInfo& info) { return id == info.id; }), + disconnectCallbacks.end()); +} + +} // namespace lime diff --git a/src/boards/LimeSDR_Mini/LimeSDR_Mini.h b/src/boards/LimeSDR_Mini/LimeSDR_Mini.h index b6eacb46c..b69dd85b8 100644 --- a/src/boards/LimeSDR_Mini/LimeSDR_Mini.h +++ b/src/boards/LimeSDR_Mini/LimeSDR_Mini.h @@ -38,9 +38,7 @@ class LimeSDR_Mini : public LMS7002M_SDRDevice OpStatus SPI(uint32_t chipSelect, const uint32_t* MOSI, uint32_t* MISO, uint32_t count) override; - OpStatus StreamSetup(const StreamConfig& config, - uint8_t moduleIndex, - const CallbackInfo& hotplugDisconnectCallback) override; + OpStatus StreamSetup(const StreamConfig& config, uint8_t moduleIndex) override; void StreamStart(uint8_t moduleIndex) override; void StreamStop(uint8_t moduleIndex) override; @@ -55,6 +53,9 @@ class LimeSDR_Mini : public LMS7002M_SDRDevice void SetSerialNumber(const std::string& number); + std::size_t AddHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) override; + void RemoveHotplugDisconnectCallback(std::size_t id) override; + protected: SDRDescriptor GetDeviceInfo(); static OpStatus UpdateFPGAInterface(void* userData); @@ -65,6 +66,8 @@ class LimeSDR_Mini : public LMS7002M_SDRDevice std::shared_ptr mlms7002mPort; std::shared_ptr mfpgaPort; bool mConfigInProgress{}; + + std::vector> disconnectCallbacks; }; } // namespace lime diff --git a/src/boards/LimeSDR_X3/LimeSDR_X3.cpp b/src/boards/LimeSDR_X3/LimeSDR_X3.cpp index fbb107946..f148029e1 100644 --- a/src/boards/LimeSDR_X3/LimeSDR_X3.cpp +++ b/src/boards/LimeSDR_X3/LimeSDR_X3.cpp @@ -865,9 +865,7 @@ OpStatus LimeSDR_X3::SPI(uint32_t chipSelect, const uint32_t* MOSI, uint32_t* MI } } -OpStatus LimeSDR_X3::StreamSetup(const StreamConfig& config, - uint8_t moduleIndex, - [[maybe_unused]] const CallbackInfo& hotplugDisconnectCallback) +OpStatus LimeSDR_X3::StreamSetup(const StreamConfig& config, uint8_t moduleIndex) { // Allow multiple setup calls if (mStreamers.at(moduleIndex) != nullptr) diff --git a/src/boards/LimeSDR_X3/LimeSDR_X3.h b/src/boards/LimeSDR_X3/LimeSDR_X3.h index 3e03590c3..527318e08 100644 --- a/src/boards/LimeSDR_X3/LimeSDR_X3.h +++ b/src/boards/LimeSDR_X3/LimeSDR_X3.h @@ -41,9 +41,7 @@ class LimeSDR_X3 : public LMS7002M_SDRDevice OpStatus SPI(uint32_t chipSelect, const uint32_t* MOSI, uint32_t* MISO, uint32_t count) override; - OpStatus StreamSetup(const StreamConfig& config, - uint8_t moduleIndex, - const CallbackInfo& hotplugDisconnectCallback) override; + OpStatus StreamSetup(const StreamConfig& config, uint8_t moduleIndex) override; void StreamStop(uint8_t moduleIndex) override; OpStatus CustomParameterWrite(const std::vector& parameters) override; diff --git a/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.cpp b/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.cpp index e583e010b..ee3ff9620 100644 --- a/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.cpp +++ b/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.cpp @@ -364,9 +364,7 @@ OpStatus LimeSDR_XTRX::SPI(uint32_t chipSelect, const uint32_t* MOSI, uint32_t* } } -OpStatus LimeSDR_XTRX::StreamSetup(const StreamConfig& config, - uint8_t moduleIndex, - [[maybe_unused]] const CallbackInfo& hotplugDisconnectCallback) +OpStatus LimeSDR_XTRX::StreamSetup(const StreamConfig& config, uint8_t moduleIndex) { // Allow multiple setup calls if (mStreamers.at(moduleIndex) != nullptr) diff --git a/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.h b/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.h index a750e46f1..9f07d7c4a 100644 --- a/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.h +++ b/src/boards/LimeSDR_XTRX/LimeSDR_XTRX.h @@ -37,9 +37,7 @@ class LimeSDR_XTRX : public LMS7002M_SDRDevice OpStatus SPI(uint32_t chipSelect, const uint32_t* MOSI, uint32_t* MISO, uint32_t count) override; - OpStatus StreamSetup(const StreamConfig& config, - uint8_t moduleIndex, - const CallbackInfo& hotplugDisconnectCallback = { 0, nullptr }) override; + OpStatus StreamSetup(const StreamConfig& config, uint8_t moduleIndex) override; void StreamStop(uint8_t moduleIndex) override; OpStatus CustomParameterWrite(const std::vector& parameters) override; diff --git a/src/boards/MMX8/MM_X8.cpp b/src/boards/MMX8/MM_X8.cpp index 2ef9c42e9..d073571f2 100644 --- a/src/boards/MMX8/MM_X8.cpp +++ b/src/boards/MMX8/MM_X8.cpp @@ -611,9 +611,7 @@ ChannelConfig::Direction::TestSignal LimeSDR_MMX8::GetTestSignal(uint8_t moduleI return mSubDevices[moduleIndex]->GetTestSignal(0, direction, channel); } -OpStatus LimeSDR_MMX8::StreamSetup(const StreamConfig& config, - uint8_t moduleIndex, - [[maybe_unused]] const CallbackInfo& hotplugDisconnectCallback) +OpStatus LimeSDR_MMX8::StreamSetup(const StreamConfig& config, uint8_t moduleIndex) { OpStatus ret = mSubDevices[moduleIndex]->StreamSetup(config, 0); if (ret != OpStatus::Success) @@ -832,4 +830,14 @@ OpStatus LimeSDR_MMX8::UploadTxWaveform(const StreamConfig& config, uint8_t modu return mSubDevices[moduleIndex]->UploadTxWaveform(config, 0, samples, count); } +std::size_t LimeSDR_MMX8::AddHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) +{ + return 0; +} + +void LimeSDR_MMX8::RemoveHotplugDisconnectCallback(std::size_t id) +{ + return; +} + } //namespace lime diff --git a/src/boards/MMX8/MM_X8.h b/src/boards/MMX8/MM_X8.h index f5de4f0dd..a7f990ca7 100644 --- a/src/boards/MMX8/MM_X8.h +++ b/src/boards/MMX8/MM_X8.h @@ -117,9 +117,7 @@ class LimeSDR_MMX8 : public SDRDevice uint64_t GetHardwareTimestamp(uint8_t moduleIndex) override; OpStatus SetHardwareTimestamp(uint8_t moduleIndex, const uint64_t now) override; - OpStatus StreamSetup(const StreamConfig& config, - uint8_t moduleIndex, - const CallbackInfo& hotplugDisconnectCallback) override; + OpStatus StreamSetup(const StreamConfig& config, uint8_t moduleIndex) override; void StreamStart(uint8_t moduleIndex) override; void StreamStart(const std::vector moduleIndexes) override; void StreamStop(uint8_t moduleIndex) override; @@ -151,6 +149,9 @@ class LimeSDR_MMX8 : public SDRDevice OpStatus MemoryRead(std::shared_ptr storage, Region region, void* data) override; OpStatus UploadTxWaveform(const StreamConfig& config, uint8_t moduleIndex, const void** samples, uint32_t count) override; + std::size_t AddHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) override; + void RemoveHotplugDisconnectCallback(std::size_t id) override; + private: std::shared_ptr mMainFPGAcomms; SDRDescriptor mDeviceDescriptor; diff --git a/src/include/limesuiteng/SDRDevice.h b/src/include/limesuiteng/SDRDevice.h index b00667fcc..79fe238ef 100644 --- a/src/include/limesuiteng/SDRDevice.h +++ b/src/include/limesuiteng/SDRDevice.h @@ -425,24 +425,11 @@ class LIME_API SDRDevice /// @return The status of the operation. virtual OpStatus SetHardwareTimestamp(uint8_t moduleIndex, const uint64_t now) = 0; - /// @brief The type of the function to call when a disconnect event happens. - typedef std::function HotplugDisconnectCallbackType; - - /// @brief The structure to hold the information for the callback - /// @tparam T The type of function to call - template struct CallbackInfo { - T function; - void* userData; - }; - /// @brief Sets up all the streams on a device. /// @param config The configuration to use for setting the streams up. /// @param moduleIndex The index of the device to set up. - /// @param hotplugDisconnectCallback The function to call if the device gets suddenly disconnected (USB only). /// @return The status code of the operation. - virtual OpStatus StreamSetup(const StreamConfig& config, - uint8_t moduleIndex, - const CallbackInfo& hotplugDisconnectCallback = { 0, nullptr }) = 0; + virtual OpStatus StreamSetup(const StreamConfig& config, uint8_t moduleIndex) = 0; /// @brief Starts all the set up streams on the device. /// @param moduleIndex The index of the device to start the streams on. @@ -585,6 +572,29 @@ class LIME_API SDRDevice /// @param serialNumber Device's serial number /// @return The operation success state. virtual OpStatus WriteSerialNumber(uint64_t serialNumber); + + /// @brief The type of the function to call when a disconnect event happens. + typedef std::function HotplugDisconnectCallbackType; + + /// @brief The structure to hold the information for the callback + /// @tparam T The type of function to call + template struct CallbackInfo { + T function; + void* userData; + std::size_t id; + + void operator()() const { return function(userData); } + }; + + /// @brief Adds a callback to run when a hotplug disconnect event happens (currently USB only). + /// @param function The function to run when a disconnect happens. + /// @param userData The data to pass into the function when it runs. + /// @return The ID of the callback for removal later. + virtual std::size_t AddHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) = 0; + + /// @brief Removes the given hotplug disconnect callback by ID. + /// @param id The ID of the callback to remove. + virtual void RemoveHotplugDisconnectCallback(std::size_t id) = 0; }; } // namespace lime From 291949da17fc4f209d310994fd3a3d8f2c95d2c5 Mon Sep 17 00:00:00 2001 From: Dominykas Date: Tue, 11 Jun 2024 14:01:32 +0300 Subject: [PATCH 03/11] Slight GUI file clean-up --- GUI/limeGUIFrame.cpp | 3 +-- GUI/limeGUIFrame.h | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/GUI/limeGUIFrame.cpp b/GUI/limeGUIFrame.cpp index 38d34a86c..b5c950a35 100644 --- a/GUI/limeGUIFrame.cpp +++ b/GUI/limeGUIFrame.cpp @@ -34,6 +34,7 @@ #include "limesuiteng/SDRDescriptor.h" #include "DeviceTreeNode.h" #include "limesuiteng/Logger.h" +#include "DeviceConnectionPanel.h" using namespace std; using namespace lime; @@ -43,8 +44,6 @@ static constexpr int controlColumn = 1; limeGUIFrame* limeGUIFrame::obj_ptr = nullptr; -int limeGUIFrame::m_lmsSelection = 0; - void limeGUIFrame::OnGlobalLogEvent(const lime::LogLevel level, const std::string& message) { if (obj_ptr == nullptr || obj_ptr->mMiniLog == nullptr) diff --git a/GUI/limeGUIFrame.h b/GUI/limeGUIFrame.h index 9e357a9c6..00a53a963 100644 --- a/GUI/limeGUIFrame.h +++ b/GUI/limeGUIFrame.h @@ -29,10 +29,6 @@ #include #include -#include "IModuleFrame.h" -#include "ISOCPanel.h" -#include "DeviceConnectionPanel.h" -#include "dlgAbout.h" #include "limeGUI.h" class pnlMiniLog; @@ -40,10 +36,21 @@ class lms7002_mainPanel; class fftviewer_frFFTviewer; class LMS_Programming_wxgui; class pnlBoardControls; +class IModuleFrame; +class ISOCPanel; + +namespace lime { +class SDRDevice; +class DeviceConnectionPanel; +} // namespace lime class limeGUIFrame : public wxFrame { - protected: + public: + limeGUIFrame(wxWindow* parent, const AppArgs& appArgs); + ~limeGUIFrame(); + + private: void AddModule(IModuleFrame* module, const std::string& title); void RemoveModule(IModuleFrame* module); // Handlers for AppFrame events. @@ -57,13 +64,6 @@ class limeGUIFrame : public wxFrame void DeviceTreeSelectionChanged(wxTreeEvent& event); - public: - limeGUIFrame(wxWindow* parent, const AppArgs& appArgs); - - virtual ~limeGUIFrame(); - static int m_lmsSelection; - - protected: static void OnGlobalLogEvent(const lime::LogLevel level, const std::string& message); void OnLogMessage(wxCommandEvent& event); void UpdateConnections(lime::SDRDevice* port); From cb44fe6f9932fba1f950e38c7f5f4f51c4c4f011 Mon Sep 17 00:00:00 2001 From: Dominykas Date: Tue, 11 Jun 2024 14:59:31 +0300 Subject: [PATCH 04/11] Fix small tiny piece of undefined behaviour --- embedded/lms7002m/privates.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embedded/lms7002m/privates.c b/embedded/lms7002m/privates.c index a4227998b..f19b3016c 100644 --- a/embedded/lms7002m/privates.c +++ b/embedded/lms7002m/privates.c @@ -59,7 +59,7 @@ void lms7002m_sleep(long timeInMicroseconds) void lms7002m_spi_write(lms7002m_context* self, uint16_t address, uint16_t value) { uint32_t mosi = address << 16 | value; - mosi |= 1 << 31; + mosi |= 0x80000000; self->hooks.spi16_transact(&mosi, NULL, 1, self->hooks.spi16_userData); } From 05107455264f4fe2d134025cfe43e6fec439ad84 Mon Sep 17 00:00:00 2001 From: Dominykas Date: Tue, 11 Jun 2024 15:18:46 +0300 Subject: [PATCH 05/11] Fix all related GUI crashes --- GUI/limeGUIFrame.cpp | 15 +++++++++++--- src/boards/LimeSDR/LimeSDR.cpp | 25 ++++++++++++------------ src/boards/LimeSDR/LimeSDR.h | 1 + src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp | 25 ++++++++++++------------ src/comms/USB/USBGeneric.cpp | 5 +++-- 5 files changed, 40 insertions(+), 31 deletions(-) diff --git a/GUI/limeGUIFrame.cpp b/GUI/limeGUIFrame.cpp index b5c950a35..2935eee0a 100644 --- a/GUI/limeGUIFrame.cpp +++ b/GUI/limeGUIFrame.cpp @@ -5,9 +5,9 @@ #endif //__BORLANDC__ #include +#include #include "chips/LMS7002M/lms7002_mainPanel.h" - #include "limeGUIFrame.h" #include "dlgAbout.h" #include "lms7suiteEvents.h" @@ -19,9 +19,7 @@ #include "utility/pnlMiniLog.h" #include "FPGAcontrols_wxgui.h" #include "utility/SPI_wxgui.h" -#include #include "utility/dlgDeviceInfo.h" -#include #include "boards/pnlBoardControls.h" #include "protocols/LMSBoards.h" #include "utility/SPI_wxgui.h" @@ -36,6 +34,8 @@ #include "limesuiteng/Logger.h" #include "DeviceConnectionPanel.h" +#include + using namespace std; using namespace lime; using namespace std::literals::string_literals; @@ -398,6 +398,15 @@ void limeGUIFrame::OnDeviceHandleChange(wxCommandEvent& event) wxPostEvent(this, evt); UpdateConnections(lmsControl); + lmsControl->AddHotplugDisconnectCallback( + [&](void* data) { + auto* evt = new wxCommandEvent(); + evt->SetEventType(limeEVT_SDR_HANDLE_SELECTED); + evt->SetString(wxEmptyString); + wxQueueEvent(this, evt); + }, + this); + Fit(); } catch (std::runtime_error& e) { diff --git a/src/boards/LimeSDR/LimeSDR.cpp b/src/boards/LimeSDR/LimeSDR.cpp index 1a33d257b..89e025304 100644 --- a/src/boards/LimeSDR/LimeSDR.cpp +++ b/src/boards/LimeSDR/LimeSDR.cpp @@ -155,6 +155,18 @@ LimeSDR::LimeSDR(std::shared_ptr spiLMS, mDeviceDescriptor = descriptor; + mStreamPort->AddOnHotplugDisconnectCallback( + [](void* userData) { + auto* const sdr = reinterpret_cast(userData); + + // Call in reverse order so that the "smaller" scoped callbacks run first. + for (auto iter = sdr->disconnectCallbacks.rbegin(); iter != sdr->disconnectCallbacks.rend(); ++iter) + { + (*iter)(); + } + }, + this); + //must configure synthesizer before using LimeSDR /*if (info.device == LMS_DEV_LIMESDR && info.hardware < 4) { @@ -500,19 +512,6 @@ OpStatus LimeSDR::StreamSetup(const StreamConfig& config, uint8_t moduleIndex) delete mStreamers.at(moduleIndex); } - mStreamPort->AddOnHotplugDisconnectCallback( - [](void* userData) { - auto* const sdr = reinterpret_cast(userData); - - for (const auto& callback : sdr->disconnectCallbacks) - { - callback(); - } - - sdr->StreamStop(0); - }, - this); - constexpr uint8_t rxBulkEndpoint = 0x81; constexpr uint8_t txBulkEndpoint = 0x01; auto rxdma = std::make_shared(mStreamPort, rxBulkEndpoint, DataTransferDirection::DeviceToHost); diff --git a/src/boards/LimeSDR/LimeSDR.h b/src/boards/LimeSDR/LimeSDR.h index 6447ff5bf..5e065185f 100644 --- a/src/boards/LimeSDR/LimeSDR.h +++ b/src/boards/LimeSDR/LimeSDR.h @@ -82,6 +82,7 @@ class LimeSDR : public LMS7002M_SDRDevice bool mConfigInProgress; std::vector> disconnectCallbacks; + std::size_t mStreamStopCallbackId; }; } // namespace lime diff --git a/src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp b/src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp index ee1082bd2..7e6364a9f 100644 --- a/src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp +++ b/src/boards/LimeSDR_Mini/LimeSDR_Mini.cpp @@ -206,6 +206,18 @@ LimeSDR_Mini::LimeSDR_Mini(std::shared_ptr spiLMS, descriptor.socTree->children.push_back(fpgaNode); mDeviceDescriptor = descriptor; + + mStreamPort->AddOnHotplugDisconnectCallback( + [](void* userData) { + auto* const mini = reinterpret_cast(userData); + + // Call in reverse order so that the "smaller" scoped callbacks run first. + for (auto iter = mini->disconnectCallbacks.rbegin(); iter != mini->disconnectCallbacks.rend(); ++iter) + { + (*iter)(); + } + }, + this); } LimeSDR_Mini::~LimeSDR_Mini() @@ -541,19 +553,6 @@ OpStatus LimeSDR_Mini::StreamSetup(const StreamConfig& config, uint8_t moduleInd FT601* ftdi = dynamic_cast(mStreamPort.get()); ftdi->ResetStreamBuffers(); - mStreamPort->AddOnHotplugDisconnectCallback( - [](void* userData) { - auto* const mini = reinterpret_cast(userData); - - for (const auto& callback : mini->disconnectCallbacks) - { - callback(); - } - - mini->StreamStop(0); - }, - this); - auto rxdma = std::make_shared(mStreamPort, STREAM_BULK_READ_ADDRESS, DataTransferDirection::DeviceToHost); auto txdma = std::make_shared(mStreamPort, STREAM_BULK_WRITE_ADDRESS, DataTransferDirection::HostToDevice); diff --git a/src/comms/USB/USBGeneric.cpp b/src/comms/USB/USBGeneric.cpp index 8333c8f93..7c74f9aa6 100644 --- a/src/comms/USB/USBGeneric.cpp +++ b/src/comms/USB/USBGeneric.cpp @@ -110,13 +110,14 @@ static void process_libusbtransfer(libusb_transfer* trans) context->cv.notify_one(); } +// Runs within the gUSBProcessingThread thread int USBGeneric::HotplugCallback(libusb_context* ctx, libusb_device* device, libusb_hotplug_event event, void* user_data) { auto* usb = reinterpret_cast(user_data); - for (const auto& callback : usb->hotplugDisconnectCallbacks) + for (auto iter = usb->hotplugDisconnectCallbacks.rbegin(); iter != usb->hotplugDisconnectCallbacks.rend(); ++iter) { - callback.function(callback.userData); + iter->function(iter->userData); } usb->Disconnect(); From 61727ad6eb431d3f33719be2a26e4c8d26a687d5 Mon Sep 17 00:00:00 2001 From: Dominykas Date: Tue, 11 Jun 2024 15:18:57 +0300 Subject: [PATCH 06/11] Make the IUSB struct nicer as well --- src/comms/USB/IUSB.h | 2 ++ src/comms/USB/USBGeneric.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/comms/USB/IUSB.h b/src/comms/USB/IUSB.h index d3068c8aa..885f70faa 100644 --- a/src/comms/USB/IUSB.h +++ b/src/comms/USB/IUSB.h @@ -122,6 +122,8 @@ class IUSB template struct CallbackInfo { T function; void* userData; + + void operator()() { return function(userData); } }; virtual void AddOnHotplugDisconnectCallback(const HotplugDisconnectCallbackType& function, void* userData) = 0; }; diff --git a/src/comms/USB/USBGeneric.cpp b/src/comms/USB/USBGeneric.cpp index 7c74f9aa6..1fdb8e7ee 100644 --- a/src/comms/USB/USBGeneric.cpp +++ b/src/comms/USB/USBGeneric.cpp @@ -117,7 +117,7 @@ int USBGeneric::HotplugCallback(libusb_context* ctx, libusb_device* device, libu for (auto iter = usb->hotplugDisconnectCallbacks.rbegin(); iter != usb->hotplugDisconnectCallbacks.rend(); ++iter) { - iter->function(iter->userData); + (*iter)(); } usb->Disconnect(); From 13ae46e23e2f00f4f621b2be35035521c81ff304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominykas=20Petkevi=C4=8Dius?= Date: Tue, 11 Jun 2024 15:57:18 +0300 Subject: [PATCH 07/11] Add note in FT601 code that hotplugging events are not supported by the library --- src/comms/USB/FT601/FT601.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/comms/USB/FT601/FT601.cpp b/src/comms/USB/FT601/FT601.cpp index facd77e16..f70a4dcbb 100644 --- a/src/comms/USB/FT601/FT601.cpp +++ b/src/comms/USB/FT601/FT601.cpp @@ -378,7 +378,7 @@ void FT601::AddOnHotplugDisconnectCallback(const IUSB::HotplugDisconnectCallback #ifdef __unix__ libusb_impl.AddOnHotplugDisconnectCallback(function, userData); #else - // TODO: IMPLEMENT + // Hotplug events are not supported by the library #endif } From 2cf4f615916e8a5428f9a8466c8e1cb01665840a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominykas=20Petkevi=C4=8Dius?= Date: Wed, 12 Jun 2024 09:42:34 +0300 Subject: [PATCH 08/11] Add note on Cypress API library hotplugging capabilities --- src/comms/USB/FX3/FX3.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/comms/USB/FX3/FX3.cpp b/src/comms/USB/FX3/FX3.cpp index ca59f4263..8dbcdafc1 100644 --- a/src/comms/USB/FX3/FX3.cpp +++ b/src/comms/USB/FX3/FX3.cpp @@ -260,7 +260,8 @@ void FX3::AddOnHotplugDisconnectCallback(const IUSB::HotplugDisconnectCallbackTy #ifdef __unix__ libusb_impl.AddOnHotplugDisconnectCallback(function, userData); #else - // TODO: IMPLEMENT + // TODO: figure out how to pass something to CCyUSBDevice constructor's first parameter + // that would be able to collect the Windows Plug and Play events that the library would send #endif } From 450b74e99ebf8fc805ec8cc50bf5136d5e879f49 Mon Sep 17 00:00:00 2001 From: Dominykas Date: Wed, 12 Jun 2024 09:56:08 +0300 Subject: [PATCH 09/11] Don't remove the callback event in fftviewer if it did not actually assign it --- GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp b/GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp index e9cc2589f..9068938f9 100644 --- a/GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp +++ b/GUI/fftviewer_wxgui/fftviewer_frFFTviewer.cpp @@ -15,6 +15,7 @@ #include "limesuiteng/StreamConfig.h" #include "limesuiteng/complex.h" #include +#include using namespace std; using namespace lime; @@ -463,7 +464,7 @@ void fftviewer_frFFTviewer::StreamingLoop( const lime::complex32f_t* src[2] = { txPattern[0].data(), txPattern[1].data() };*/ - std::size_t callbackId = 0; + std::optional callbackId{ std::nullopt }; try { pthis->device->StreamSetup(config, chipIndex); @@ -653,7 +654,10 @@ void fftviewer_frFFTviewer::StreamingLoop( }*/ kiss_fft_free(m_fftCalcPlan); - pthis->device->RemoveHotplugDisconnectCallback(callbackId); + if (callbackId) + { + pthis->device->RemoveHotplugDisconnectCallback(callbackId.value()); + } pthis->stopProcessing.store(true); pthis->device->StreamStop(chipIndex); From fc432356f0f00abfe41f4e5d2981d024ff0580bb Mon Sep 17 00:00:00 2001 From: Dominykas Date: Wed, 12 Jun 2024 10:26:14 +0300 Subject: [PATCH 10/11] Add stopping callbacks to examples and `limeTRX` --- src/cli/limeTRX.cpp | 2 ++ src/comms/USB/USBGeneric.cpp | 5 ++++ src/examples/basicRX.cpp | 2 +- src/examples/basicTX.cpp | 2 +- src/examples/dualRXTX.cpp | 2 +- src/protocols/TRXLooper.cpp | 46 +++++++++++++++++++++--------------- 6 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/cli/limeTRX.cpp b/src/cli/limeTRX.cpp index 980b71dfa..d8e743c38 100644 --- a/src/cli/limeTRX.cpp +++ b/src/cli/limeTRX.cpp @@ -467,6 +467,8 @@ int main(int argc, char** argv) else device->StreamStart(chipIndex); + device->AddHotplugDisconnectCallback([](void* data) { *reinterpret_cast(data) = true; }, &stopProgram); + auto startTime = std::chrono::high_resolution_clock::now(); auto t1 = startTime - std::chrono::seconds(2); // rewind t1 to do update on first loop auto t2 = t1; diff --git a/src/comms/USB/USBGeneric.cpp b/src/comms/USB/USBGeneric.cpp index 1fdb8e7ee..4bb2898e7 100644 --- a/src/comms/USB/USBGeneric.cpp +++ b/src/comms/USB/USBGeneric.cpp @@ -366,6 +366,11 @@ OpStatus USBGeneric::BeginDataXfer(void* context, uint8_t* buffer, size_t length libusb_fill_bulk_transfer(tr, dev_handle, endPointAddr, buffer, length, process_libusbtransfer, xfer, 0); xfer->done.store(false); xfer->bytesXfered = 0; + if (tr->dev_handle == nullptr) + { + return OpStatus::Error; + } + int status = libusb_submit_transfer(tr); if (status != 0) { diff --git a/src/examples/basicRX.cpp b/src/examples/basicRX.cpp index f55f6decb..e97188228 100644 --- a/src/examples/basicRX.cpp +++ b/src/examples/basicRX.cpp @@ -97,7 +97,7 @@ int main(int argc, char** argv) device->StreamSetup(stream, chipIndex); device->StreamStart(chipIndex); - + device->AddHotplugDisconnectCallback([](void* data) { *reinterpret_cast(data) = true; }, &stopProgram); } catch (std::runtime_error& e) { std::cout << "Failed to configure settings: "sv << e.what() << std::endl; diff --git a/src/examples/basicTX.cpp b/src/examples/basicTX.cpp index 213776bd1..a96a1ecdb 100644 --- a/src/examples/basicTX.cpp +++ b/src/examples/basicTX.cpp @@ -90,7 +90,7 @@ int main(int argc, char** argv) device->StreamSetup(stream, chipIndex); device->StreamStart(chipIndex); - + device->AddHotplugDisconnectCallback([](void* data) { *reinterpret_cast(data) = true; }, &stopProgram); } catch (std::runtime_error& e) { std::cout << "Failed to configure settings: "sv << e.what() << std::endl; diff --git a/src/examples/dualRXTX.cpp b/src/examples/dualRXTX.cpp index 71efe7f7e..b6517e8c7 100644 --- a/src/examples/dualRXTX.cpp +++ b/src/examples/dualRXTX.cpp @@ -110,7 +110,7 @@ int main(int argc, char** argv) device->StreamSetup(stream, chipIndex); device->StreamStart(chipIndex); - + device->AddHotplugDisconnectCallback([](void* data) { *reinterpret_cast(data) = true; }, &stopProgram); } catch (std::runtime_error& e) { std::cout << "Failed to configure settings: "sv << e.what() << std::endl; diff --git a/src/protocols/TRXLooper.cpp b/src/protocols/TRXLooper.cpp index 457d5acf2..c1a574df2 100644 --- a/src/protocols/TRXLooper.cpp +++ b/src/protocols/TRXLooper.cpp @@ -257,28 +257,36 @@ void TRXLooper::Stop() { lime::error("Failed to join TRXLooper threads"s); } - fpga->StopStreaming(); - uint32_t fpgaTxPktIngressCount; - uint32_t fpgaTxPktDropCounter; - fpga->ReadTxPacketCounters(chipId, &fpgaTxPktIngressCount, &fpgaTxPktDropCounter); - if (mCallback_logMessage) + mStreamEnabled = false; + + try { - char msg[512]; - std::snprintf(msg, - sizeof(msg), - "Tx%i stop: host sent packets: %li (0x%08lX), FPGA packet ingresed: %i (0x%08X), diff: %li, Tx packet dropped: %i", - chipId, - mTx.stats.packets, - mTx.stats.packets, - fpgaTxPktIngressCount, - fpgaTxPktIngressCount, - (mTx.stats.packets & 0xFFFFFFFF) - fpgaTxPktIngressCount, - fpgaTxPktDropCounter); - mCallback_logMessage(LogLevel::Debug, msg); - } + fpga->StopStreaming(); - mStreamEnabled = false; + uint32_t fpgaTxPktIngressCount; + uint32_t fpgaTxPktDropCounter; + fpga->ReadTxPacketCounters(chipId, &fpgaTxPktIngressCount, &fpgaTxPktDropCounter); + if (mCallback_logMessage) + { + char msg[512]; + std::snprintf(msg, + sizeof(msg), + "Tx%i stop: host sent packets: %li (0x%08lX), FPGA packet ingresed: %i (0x%08X), diff: %li, Tx packet dropped: %i", + chipId, + mTx.stats.packets, + mTx.stats.packets, + fpgaTxPktIngressCount, + fpgaTxPktIngressCount, + (mTx.stats.packets & 0xFFFFFFFF) - fpgaTxPktIngressCount, + fpgaTxPktDropCounter); + mCallback_logMessage(LogLevel::Debug, msg); + } + } + catch (const std::exception& e) + { + lime::error("%s", e.what()); + } } void TRXLooper::Teardown() From 6b6598ee6a2733751e637264f2b8586f38286739 Mon Sep 17 00:00:00 2001 From: Dominykas Date: Wed, 12 Jun 2024 10:58:20 +0300 Subject: [PATCH 11/11] clang-format --- src/protocols/TRXLooper.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/protocols/TRXLooper.cpp b/src/protocols/TRXLooper.cpp index c1a574df2..78dffa900 100644 --- a/src/protocols/TRXLooper.cpp +++ b/src/protocols/TRXLooper.cpp @@ -282,8 +282,7 @@ void TRXLooper::Stop() fpgaTxPktDropCounter); mCallback_logMessage(LogLevel::Debug, msg); } - } - catch (const std::exception& e) + } catch (const std::exception& e) { lime::error("%s", e.what()); }