diff --git a/Controllers/LogitechController/LogitechControllerDetect.cpp b/Controllers/LogitechController/LogitechControllerDetect.cpp index c0c50706c..492177489 100644 --- a/Controllers/LogitechController/LogitechControllerDetect.cpp +++ b/Controllers/LogitechController/LogitechControllerDetect.cpp @@ -7,6 +7,7 @@ #include "LogitechG213Controller.h" #include "LogitechGProWirelessController.h" #include "LogitechGPowerPlayController.h" +#include "LogitechG560Controller.h" #include "RGBController.h" #include "RGBController_LogitechG203.h" #include "RGBController_LogitechG203L.h" @@ -16,6 +17,7 @@ #include "RGBController_LogitechG213.h" #include "RGBController_LogitechGProWireless.h" #include "RGBController_LogitechGPowerPlay.h" +#include "RGBController_LogitechG560.h" #include #include @@ -50,6 +52,10 @@ | Mousemat product IDs | \*-----------------------------------------------------*/ #define LOGITECH_G_LIGHTSPEED_POWERPLAY_PID 0xC53A +/*-----------------------------------------------------*\ +| Speaker product IDs | +\*-----------------------------------------------------*/ +#define LOGITECH_G560_PID 0x0A78 void DetectLogitechKeyboardG810(hid_device_info* info, const std::string& name) { @@ -199,6 +205,19 @@ void DetectLogitechMouseGLS(hid_device_info* info, const std::string& name) } } +void DetectLogitechG560(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + if(dev) + { + //Add G560 Speaker + LogitechG560Controller* speaker_controller = new LogitechG560Controller(dev, info->path); + RGBController_LogitechG560* speaker_rgb_controller = new RGBController_LogitechG560(speaker_controller); + speaker_rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(speaker_rgb_controller); + } +} + /*-------------------------------------------------------------------------------------------------------------------------------------------------*\ | Keyboards | \*-------------------------------------------------------------------------------------------------------------------------------------------------*/ @@ -226,3 +245,7 @@ REGISTER_HID_DETECTOR_IPU("Logitech G Pro Wireless Gaming Mouse (Wired)", Detec | Mousemats | \*-------------------------------------------------------------------------------------------------------------------------------------------------*/ REGISTER_HID_DETECTOR_IPU("Logitech G Powerplay Mousepad with Lightspeed", DetectLogitechMouseGLS, LOGITECH_VID, LOGITECH_G_LIGHTSPEED_POWERPLAY_PID, 2, 0xFF00, 2); +/*-------------------------------------------------------------------------------------------------------------------------------------------------*\ +| Speakers | +\*-------------------------------------------------------------------------------------------------------------------------------------------------*/ +REGISTER_HID_DETECTOR_IPU("Logitech G560 Lightsync Speaker", DetectLogitechG560, LOGITECH_VID, LOGITECH_G560_PID, 2, 0xFF43, 514); diff --git a/Controllers/LogitechController/LogitechG560Controller.cpp b/Controllers/LogitechController/LogitechG560Controller.cpp new file mode 100644 index 000000000..2eb1e6c78 --- /dev/null +++ b/Controllers/LogitechController/LogitechG560Controller.cpp @@ -0,0 +1,147 @@ +/*-----------------------------------------*\ +| LogitechG560Controller.cpp | +| | +| Driver for Logitech G560 RGB Speaker | +| Charging System | +| | +| Cheerpipe 10/28/2020 | +| Based on | +| TheRogueZeta 8/31/2020 | +\*-----------------------------------------*/ + +#include "LogitechG560Controller.h" +#include +#include +#include + +using namespace std::chrono_literals; + +LogitechG560Controller::LogitechG560Controller(hid_device* dev_handle, const char* path) +{ + dev = dev_handle; + location = path; +} + +LogitechG560Controller::~LogitechG560Controller() +{ + hid_close(dev); +} + +std::string LogitechG560Controller::GetDeviceLocation() +{ + return("HID: " + location); +} + +void LogitechG560Controller::SetDirectMode(uint8_t zone) +{ + unsigned char usb_buf[20]; + + usb_buf[0x00] = 0x11; + usb_buf[0x01] = 0xFF; + usb_buf[0x02] = 0x04; + usb_buf[0x03] = 0xCA; + usb_buf[0x04] = zone; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + fail_retry_write(dev, usb_buf, 20); +} + +void LogitechG560Controller::SetOffMode(uint8_t zone) +{ + unsigned char usb_buf[20]; + + usb_buf[0x00] = 0x11; + usb_buf[0x01] = 0xFF; + usb_buf[0x02] = 0x04; + usb_buf[0x03] = 0x3F; + usb_buf[0x04] = zone; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + fail_retry_write(dev, usb_buf, 20); +} + +void LogitechG560Controller::SendSpeakerMode + ( + unsigned char zone, //0x04 + unsigned char mode, //0x05 + unsigned char speed, //0x0B // not working so far + unsigned char red, //0x06 + unsigned char green, //0x07 + unsigned char blue //0x08 + ) +{ + unsigned char usb_buf[20]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Lighting Control | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x11; + usb_buf[0x01] = 0xFF; + usb_buf[0x02] = 0x04; + + /*-----------------------------------------------------*\ + | This packet sets speaker into direct mode. This mode | + | is used by Lightsync Ambilight and Music Visualizer | + | realtime effect. | + \*-----------------------------------------------------*/ + usb_buf[0x03] = 0x3A; + + /*-----------------------------------------------------*\ + | Set up mode and speed | + \*-----------------------------------------------------*/ + usb_buf[0x04] = zone; + usb_buf[0x05] = mode; + + /*-----------------------------------------------------*\ + | And set up the colors | + \*-----------------------------------------------------*/ + usb_buf[0x06] = red; + usb_buf[0x07] = green; + usb_buf[0x08] = blue; + + if(mode == LOGITECH_G560_MODE_DIRECT) //G560 only has Direct Mode. + { + usb_buf[0x09] = 0x02; + } + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + fail_retry_write(dev, usb_buf, 20); +} + +void LogitechG560Controller::fail_retry_write(hid_device *device, const unsigned char *data, size_t length) +{ + unsigned char usb_buf_out[33]; + uint8_t write_max_retry=3; + do + { + std::this_thread::sleep_for(1ms); + int ret = hid_write(device, data, length); + + /*-------------------------------------------------------------------------------------*\ + | HID write fails if a change led color and set volume command are sent at | + | the same time because RGB controller and volume control shares the same interface. | + \*-------------------------------------------------------------------------------------*/ + if (ret > 0) + { + std::this_thread::sleep_for(1ms); + hid_read_timeout(dev, usb_buf_out, 33, 100); + break; + } + else + { + write_max_retry--; + } + + }while (write_max_retry > 0); +} diff --git a/Controllers/LogitechController/LogitechG560Controller.h b/Controllers/LogitechController/LogitechG560Controller.h new file mode 100644 index 000000000..2b432d1fa --- /dev/null +++ b/Controllers/LogitechController/LogitechG560Controller.h @@ -0,0 +1,62 @@ +/*-----------------------------------------*\ +| LogitechG560Controller.h | +| | +| Definitions and types for Logitech G560 | +| RGB Speaker | +| | +| Cheerpipe 10/28/2020 | +| Based on | +| TheRogueZeta 8/31/2020 | +\*-----------------------------------------*/ + +#include "RGBController.h" + +#include +#include + +#pragma once + +enum +{ + LOGITECH_G560_MODE_OFF = 0x00, + LOGITECH_G560_MODE_DIRECT = 0x01, + LOGITECH_G560_MODE_CYCLE = 0x02, + LOGITECH_G560_MODE_BREATHING = 0x03, +}; + +/*---------------------------------------------------------------------------------------------*\ +| Speed is 1000 for fast and 20000 for slow. | +| Values are mutipled by 100 later to give lots of GUI steps. | +\*---------------------------------------------------------------------------------------------*/ +enum +{ + LOGITECH_G560_SPEED_SLOWEST = 0xC8, /* Slowest speed */ + LOGITECH_G560_SPEED_NORMAL = 0x32, /* Normal speed */ + LOGITECH_G560_SPEED_FASTEST = 0x0A, /* Fastest speed */ +}; + +class LogitechG560Controller +{ +public: + LogitechG560Controller(hid_device* dev_handle, const char* path); + ~LogitechG560Controller(); + std::string GetDeviceLocation(); + void SetDirectMode(uint8_t zone); + void SetOffMode(uint8_t zone); + void SendSpeakerMode + ( + unsigned char zone, //0x04 + unsigned char mode, //0x05 + unsigned char speed, //0x0B + unsigned char red, //0x06 + unsigned char green, //0x07 + unsigned char blue //0x08 + ); + +private: + hid_device* dev; + std::string location; + void fail_retry_write(hid_device *device, const unsigned char *data, size_t length); +}; + + diff --git a/Controllers/LogitechController/RGBController_LogitechG560.cpp b/Controllers/LogitechController/RGBController_LogitechG560.cpp new file mode 100644 index 000000000..1b3202184 --- /dev/null +++ b/Controllers/LogitechController/RGBController_LogitechG560.cpp @@ -0,0 +1,148 @@ +/*-----------------------------------------*\ +| RGBController_LogitechG560.cpp | +| | +| Generic RGB Interface for | +| Logitech G560 RGB Speaker | +| | +| Cheerpipe 10/28/2020 | +| Based on | +| TheRogueZeta 8/31/2020 | +\*-----------------------------------------*/ + +#include "RGBController_LogitechG560.h" + +RGBController_LogitechG560::RGBController_LogitechG560(LogitechG560Controller* logitech_ptr) +{ + logitech = logitech_ptr; + + name = "Logitech G560 Lightsync Speaker"; + vendor = "Logitech"; + type = DEVICE_TYPE_SPEAKER; + description = "Logitech G560 Lightsync Speaker"; + location = logitech->GetDeviceLocation(); + + mode Off; + Off.name = "Off"; + Off.value = LOGITECH_G560_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Off); + + mode Direct; + Direct.name = "Direct"; + Direct.value = LOGITECH_G560_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + SetupZones(); +} + +void RGBController_LogitechG560::SetupZones() +{ + zone G560_left_front; + G560_left_front.name = "Left Front"; + G560_left_front.type = ZONE_TYPE_SINGLE; + G560_left_front.leds_min = 1; + G560_left_front.leds_max = 1; + G560_left_front.leds_count = 1; + G560_left_front.matrix_map = NULL; + zones.push_back(G560_left_front); + + led G560_left_front_led; + G560_left_front_led.name = "Left Front"; + G560_left_front_led.value = 0x00; + leds.push_back(G560_left_front_led); + + zone G560_right_front; + G560_right_front.name = "Right Front"; + G560_right_front.type = ZONE_TYPE_SINGLE; + G560_right_front.leds_min = 1; + G560_right_front.leds_max = 1; + G560_right_front.leds_count = 1; + G560_right_front.matrix_map = NULL; + zones.push_back(G560_right_front); + + led G560_right_front_led; + G560_right_front_led.name = "Right Front"; + G560_right_front_led.value = 0x01; + leds.push_back(G560_right_front_led); + + + zone G560_left_rear; + G560_left_rear.name = "Left Rear"; + G560_left_rear.type = ZONE_TYPE_SINGLE; + G560_left_rear.leds_min = 1; + G560_left_rear.leds_max = 1; + G560_left_rear.leds_count = 1; + G560_left_rear.matrix_map = NULL; + zones.push_back(G560_left_rear); + + led G560_left_read_led; + G560_left_read_led.name = "Left Rear"; + G560_left_read_led.value = 0x02; + leds.push_back(G560_left_read_led); + + + zone G560_right_rear; + G560_right_rear.name = "Right Rear"; + G560_right_rear.type = ZONE_TYPE_SINGLE; + G560_right_rear.leds_min = 1; + G560_right_rear.leds_max = 1; + G560_right_rear.leds_count = 1; + G560_right_rear.matrix_map = NULL; + zones.push_back(G560_right_rear); + + led G560_right_rear_led; + G560_right_rear_led.name = "Right Rear"; + G560_right_rear_led.value = 0x03; + leds.push_back(G560_right_rear_led); + + SetupColors(); +} + +void RGBController_LogitechG560::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_LogitechG560::DeviceUpdateLEDs() +{ + for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++) + { + unsigned char red = RGBGetRValue(colors[led_idx]); + unsigned char grn = RGBGetGValue(colors[led_idx]); + unsigned char blu = RGBGetBValue(colors[led_idx]); + + if (modes[active_mode].value==LOGITECH_G560_MODE_DIRECT) + { + logitech->SetDirectMode(leds[led_idx].value); //Required to "reset" RGB controller and start receiving color in direct mode + } + else if (modes[active_mode].value==LOGITECH_G560_MODE_OFF) + { + logitech->SetOffMode(leds[led_idx].value); + } + logitech->SendSpeakerMode((unsigned char)leds[led_idx].value, modes[active_mode].value, modes[active_mode].speed,red, grn, blu); + } +} + +void RGBController_LogitechG560::UpdateZoneLEDs(int zone) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LogitechG560::UpdateSingleLED(int led) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LogitechG560::SetCustomMode() +{ + active_mode = 1; +} + +void RGBController_LogitechG560::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/LogitechController/RGBController_LogitechG560.h b/Controllers/LogitechController/RGBController_LogitechG560.h new file mode 100644 index 000000000..caebf2923 --- /dev/null +++ b/Controllers/LogitechController/RGBController_LogitechG560.h @@ -0,0 +1,34 @@ +/*-----------------------------------------*\ +| RGBController_LogitechG560.h | +| | +| Generic RGB Interface for | +| G560 RGB Speaker | +| | +| Cheerpipe 10/28/2020 | +| Based on | +| TheRogueZeta 8/31/2020 | +\*-----------------------------------------*/ + +#pragma once +#include "RGBController.h" +#include "LogitechG560Controller.h" + +class RGBController_LogitechG560 : public RGBController +{ +public: + RGBController_LogitechG560(LogitechG560Controller* logitech_ptr); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void SetCustomMode(); + void DeviceUpdateMode(); + +private: + LogitechG560Controller* logitech; +}; diff --git a/OpenRGB.pro b/OpenRGB.pro index 67042266a..e42413340 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -229,7 +229,7 @@ HEADERS += Controllers/HyperXMouseController/HyperXPulsefireDartController.h \ Controllers/HyperXMouseController/RGBController_HyperXPulsefireFPSPro.h \ Controllers/HyperXMouseController/RGBController_HyperXPulsefireSurge.h \ - Controllers/HyperXMouseController/RGBController_HyperXPulsefireDart.h \ + Controllers/HyperXMouseController/RGBController_HyperXPulsefireDart.h \ Controllers/HyperXMousematController/HyperXMousematController.h \ Controllers/HyperXMousematController/RGBController_HyperXMousemat.h \ Controllers/LEDStripController/LEDStripController.h \ @@ -238,6 +238,7 @@ HEADERS += Controllers/LogitechController/LogitechG203LController.h \ Controllers/LogitechController/LogitechG403Controller.h \ Controllers/LogitechController/LogitechG502PSController.h \ + Controllers/LogitechController/LogitechG560Controller.h \ Controllers/LogitechController/LogitechG810Controller.h \ Controllers/LogitechController/LogitechG213Controller.h \ Controllers/LogitechController/LogitechGPowerPlayController.h \ @@ -246,6 +247,7 @@ HEADERS += Controllers/LogitechController/RGBController_LogitechG203L.h \ Controllers/LogitechController/RGBController_LogitechG403.h \ Controllers/LogitechController/RGBController_LogitechG502PS.h \ + Controllers/LogitechController/RGBController_LogitechG560.h \ Controllers/LogitechController/RGBController_LogitechG810.h \ Controllers/LogitechController/RGBController_LogitechG213.h \ Controllers/LogitechController/RGBController_LogitechGPowerPlay.h \ @@ -473,6 +475,7 @@ SOURCES += Controllers/LogitechController/LogitechG203LController.cpp \ Controllers/LogitechController/LogitechG403Controller.cpp \ Controllers/LogitechController/LogitechG502PSController.cpp \ + Controllers/LogitechController/LogitechG560Controller.cpp \ Controllers/LogitechController/LogitechG810Controller.cpp \ Controllers/LogitechController/LogitechG213Controller.cpp \ Controllers/LogitechController/LogitechGPowerPlayController.cpp \ @@ -481,6 +484,7 @@ SOURCES += Controllers/LogitechController/RGBController_LogitechG203L.cpp \ Controllers/LogitechController/RGBController_LogitechG403.cpp \ Controllers/LogitechController/RGBController_LogitechG502PS.cpp \ + Controllers/LogitechController/RGBController_LogitechG560.cpp \ Controllers/LogitechController/RGBController_LogitechG810.cpp \ Controllers/LogitechController/RGBController_LogitechG213.cpp \ Controllers/LogitechController/RGBController_LogitechGPowerPlay.cpp \ diff --git a/RGBController/RGBController.cpp b/RGBController/RGBController.cpp index 645f07046..9007efc72 100644 --- a/RGBController/RGBController.cpp +++ b/RGBController/RGBController.cpp @@ -1457,6 +1457,8 @@ std::string device_type_to_str(device_type type) return "Gamepad"; case DEVICE_TYPE_LIGHT: return "Light"; + case DEVICE_TYPE_SPEAKER: + return "Speaker"; default: return "Unknown"; } diff --git a/RGBController/RGBController.h b/RGBController/RGBController.h index c8753572b..cd96396e9 100644 --- a/RGBController/RGBController.h +++ b/RGBController/RGBController.h @@ -117,6 +117,7 @@ enum DEVICE_TYPE_HEADSET_STAND, DEVICE_TYPE_GAMEPAD, DEVICE_TYPE_LIGHT, + DEVICE_TYPE_SPEAKER, DEVICE_TYPE_UNKNOWN }; diff --git a/qt/OpenRGBDialog2.cpp b/qt/OpenRGBDialog2.cpp index 856813f50..c5632aee4 100644 --- a/qt/OpenRGBDialog2.cpp +++ b/qt/OpenRGBDialog2.cpp @@ -61,6 +61,9 @@ static QString GetIconString(device_type type, bool dark) case DEVICE_TYPE_LIGHT: filename = "light"; break; + case DEVICE_TYPE_SPEAKER: + filename = "speaker"; + break; default: filename = "unknown"; break; diff --git a/qt/resources.qrc b/qt/resources.qrc index d9702cbff..f832d2d61 100644 --- a/qt/resources.qrc +++ b/qt/resources.qrc @@ -34,5 +34,7 @@ arrow-up.png plugin.png plugin_dark.png + speaker.png + speaker_dark.png diff --git a/qt/speaker.png b/qt/speaker.png new file mode 100644 index 000000000..66e124522 Binary files /dev/null and b/qt/speaker.png differ diff --git a/qt/speaker_dark.png b/qt/speaker_dark.png new file mode 100644 index 000000000..f1a7b8a93 Binary files /dev/null and b/qt/speaker_dark.png differ