/*---------------------------------------------------------*\ | EVGAMouseController.h | | | | Driver for EVGA mouse | | | | Cooper Knaak 23 Jan 2022 | | | | This file is part of the OpenRGB project | | SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #pragma once #include #include #include #include "RGBController.h" #define EVGA_PERIPHERAL_PACKET_SIZE 65 #define EVGA_PERIPHERAL_LED_COUNT 3 #define HID_MAX_STR 255 enum { EVGA_PERIPHERAL_MODE_STATIC = 1, EVGA_PERIPHERAL_MODE_BREATHING = 2, EVGA_PERIPHERAL_MODE_RAINBOW = 3, EVGA_PERIPHERAL_MODE_PULSE = 4, EVGA_PERIPHERAL_MODE_TRIGGER = 6 }; enum { EVGA_PERIPHERAL_LED_FRONT = 0, EVGA_PERIPHERAL_LED_WHEEL = 1, EVGA_PERIPHERAL_LED_LOGO = 2 }; /*----------------------------------------------------------------------*\ | All values in this enum account for the required 0x0 byte at index 0 | | when using hid* APIs. The byte controlling the red value of an LED is | | at index 15 in the buffer passed to hid* APIs because there is a 0x0 | | byte at the beginning of said buffer. It would only be index 14 in the | | raw packet received by the peripheral. | \*----------------------------------------------------------------------*/ enum { EVGA_PERIPHERAL_CONNECTION_TYPE_BYTE = 3, EVGA_PERIPHERAL_LED_INDEX_BYTE = 8, EVGA_PERIPHERAL_MODE_BYTE = 9, /*--------------*\ | Range [0, 100] | \*--------------*/ EVGA_PERIPHERAL_BRIGHTNESS_BYTE = 10, /*--------------*\ | Range [0, 100] | \*--------------*/ EVGA_PERIPHERAL_SPEED_BYTE = 11, /*-------------------------------------------------------*\ | Determines when the lights initiate and terminate: | | immediately, on key press, or on key release. | | Currently unused because OpenRGB does not support this. | \*-------------------------------------------------------*/ EVGA_PERIPHERAL_EFFECT_DURATION_BYTE = 13, /*---------------------------------------------------------------------------------*\ | The byte at this index specifies how many colors are being passed in this packet. | | The colors are a sequence of 3 bytes per color: red, green, then blue. Thus, when | | passing 1 for this byte, the device will read the 3 next bytes as the color. When | | passing 7, the device will read the next 21 bytes in sets of 3. | \*---------------------------------------------------------------------------------*/ EVGA_PERIPHERAL_COLOR_COUNT_BYTE = 14, EVGA_PERIPHERAL_RED_BYTE = 15, EVGA_PERIPHERAL_GREEN_BYTE = 16, EVGA_PERIPHERAL_BLUE_BYTE = 17, }; enum { EVGA_PERIPHERAL_CONNECTION_TYPE_WIRED = 0, EVGA_PERIPHERAL_CONNECTION_TYPE_WIRELESS = 2, }; struct EVGAMouseControllerDeviceState { uint8_t mode; uint8_t brightness; uint8_t speed; std::vector colors; }; class EVGAMouseController { public: EVGAMouseController(hid_device* dev_handle, char *_path, int connection_type); ~EVGAMouseController(); std::string GetDeviceName(); std::string GetSerial(); std::string GetLocation(); /*---------------------------------------------------------------*\ | Gets the mode, colors, or entire state currently on the device. | | OpenRGB does not support per-zone modes. All zones must be set | | to the same mode. It's possible to use the vendor's software | | to set each LED to separate states. These methods use the logo | | LED (#2) as the source of truth. | \*---------------------------------------------------------------*/ uint8_t GetMode(); EVGAMouseControllerDeviceState GetState(); /*-------------------------------------------------------------------------*\ | Gets the color of the given LED from the device. If a device is in a mode | | with multiple colors, returns the first color in the list. | \*-------------------------------------------------------------------------*/ RGBColor GetColorOfLed(int led); inline void SetMode(uint8_t mode) { SetMode(mode, 0); SetMode(mode, 1); SetMode(mode, 2); } void SetMode(uint8_t mode, uint8_t index); /*-----------------------------------*\ | Set a single LED to a single color. | \*-----------------------------------*/ void SetLed(uint8_t index, uint8_t brightness, uint8_t speed, RGBColor color); /*---------------------------------------------------*\ | Set the LED at the given index to a list of colors. | \*---------------------------------------------------*/ void SetLed(uint8_t index, uint8_t brightness, uint8_t speed, const std::vector& colors); /*---------------------------------------------------------------------------*\ | Set the LED at the given index to a list of colors, then activate the mode. | \*---------------------------------------------------------------------------*/ void SetLedAndActivate(uint8_t index, uint8_t brightness, uint8_t speed, const std::vector& colors); /*---------------------------------*\ | Set all LEDs to a list of colors. | \*---------------------------------*/ void SetAllLeds(uint8_t brightness, uint8_t speed, const std::vector& colors); /*---------------------------------------------------------*\ | Set all LEDs to a list of colors, then activate the mode. | \*---------------------------------------------------------*/ void SetAllLedsAndActivate(uint8_t brightness, uint8_t speed, const std::vector& colors); private: /*----------------------------------------------------------------------------------------------------------------*\ | Sets the led to the given colors with the given brightness and speed. if activate is true, activates the current | | mode. If false, just sets the colors. | \*----------------------------------------------------------------------------------------------------------------*/ void SetLed(uint8_t index, uint8_t brightness, uint8_t speed, const std::vector& colors, bool activate); /*-----------------------------------------------------------------------------*\ | Requests and stores the current mode and colors for all leds from the device. | \*-----------------------------------------------------------------------------*/ void RefreshDeviceState(); /*----------------------------------------------------------------------------------*\ | Requests and stores the current mode and colors for the given led from the device. | \*----------------------------------------------------------------------------------*/ void RefreshDeviceState(int led); /*-----------------------------------------------------------------------------------*\ | Repeatedly reads a packet from the device until a valid packet is received. If no | | such packet is received after max_attempts tries, returns false. Otherwise, returns | | true. buffer must be an array with size EVGA_PERIPHERAL_PACKET_SIZE. | \*-----------------------------------------------------------------------------------*/ bool ReadPacketOrLogErrors(unsigned char *buffer, int max_attempts); /*-----------------------------------------------------------------------------------*\ | Repeatedly reads a packet from the device until a valid packet is received. If a | | "response not ready" packet is returned, try again, up to a maximum number of tries | | max_attempts. buffer must be an array with size EVGA_PERIPHERAL_PACKET_SIZE. | | Returns the number of bytes read or -1 on error. | \*-----------------------------------------------------------------------------------*/ int ReadPacketOrWait(unsigned char *buffer, int max_attempts); /*-----------------------------------------------------------------------------*\ | Waits a predetermined amount of time to avoid sending packets to frequently. | | In wireless mode, packets sent too close together might overwrite each other, | | causing earlier ones to silently not propagate. Does not wait in connection | | types that do not have this problem. | \*-----------------------------------------------------------------------------*/ void Wait(); /*------------------------------------------------------------------------------*\ | Returns true if the packet received from the device signals that the device is | | asleep and will not send or receive other packets. | \*------------------------------------------------------------------------------*/ bool IsAsleepPacket(unsigned char *buffer); /*------------------------------------------------------------------------------*\ | Returns true if the packet received from the device signals that the device is | | still processing a request device state packet. In this case, the request to | | read from the device should be retried at a later time. | \*------------------------------------------------------------------------------*/ bool IsResponseNotReadyPacket(unsigned char *buffer); std::string device_name; std::string location; hid_device* dev; int connection_type; std::vector led_states; };