diff --git a/interfaces/iusbdevice.h b/interfaces/iusbdevice.h index 9e904b1..b07be63 100644 --- a/interfaces/iusbdevice.h +++ b/interfaces/iusbdevice.h @@ -2,7 +2,6 @@ #define IUSBDEVICE_H #include -#include #include namespace noolitelib @@ -17,7 +16,7 @@ public: virtual void openDevice(uint16_t vendorId, uint16_t productId) = 0; virtual void close() = 0; - virtual bool sendDataToDevice(const Data &data, std::chrono::milliseconds timeout) = 0; + virtual bool sendDataToDevice(const Data &data) = 0; }; } diff --git a/src/libusbdevice.cpp b/src/libusbdevice.cpp index bf978f1..4ffcc2d 100644 --- a/src/libusbdevice.cpp +++ b/src/libusbdevice.cpp @@ -6,11 +6,13 @@ namespace noolitelib { +constexpr auto DefaultTimeout = 1000; + LibUsbDevice::LibUsbDevice() { auto status = libusb_init(&m_context); if (status) { - std::cout << "Error initializing context: " << libusb_strerror(status) << std::endl; + std::cerr << "Error initializing context: " << libusb_strerror(status) << std::endl; } } @@ -33,10 +35,10 @@ void LibUsbDevice::close() } } -bool LibUsbDevice::sendDataToDevice(const Data &data, std::chrono::milliseconds timeout) +bool LibUsbDevice::sendDataToDevice(const Data &data) { if (!m_device) { - std::cout << "Device not opened" << std::endl; + std::cerr << "Device not opened" << std::endl; } auto requestType = LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE; @@ -45,10 +47,10 @@ bool LibUsbDevice::sendDataToDevice(const Data &data, std::chrono::milliseconds unsigned char package[data.size()]; std::copy(data.begin(), data.end(), package); - auto status = libusb_control_transfer(m_device, requestType, request, 0, 0, package, data.size(), timeout.count()); + auto status = libusb_control_transfer(m_device, requestType, request, 0, 0, package, data.size(), DefaultTimeout); if (status) { - std::cout << "Sending data error: " << libusb_strerror(status) << std::endl; + std::cerr << "Sending data error: " << libusb_strerror(status) << std::endl; return false; } diff --git a/src/libusbdevice.h b/src/libusbdevice.h index aebbd60..f02eed0 100644 --- a/src/libusbdevice.h +++ b/src/libusbdevice.h @@ -17,7 +17,7 @@ public: void openDevice(uint16_t vendorId, uint16_t productId) override; void close() override; - bool sendDataToDevice(const Data &data, std::chrono::milliseconds timeout = std::chrono::seconds(1)) override; + bool sendDataToDevice(const Data &data) override; private: libusb_context *m_context = nullptr; diff --git a/src/noolite.cpp b/src/noolite.cpp index 193c52d..5be55d6 100644 --- a/src/noolite.cpp +++ b/src/noolite.cpp @@ -13,6 +13,17 @@ constexpr auto PID = 0x05df; } +namespace +{ + +constexpr char WorkMode = 0; +constexpr char Bitrate = 2; +constexpr char Repeats = 2; + +constexpr auto Mode = (Repeats << 5 | Bitrate << 3 | WorkMode); + +} + Noolite::Noolite(IUsbDevice *device) : m_device(device ? device : new LibUsbDevice()) { @@ -25,14 +36,32 @@ Noolite::~Noolite() delete m_device; } -bool Noolite::sendCommand(int channel, Command command, Params params) +bool Noolite::sendCommand(unsigned char channel, Command command, const Params ¶ms) { - (void) channel; - (void) command; - (void) params; + auto data = composeCommand(channel, command, params); + + if (data) { + return m_device->sendDataToDevice(data.value()); + } return false; } +std::optional Noolite::composeCommand(unsigned char channel, Command command, const Params ¶ms) const +{ + if (noolitelib::Set == command && !(params.size() == 1 || params.size() == 3)) { + return {}; + } + + unsigned char format = (noolitelib::Set == command) ? params.size() : (command > noolitelib::Bind ? 0x04: 0x00); + + Data res { Mode, static_cast(command), format, 0x0, channel, 0x0, 0x0, 0x0 }; + for (int i = 0; i < params.size(); ++i) { + res[5 + i] = params[i]; + } + + return res; +} + } diff --git a/src/noolite.h b/src/noolite.h index f7ca23f..6a517fa 100644 --- a/src/noolite.h +++ b/src/noolite.h @@ -2,6 +2,7 @@ #define NOOLITE_H #include +#include #include "interfaces/iusbdevice.h" @@ -37,10 +38,12 @@ public: Noolite(IUsbDevice *device = nullptr); ~Noolite(); - bool sendCommand(int channel, Command command, Params params = Params()); + bool sendCommand(unsigned char channel, Command command, const Params ¶ms = Params()); private: IUsbDevice *m_device; + + std::optional composeCommand(unsigned char channel, Command command, const Params ¶ms) const; }; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 085a2db..5a8a4e6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -4,7 +4,7 @@ project(adapter LANGUAGES CXX) enable_testing() -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) include(FetchContent) diff --git a/tests/mocks/usbdevicemock.h b/tests/mocks/usbdevicemock.h index a55dfd6..da6e13d 100644 --- a/tests/mocks/usbdevicemock.h +++ b/tests/mocks/usbdevicemock.h @@ -10,7 +10,7 @@ class UsbDeviceMock : public noolitelib::IUsbDevice public: MOCK_METHOD(void, openDevice, (uint16_t, uint16_t), (override)); MOCK_METHOD(void, close, (), (override)); - MOCK_METHOD(bool, sendDataToDevice, (const noolitelib::Data &data, std::chrono::milliseconds), (override)); + MOCK_METHOD(bool, sendDataToDevice, (const noolitelib::Data &data), (override)); }; #endif // USBDEVICEMOCK_H diff --git a/tests/tst_adapter.cpp b/tests/tst_adapter.cpp index 42b96a2..89fe8e1 100644 --- a/tests/tst_adapter.cpp +++ b/tests/tst_adapter.cpp @@ -25,8 +25,8 @@ TEST(noolite, sendCommand_Off) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x0, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x0, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::Off)); @@ -38,8 +38,8 @@ TEST(noolite, sendCommand_DecreaseBrightnes) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x01, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x01, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::DecraseBrightnes)); @@ -51,8 +51,8 @@ TEST(noolite, sendCommand_On) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x02, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x02, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::On)); @@ -64,8 +64,8 @@ TEST(noolite, sendCommand_IncreaseBrightnes) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x03, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x03, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::IncreaseBrightnes)); @@ -77,8 +77,8 @@ TEST(noolite, sendCommand_Switch) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x04, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x04, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::Switch)); @@ -90,8 +90,8 @@ TEST(noolite, sendCommand_InvertBrightnes) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x05, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x05, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::InvertBrightnes)); @@ -103,8 +103,8 @@ TEST(noolite, sendCommand_Set_OneChannel) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x06, 0x01, 0x0, 3, 0x2A, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x06, 0x01, 0x0, 3, 0x2A, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::Set, noolitelib::Params{ 42 })); @@ -116,8 +116,8 @@ TEST(noolite, sendCommand_Set_ThreeChannels) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x06, 0x03, 0x0, 3, 0x28, 0x29, 0x2A }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x06, 0x03, 0x0, 3, 0x28, 0x29, 0x2A }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::Set, noolitelib::Params{ 40, 41, 42 })); @@ -129,7 +129,7 @@ TEST(noolite, sendCommand_Set_BadArguments) noolitelib::Noolite adapter(usbDevice); - EXPECT_CALL(*usbDevice, sendDataToDevice(_, _)). + EXPECT_CALL(*usbDevice, sendDataToDevice(_)). Times(0); EXPECT_FALSE(adapter.sendCommand(3, noolitelib::Set)); @@ -143,8 +143,8 @@ TEST(noolite, sendCommand_CallScenario) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x07, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x07, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::CallScenario)); @@ -156,8 +156,8 @@ TEST(noolite, sendCommand_SaveScenario) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x08, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x08, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::SaveScenario)); @@ -169,8 +169,8 @@ TEST(noolite, sendCommand_Unbind) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x09, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x09, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::Unbind)); @@ -182,8 +182,8 @@ TEST(noolite, sendCommand_StopColorSelection) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x0A, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x0A, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::StopColorSelection)); @@ -195,8 +195,8 @@ TEST(noolite, sendCommand_Bind) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x0B, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x0F, 0x0, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::Bind)); @@ -208,8 +208,8 @@ TEST(noolite, sendCommand_ColorSelection) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x0C, 0x04, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x10, 0x04, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::ColorSelection)); @@ -221,8 +221,8 @@ TEST(noolite, sendCommand_ColorSwitch) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x0D, 0x04, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x11, 0x04, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::ColorSwitch)); @@ -234,8 +234,8 @@ TEST(noolite, sendCommand_ModeSwitch) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x0E, 0x04, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x12, 0x04, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::ModeSwitch)); @@ -247,8 +247,8 @@ TEST(noolite, sendCommand_EffectSpeed) noolitelib::Noolite adapter(usbDevice); - noolitelib::Data expectedData{ 0x30, 0x0F, 0x04, 0x0, 3, 0x0, 0x0, 0x0 }; - EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData, std::chrono::milliseconds())). + noolitelib::Data expectedData{ 0x50, 0x13, 0x04, 0x0, 3, 0x0, 0x0, 0x0 }; + EXPECT_CALL(*usbDevice, sendDataToDevice(expectedData)). WillOnce(Return(true)); EXPECT_TRUE(adapter.sendCommand(3, noolitelib::EffectSpeed));