Skip to content

Instantly share code, notes, and snippets.

@makkarpov
Created June 6, 2016 19:55
Show Gist options
  • Save makkarpov/b559a82724158adeecf195e26ef3d951 to your computer and use it in GitHub Desktop.
Save makkarpov/b559a82724158adeecf195e26ef3d951 to your computer and use it in GitHub Desktop.
MSI keyboard C++
#include "Color.h"
Color::Color(uint8_t r, uint8_t g, uint8_t b) noexcept
: _r(r), _g(g), _b(b)
{
}
uint8_t Color::r() const noexcept {
return _r;
}
uint8_t Color::g() const noexcept {
return _g;
}
uint8_t Color::b() const noexcept {
return _b;
}
bool Color::operator==(const Color &rhs) const noexcept {
return (_r == rhs._r) && (_g == rhs._g) && (_b == rhs._b);
}
bool Color::operator!=(const Color &rhs) const noexcept {
return (_r != rhs._r) || (_g != rhs._g) || (_b != rhs._b);
}
Color Color::rgb(int rgb) noexcept {
return Color((uint8_t)((rgb >> 16) & 0xFF), (uint8_t) ((rgb >> 8) & 0xFF), (uint8_t) (rgb & 0xFF));
}
Color Color::hue(unsigned int hue) noexcept {
if (hue >= 360) {
hue %= 360;
}
uint8_t cu = (uint8_t) ((hue % 60) * 255 / 60);
uint8_t cd = (uint8_t) (255 - cu);
uint8_t r, g, b;
switch (hue / 60) {
case 0: r = 255; g = cu; b = 0; break;
case 1: r = cd; g = 255; b = 0; break;
case 2: r = 0; g = 255; b = cu; break;
case 3: r = 0; g = cd; b = 255; break;
case 4: r = cu; g = 0; b = 255; break;
case 5: r = 255; g = 0; b = cd; break;
default: r = 0; g = 0; b = 0; break; // to avoid compiler warning
}
return Color(r, g, b);
}
#ifndef MSIKBD_COLOR_H
#define MSIKBD_COLOR_H
#include <cstdint>
class Color {
uint8_t _r, _g, _b;
public:
Color(uint8_t r, uint8_t g, uint8_t b) noexcept;
uint8_t r() const noexcept;
uint8_t g() const noexcept;
uint8_t b() const noexcept;
bool operator==(const Color &rhs) const noexcept;
bool operator!=(const Color &rhs) const noexcept;
static Color hue(unsigned int hue) noexcept;
static Color rgb(int rgb) noexcept;
};
#endif //MSIKBD_COLOR_H
#include "Keyboard.h"
#include <stdexcept>
Keyboard::Keyboard() {
_dev = hid_open(0x1770, 0xFF00, nullptr);
if (_dev == nullptr) {
throw std::runtime_error("device is not present");
}
}
void Keyboard::write(uint8_t *data, size_t length) {
if (hid_send_feature_report(_dev, data, length) != length) {
throw std::runtime_error("feature report failed");
}
}
void Keyboard::write_color(uint8_t function, uint8_t index, Color color) {
uint8_t data[] = {
0x01, 0x02, function, index,
color.r(), color.g(), color.b(), 0x00
};
write(data, sizeof(data));
}
void Keyboard::write_mode(uint8_t mode) {
uint8_t data[] = {
0x01, 0x02, 0x41, mode,
0x00, 0x00, 0x00, 0x00
};
write(data, sizeof(data));
}
void Keyboard::write_gradient(uint8_t region, Color first, Color second) {
uint8_t index = (uint8_t) ((region - 1) * 3 + 1);
write_color(FUNCTION_GRAD, index++, first);
write_color(FUNCTION_GRAD, index++, second);
write_color(FUNCTION_GRAD, index, Color(0, 0, 255));
}
void Keyboard::normal(Color left, Color middle, Color right) {
write_mode(MODE_NORMAL);
write_color(FUNCTION_SET, REGION_LEFT, left);
write_color(FUNCTION_SET, REGION_MIDDLE, middle);
write_color(FUNCTION_SET, REGION_RIGHT, right);
}
void Keyboard::gaming(Color left) {
write_mode(MODE_GAMING);
write_color(FUNCTION_SET, REGION_LEFT, left);
}
void Keyboard::breathing(Color left, Color middle, Color right) {
write_gradient(REGION_LEFT, left, Color(0, 0, 0));
write_mode(MODE_BREATHING);
write_gradient(REGION_MIDDLE, middle, Color(0, 0, 0));
write_mode(MODE_BREATHING);
write_gradient(REGION_RIGHT, right, Color(0, 0, 0));
write_mode(MODE_BREATHING);
}
void Keyboard::breathing(ColorPair left, ColorPair middle, ColorPair right) {
write_gradient(REGION_LEFT, left.first, left.second);
write_mode(MODE_BREATHING);
write_gradient(REGION_MIDDLE, middle.first, middle.second);
write_mode(MODE_BREATHING);
write_gradient(REGION_RIGHT, right.first, right.second);
write_mode(MODE_BREATHING);
}
void Keyboard::wave(Color left, Color middle, Color right) {
write_gradient(REGION_LEFT, left, Color(0, 0, 0));
write_mode(MODE_WAVE);
write_gradient(REGION_MIDDLE, middle, Color(0, 0, 0));
write_mode(MODE_WAVE);
write_gradient(REGION_RIGHT, right, Color(0, 0, 0));
write_mode(MODE_WAVE);
}
void Keyboard::wave(ColorPair left, ColorPair middle, ColorPair right) {
write_gradient(REGION_LEFT, left.first, left.second);
write_mode(MODE_WAVE);
write_gradient(REGION_MIDDLE, middle.first, middle.second);
write_mode(MODE_WAVE);
write_gradient(REGION_RIGHT, right.first, right.second);
write_mode(MODE_WAVE);
}
#ifndef MSIKBD_KEYBOARD_H
#define MSIKBD_KEYBOARD_H
#include <hidapi/hidapi.h>
#include <utility>
#include "Color.h"
class Keyboard {
hid_device *_dev;
void write(uint8_t *data, size_t length);
void write_color(uint8_t function, uint8_t index, Color color);
void write_mode(uint8_t mode);
void write_gradient(uint8_t region, Color first, Color second);
enum {
MODE_NORMAL = 0x01,
MODE_GAMING = 0x02,
MODE_BREATHING = 0x03,
MODE_AUDIO = 0x04,
MODE_WAVE = 0x05,
MODE_DUAL_COLOR = 0x06,
REGION_LEFT = 0x01,
REGION_MIDDLE = 0x02,
REGION_RIGHT = 0x03,
FUNCTION_SET = 0x40,
FUNCTION_GRAD = 0x44
};
public:
Keyboard();
typedef std::pair<Color, Color> ColorPair;
void normal(Color left, Color middle, Color right);
void gaming(Color left);
void breathing(Color left, Color middle, Color right);
void breathing(ColorPair left, ColorPair middle, ColorPair right);
void wave(Color left, Color middle, Color right);
void wave(ColorPair left, ColorPair middle, ColorPair right);
};
#endif //MSIKBD_KEYBOARD_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment