From a7f3d536abe06f10635dae541eb0b2f4fce52cca Mon Sep 17 00:00:00 2001 From: morg Date: Sat, 3 Jun 2023 19:08:18 +0000 Subject: [PATCH] Add support for Lego Dimensions Toypad Base. Closes #3399 --- .../LegoDimensionsToypadBaseController.cpp | 148 ++++++++++++++++++ .../LegoDimensionsToypadBaseController.h | 54 +++++++ ...goDimensionsToypadBaseControllerDetect.cpp | 29 ++++ ...RGBController_LegoDimensionsToypadBase.cpp | 134 ++++++++++++++++ .../RGBController_LegoDimensionsToypadBase.h | 32 ++++ OpenRGB.pro | 6 + 6 files changed, 403 insertions(+) create mode 100644 Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.cpp create mode 100644 Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.h create mode 100644 Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseControllerDetect.cpp create mode 100644 Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.cpp create mode 100644 Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.h diff --git a/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.cpp b/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.cpp new file mode 100644 index 00000000..5f4f345f --- /dev/null +++ b/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.cpp @@ -0,0 +1,148 @@ +/*-----------------------------------------*\ +| LegoDimensionsToypadBaseController.h | +| | +| Driver for Lego Dimensions ToypadBase | +| controller | +| | +| Guimard Morgan (morg) 06/02/2023 | +\*-----------------------------------------*/ +#include "LegoDimensionsToypadBaseController.h" +#include + +LegoDimensionsToypadBaseController::LegoDimensionsToypadBaseController(hid_device* dev_handle, const hid_device_info& info) +{ + dev = dev_handle; + location = info.path; + version = ""; + + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + serial_number = ""; + } + else + { + std::wstring return_wstring = serial_string; + serial_number = std::string(return_wstring.begin(), return_wstring.end()); + } + + Activate(); +} + +LegoDimensionsToypadBaseController::~LegoDimensionsToypadBaseController() +{ + hid_close(dev); +} + +std::string LegoDimensionsToypadBaseController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string LegoDimensionsToypadBaseController::GetSerialString() +{ + return(serial_number); +} + +std::string LegoDimensionsToypadBaseController::GetFirmwareVersion() +{ + return(version); +} + +void LegoDimensionsToypadBaseController::Activate() +{ + unsigned char usb_buf[LEGO_DIMENSIONS_TOYPAD_BASE_PACKET_LENGTH]; + + memset(usb_buf, 0x00, LEGO_DIMENSIONS_TOYPAD_BASE_PACKET_LENGTH); + + usb_buf[1] = LEGO_DIMENSIONS_TOYPAD_BASE_REPORT_ID; + usb_buf[2] = 0x0F; // command length + usb_buf[3] = LEGO_DIMENSIONS_TOYPAD_BASE_ACTIVATE_VALUE; + usb_buf[4] = 0x01; + usb_buf[5] = 0x28; //'(' + usb_buf[6] = 0x63; //'c' + usb_buf[7] = 0x29; //')' + usb_buf[8] = 0x20; //' ' + usb_buf[9] = 0x4C; //'L' + usb_buf[10] = 0x45; //'E' + usb_buf[11] = 0x47; //'G' + usb_buf[12] = 0x4F; //'O' + usb_buf[13] = 0x20; //' ' + usb_buf[14] = 0x32; //'2' + usb_buf[15] = 0x30; //'0' + usb_buf[16] = 0x31; //'1' + usb_buf[17] = 0x34; //'4' + usb_buf[18] = 0xF7; // checksum + + hid_write(dev, usb_buf, LEGO_DIMENSIONS_TOYPAD_BASE_PACKET_LENGTH); +} + +void LegoDimensionsToypadBaseController::SetDirect(unsigned char zone, RGBColor color) +{ + unsigned char usb_buf[LEGO_DIMENSIONS_TOYPAD_BASE_PACKET_LENGTH]; + + memset(usb_buf, 0x00, LEGO_DIMENSIONS_TOYPAD_BASE_PACKET_LENGTH); + + usb_buf[1] = LEGO_DIMENSIONS_TOYPAD_BASE_REPORT_ID; + usb_buf[2] = 0x06; // command length + usb_buf[3] = LEGO_DIMENSIONS_TOYPAD_BASE_DIRECT_MODE_VALUE; + usb_buf[4] = 0x02; // constant value + usb_buf[5] = zone; + usb_buf[6] = RGBGetRValue(color); + usb_buf[7] = RGBGetGValue(color); + usb_buf[8] = RGBGetBValue(color); + + for(unsigned int i = 1; i < 9; i ++) + { + usb_buf[9] += usb_buf[i]; // checksum + } + + hid_write(dev, usb_buf, LEGO_DIMENSIONS_TOYPAD_BASE_PACKET_LENGTH); +} + +void LegoDimensionsToypadBaseController::SetMode(unsigned char zone, unsigned char mode_value, uint8_t speed, RGBColor color) +{ + unsigned char usb_buf[LEGO_DIMENSIONS_TOYPAD_BASE_PACKET_LENGTH]; + + memset(usb_buf, 0x00, LEGO_DIMENSIONS_TOYPAD_BASE_PACKET_LENGTH); + + usb_buf[1] = LEGO_DIMENSIONS_TOYPAD_BASE_REPORT_ID; + usb_buf[3] = mode_value; + usb_buf[5] = zone; + + if(mode_value == LEGO_DIMENSIONS_TOYPAD_BASE_FLASH_MODE_VALUE) + { + usb_buf[2] = 0x09; // command length + usb_buf[4] = 0x1F; // constant value + usb_buf[6] = speed; // light on length + usb_buf[7] = speed; // light off length + usb_buf[8] = 10; // number of pulses + usb_buf[9] = RGBGetRValue(color); + usb_buf[10] = RGBGetGValue(color); + usb_buf[11] = RGBGetBValue(color); + + for(unsigned int i = 1; i < 12; i ++) + { + usb_buf[12] += usb_buf[i]; // checksum + } + } + else if (mode_value == LEGO_DIMENSIONS_TOYPAD_BASE_FADE_MODE_VALUE) + { + usb_buf[2] = 0x08; // command length + usb_buf[4] = 0x0F; // constant value + usb_buf[6] = speed; // light on length + usb_buf[7] = 10; // number of pulses + usb_buf[8] = RGBGetRValue(color); + usb_buf[9] = RGBGetGValue(color); + usb_buf[10] = RGBGetBValue(color); + + for(unsigned int i = 1; i < 11; i ++) + { + usb_buf[11] += usb_buf[i]; // checksum + } + } + + hid_write(dev, usb_buf, LEGO_DIMENSIONS_TOYPAD_BASE_PACKET_LENGTH); +} diff --git a/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.h b/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.h new file mode 100644 index 00000000..26e0545c --- /dev/null +++ b/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.h @@ -0,0 +1,54 @@ +/*-----------------------------------------*\ +| LegoDimensionsToypadBaseController.h | +| | +| Driver for Lego Dimensions ToypadBase | +| controller - header file | +| | +| Guimard Morgan (morg) 06/02/2023 | +\*-----------------------------------------*/ +#pragma once + +#include "RGBController.h" +#include +#include + +#define LEGO_DIMENSIONS_TOYPAD_BASE_REPORT_ID 0x55 +#define LEGO_DIMENSIONS_TOYPAD_BASE_PACKET_LENGTH 32 + +enum +{ + LEGO_DIMENSIONS_TOYPAD_BASE_ACTIVATE_VALUE = 0xB0, + LEGO_DIMENSIONS_TOYPAD_BASE_DIRECT_MODE_VALUE = 0xC0, + LEGO_DIMENSIONS_TOYPAD_BASE_FLASH_MODE_VALUE = 0xC3, + LEGO_DIMENSIONS_TOYPAD_BASE_FADE_MODE_VALUE = 0xC2 +}; + +enum +{ + LEGO_DIMENSIONS_TOYPAD_BASE_SPEED_MIN = 0x00, + LEGO_DIMENSIONS_TOYPAD_BASE_SPEED_MAX = 0xFF +}; + +class LegoDimensionsToypadBaseController +{ +public: + LegoDimensionsToypadBaseController(hid_device* dev_handle, const hid_device_info& info); + ~LegoDimensionsToypadBaseController(); + + std::string GetSerialString(); + std::string GetDeviceLocation(); + std::string GetFirmwareVersion(); + + void SetDirect(unsigned char zone, RGBColor color); + void SetMode(unsigned char zone, unsigned char mode_value, uint8_t speed, RGBColor color); + +protected: + hid_device* dev; + +private: + std::string location; + std::string serial_number; + std::string version; + + void Activate(); +}; diff --git a/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseControllerDetect.cpp b/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseControllerDetect.cpp new file mode 100644 index 00000000..3a4b30cd --- /dev/null +++ b/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseControllerDetect.cpp @@ -0,0 +1,29 @@ +#include "Detector.h" +#include "LegoDimensionsToypadBaseController.h" +#include "RGBController.h" +#include "RGBController_LegoDimensionsToypadBase.h" + +/*---------------------------------------------------------*\ +| Logic3 vendor ID | +\*---------------------------------------------------------*/ +#define LOGIC_3_VID 0x0E6F + +/*---------------------------------------------------------*\ +| Lego Dimensions Toypad Base product ID | +\*---------------------------------------------------------*/ +#define LEGO_DIMENSIONS_TOYPAD_BASE_PID 0x0241 + +void DetectLegoDimensionsToypadBaseControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + LegoDimensionsToypadBaseController* controller = new LegoDimensionsToypadBaseController(dev, *info); + RGBController_LegoDimensionsToypadBase* rgb_controller = new RGBController_LegoDimensionsToypadBase(controller); + rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR("Lego Dimensions Toypad Base", DetectLegoDimensionsToypadBaseControllers, LOGIC_3_VID, LEGO_DIMENSIONS_TOYPAD_BASE_PID); diff --git a/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.cpp b/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.cpp new file mode 100644 index 00000000..d6ad048e --- /dev/null +++ b/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.cpp @@ -0,0 +1,134 @@ +/*-----------------------------------------*\ +| RGBController_LegoDimensionsToypadBase.h | +| | +| Generic RGB Interface for OpenRGB | +| Lego Dimensions Toypad Base USB Driver | +| | +| Guimard Morgan (morg) 06/02/2023 | +\*-----------------------------------------*/ + +#include "RGBController_LegoDimensionsToypadBase.h" + +#include +#include + +/**------------------------------------------------------------------*\ + @name Lego Dimensions Toypad Base + @category Case + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectLegoDimensionsToypadBaseControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_LegoDimensionsToypadBase::RGBController_LegoDimensionsToypadBase(LegoDimensionsToypadBaseController* controller_ptr) +{ + controller = controller_ptr; + vendor = "Logic3"; + type = DEVICE_TYPE_LEDSTRIP; + description = "Lego Dimensions Toypad Base"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + version = controller->GetFirmwareVersion(); + + mode Direct; + Direct.name = "Direct"; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Flash; + Flash.name = "Flash"; + Flash.value = LEGO_DIMENSIONS_TOYPAD_BASE_FLASH_MODE_VALUE; + Flash.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; + Flash.color_mode = MODE_COLORS_MODE_SPECIFIC; + Flash.colors.resize(1); + Flash.colors_max = 1; + Flash.colors_min = 1; + Flash.speed = LEGO_DIMENSIONS_TOYPAD_BASE_SPEED_MAX / 2; + Flash.speed_max = LEGO_DIMENSIONS_TOYPAD_BASE_SPEED_MAX; + Flash.speed_min = LEGO_DIMENSIONS_TOYPAD_BASE_SPEED_MIN; + modes.push_back(Flash); + + mode Fade; + Fade.name = "Fade"; + Fade.value = LEGO_DIMENSIONS_TOYPAD_BASE_FADE_MODE_VALUE; + Fade.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; + Fade.color_mode = MODE_COLORS_MODE_SPECIFIC; + Fade.colors.resize(1); + Fade.colors_max = 1; + Fade.colors_min = 1; + Fade.speed = LEGO_DIMENSIONS_TOYPAD_BASE_SPEED_MAX / 2; + Fade.speed_max = LEGO_DIMENSIONS_TOYPAD_BASE_SPEED_MAX; + Fade.speed_min = LEGO_DIMENSIONS_TOYPAD_BASE_SPEED_MIN; + modes.push_back(Fade); + + SetupZones(); +} + +RGBController_LegoDimensionsToypadBase::~RGBController_LegoDimensionsToypadBase() +{ + delete controller; +} + +void RGBController_LegoDimensionsToypadBase::SetupZones() +{ + std::vector zone_names = + { + "Center", + "Left", + "Right" + }; + + for(const std::string& zone_name: zone_names) + { + zone new_zone; + + new_zone.name = zone_name; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = 1; + new_zone.leds_max = 1; + new_zone.leds_count = 1; + new_zone.matrix_map = nullptr; + + zones.emplace_back(new_zone); + + led new_led; + new_led.name = "LED"; + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_LegoDimensionsToypadBase::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_LegoDimensionsToypadBase::DeviceUpdateLEDs() +{ + for(unsigned int zone = 0; zone < zones.size(); zone++) + { + UpdateZoneLEDs(zone); + } +} + +void RGBController_LegoDimensionsToypadBase::UpdateZoneLEDs(int zone) +{ + controller->SetDirect(zone + 1, zones[zone].colors[0]); +} + +void RGBController_LegoDimensionsToypadBase::UpdateSingleLED(int /*led*/) +{ + UpdateZoneLEDs(0); +} + +void RGBController_LegoDimensionsToypadBase::DeviceUpdateMode() +{ + controller->SetMode(0, modes[active_mode].value, modes[active_mode].speed, modes[active_mode].colors[0]); +} diff --git a/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.h b/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.h new file mode 100644 index 00000000..490a6f9f --- /dev/null +++ b/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.h @@ -0,0 +1,32 @@ +/*-----------------------------------------*\ +| RGBController_LegoDimensionsToypadBase.h | +| | +| Generic RGB Interface for OpenRGB | +| Lego Dimensions Toypad Base USB Driver | +| | +| Guimard Morgan (morg) 06/02/2023 | +\*-----------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LegoDimensionsToypadBaseController.h" + +class RGBController_LegoDimensionsToypadBase : public RGBController +{ +public: + RGBController_LegoDimensionsToypadBase(LegoDimensionsToypadBaseController* controller_ptr); + ~RGBController_LegoDimensionsToypadBase(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LegoDimensionsToypadBaseController* controller; +}; diff --git a/OpenRGB.pro b/OpenRGB.pro index 7c9613c7..a865d16c 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -145,6 +145,7 @@ INCLUDEPATH += Controllers/IntelArcA770LEController/ \ Controllers/IonicoController/ \ Controllers/LEDStripController/ \ + Controllers/LegoDimensionsToypadBaseController/ \ Controllers/LenovoControllers/ \ Controllers/LenovoMotherboardController/ \ Controllers/LianLiController/ \ @@ -504,6 +505,8 @@ HEADERS += Controllers/KeychronKeyboardController/RGBController_KeychronKeyboard.h \ Controllers/LEDStripController/LEDStripController.h \ Controllers/LEDStripController/RGBController_LEDStrip.h \ + Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.h \ + Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.h \ Controllers/LenovoControllers/LenovoDevices.h \ Controllers/LenovoControllers/LenovoDevices4Zone.h \ Controllers/LenovoControllers/LenovoUSBController.h \ @@ -1140,6 +1143,9 @@ SOURCES += Controllers/LEDStripController/LEDStripController.cpp \ Controllers/LEDStripController/LEDStripControllerDetect.cpp \ Controllers/LEDStripController/RGBController_LEDStrip.cpp \ + Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.cpp \ + Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseControllerDetect.cpp \ + Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.cpp \ Controllers/LenovoControllers/LenovoUSBController.cpp \ Controllers/LenovoControllers/Lenovo4ZoneUSBController.cpp \ Controllers/LenovoControllers/LenovoUSBDetect.cpp \