mirror of
https://github.com/MatMoul/g810-led.git
synced 2024-12-23 17:26:11 +00:00
Add support for G915 (libusb only)
This commit is contained in:
parent
5ee810a520
commit
1c84af312a
@ -1,6 +1,6 @@
|
||||
# g810-led</br>
|
||||
|
||||
Linux led controller for Logitech G213, G410, G413, G512, G513, G610, G810, G815, G910 and GPRO Keyboards.</br>
|
||||
Linux led controller for Logitech G213, G410, G413, G512, G513, G610, G810, G815, G910, G915 and GPRO Keyboards.</br>
|
||||
|
||||
## Compatible keyboards :</br>
|
||||
- **G213 Prodigy**</br>
|
||||
@ -14,6 +14,7 @@ Linux led controller for Logitech G213, G410, G413, G512, G513, G610, G810, G815
|
||||
- **G815 LIGHTSYNC**</br>
|
||||
- **G910 Orion Spark**</br>
|
||||
- **G910 Orion Spectrum**</br>
|
||||
- **G915 LIGHTSPEED**</br>
|
||||
- **GPRO**</br>
|
||||
|
||||
## Contribute and evolution :</br>
|
||||
@ -36,6 +37,7 @@ You can load predefined configurations on startup!
|
||||
`g810-led --help`</br>
|
||||
`g815-led --help`</br>
|
||||
`g910-led --help`</br>
|
||||
`g915-led --help`</br>
|
||||
`gpro-led --help`</br>
|
||||
|
||||
`g810-led --help-keys`</br>
|
||||
|
2
makefile
2
makefile
@ -66,6 +66,7 @@ setup:
|
||||
@test -s $(DESTDIR)/usr/bin/g610-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g610-led
|
||||
@test -s $(DESTDIR)/usr/bin/g815-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g815-led
|
||||
@test -s $(DESTDIR)/usr/bin/g910-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g910-led
|
||||
@test -s $(DESTDIR)/usr/bin/g915-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g915-led
|
||||
@test -s $(DESTDIR)/usr/bin/gpro-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/gpro-led
|
||||
@cp sample_profiles/* $(DESTDIR)/etc/$(PROGN)/samples
|
||||
@cp udev/$(PROGN).rules $(DESTDIR)/etc/udev/rules.d
|
||||
@ -114,6 +115,7 @@ uninstall:
|
||||
@rm /usr/bin/g610-led
|
||||
@rm /usr/bin/g815-led
|
||||
@rm /usr/bin/g910-led
|
||||
@rm /usr/bin/g915-led
|
||||
@rm /usr/bin/gpro-led
|
||||
@rm /usr/bin/$(PROGN)
|
||||
|
||||
|
@ -306,9 +306,18 @@ bool LedKeyboard::open(uint16_t vendorID, uint16_t productID, string serial) {
|
||||
m_ctx = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(libusb_kernel_driver_active(m_hidHandle, 1) == 1) {
|
||||
if(libusb_detach_kernel_driver(m_hidHandle, 1) != 0) {
|
||||
|
||||
int interface_num;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g915:
|
||||
interface_num = 2;
|
||||
break;
|
||||
default:
|
||||
interface_num = 1;
|
||||
}
|
||||
|
||||
if(libusb_kernel_driver_active(m_hidHandle, interface_num) == 1) {
|
||||
if(libusb_detach_kernel_driver(m_hidHandle, interface_num) != 0) {
|
||||
libusb_exit(m_ctx);
|
||||
m_ctx = NULL;
|
||||
return false;
|
||||
@ -316,9 +325,9 @@ bool LedKeyboard::open(uint16_t vendorID, uint16_t productID, string serial) {
|
||||
m_isKernellDetached = true;
|
||||
}
|
||||
|
||||
if(libusb_claim_interface(m_hidHandle, 1) < 0) {
|
||||
if(libusb_claim_interface(m_hidHandle, interface_num) < 0) {
|
||||
if(m_isKernellDetached==true) {
|
||||
libusb_attach_kernel_driver(m_hidHandle, 1);
|
||||
libusb_attach_kernel_driver(m_hidHandle, interface_num);
|
||||
m_isKernellDetached = false;
|
||||
}
|
||||
libusb_exit(m_ctx);
|
||||
@ -348,9 +357,19 @@ bool LedKeyboard::close() {
|
||||
return true;
|
||||
#elif defined(libusb)
|
||||
if (m_hidHandle == NULL) return true;
|
||||
if(libusb_release_interface(m_hidHandle, 1) != 0) return false;
|
||||
|
||||
int interface_num;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g915:
|
||||
interface_num = 2;
|
||||
break;
|
||||
default:
|
||||
interface_num = 1;
|
||||
}
|
||||
|
||||
if(libusb_release_interface(m_hidHandle, interface_num) != 0) return false;
|
||||
if(m_isKernellDetached==true) {
|
||||
libusb_attach_kernel_driver(m_hidHandle, 1);
|
||||
libusb_attach_kernel_driver(m_hidHandle, interface_num);
|
||||
m_isKernellDetached = false;
|
||||
}
|
||||
libusb_close(m_hidHandle);
|
||||
@ -388,6 +407,9 @@ bool LedKeyboard::commit() {
|
||||
case KeyboardModel::g910:
|
||||
data = { 0x11, 0xff, 0x0f, 0x5d };
|
||||
break;
|
||||
case KeyboardModel::g915:
|
||||
data = { 0x11, 0x01, 0x0b, 0x7f };
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -411,6 +433,18 @@ bool LedKeyboard::setKeys(KeyValueArray keyValues) {
|
||||
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g815:
|
||||
case KeyboardModel::g915:
|
||||
unsigned char g815_target;
|
||||
unsigned char g815_feat_idx;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g915:
|
||||
g815_target = 0x01;
|
||||
g815_feat_idx = 0x0b;
|
||||
break;
|
||||
default:
|
||||
g815_target = 0xff;
|
||||
g815_feat_idx = 0x10;
|
||||
}
|
||||
for (uint8_t i = 0; i < keyValues.size(); i++) {
|
||||
uint32_t colorkey = static_cast<uint32_t>(keyValues[i].color.red | keyValues[i].color.green << 8 | keyValues[i].color.blue << 16 );
|
||||
if (KeyByColors.count(colorkey) == 0) KeyByColors.insert(pair<uint32_t, vector<KeyValue>>(colorkey, {}));
|
||||
@ -422,7 +456,7 @@ bool LedKeyboard::setKeys(KeyValueArray keyValues) {
|
||||
uint8_t gi = 0;
|
||||
while (gi < x.second.size()) {
|
||||
size_t data_size = 20;
|
||||
byte_buffer_t data = { 0x11, 0xff, 0x10, 0x6c };
|
||||
byte_buffer_t data = { 0x11, g815_target, g815_feat_idx, 0x6c };
|
||||
data.push_back(x.second[0].color.red);
|
||||
data.push_back(x.second[0].color.green);
|
||||
data.push_back(x.second[0].color.blue);
|
||||
@ -693,6 +727,7 @@ bool LedKeyboard::setAllKeys(LedKeyboard::Color color) {
|
||||
case KeyboardModel::g810:
|
||||
case KeyboardModel::g815:
|
||||
case KeyboardModel::g910:
|
||||
case KeyboardModel::g915:
|
||||
case KeyboardModel::gpro:
|
||||
for (uint8_t i = 0; i < keyGroupLogo.size(); i++) keyValues.push_back({keyGroupLogo[i], color});
|
||||
for (uint8_t i = 0; i < keyGroupIndicators.size(); i++) keyValues.push_back({keyGroupIndicators[i], color});
|
||||
@ -716,10 +751,22 @@ bool LedKeyboard::setMRKey(uint8_t value) {
|
||||
LedKeyboard::byte_buffer_t data;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g815:
|
||||
case KeyboardModel::g915:
|
||||
unsigned char g815_target;
|
||||
unsigned char g815_feat_idx;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g915:
|
||||
g815_target = 0x01;
|
||||
g815_feat_idx = 0x13;
|
||||
break;
|
||||
default:
|
||||
g815_target = 0xff;
|
||||
g815_feat_idx = 0x0c;
|
||||
}
|
||||
switch (value) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
data = { 0x11, 0xff, 0x0c, 0x0c, value };
|
||||
data = { 0x11, g815_target, g815_feat_idx, 0x0c, value };
|
||||
data.resize(20, 0x00);
|
||||
return sendDataInternal(data);
|
||||
default:
|
||||
@ -747,17 +794,29 @@ bool LedKeyboard::setMNKey(uint8_t value) {
|
||||
LedKeyboard::byte_buffer_t data;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g815:
|
||||
case KeyboardModel::g915:
|
||||
unsigned char g815_target;
|
||||
unsigned char g815_feat_idx;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g915:
|
||||
g815_target = 0x01;
|
||||
g815_feat_idx = 0x12;
|
||||
break;
|
||||
default:
|
||||
g815_target = 0xff;
|
||||
g815_feat_idx = 0x0b;
|
||||
}
|
||||
switch (value) {
|
||||
case 0x01:
|
||||
data = { 0x11, 0xff, 0x0b, 0x1c, 0x01 };
|
||||
data = { 0x11, g815_target, g815_feat_idx, 0x1c, 0x01 };
|
||||
data.resize(20, 0x00);
|
||||
return sendDataInternal(data);
|
||||
case 0x02:
|
||||
data = { 0x11, 0xff, 0x0b, 0x1c, 0x02 };
|
||||
data = { 0x11, g815_target, g815_feat_idx, 0x1c, 0x02 };
|
||||
data.resize(20, 0x00);
|
||||
return sendDataInternal(data);
|
||||
case 0x03:
|
||||
data = { 0x11, 0xff, 0x0b, 0x1c, 0x04 };
|
||||
data = { 0x11, g815_target, g815_feat_idx, 0x1c, 0x04 };
|
||||
data.resize(20, 0x00);
|
||||
return sendDataInternal(data);
|
||||
default:
|
||||
@ -791,10 +850,22 @@ bool LedKeyboard::setGKeysMode(uint8_t value) {
|
||||
LedKeyboard::byte_buffer_t data;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g815:
|
||||
case KeyboardModel::g915:
|
||||
unsigned char g815_target;
|
||||
unsigned char g815_feat_idx;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g915:
|
||||
g815_target = 0x01;
|
||||
g815_feat_idx = 0x11;
|
||||
break;
|
||||
default:
|
||||
g815_target = 0xff;
|
||||
g815_feat_idx = 0x0a;
|
||||
}
|
||||
switch (value) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
data = { 0x11, 0xff, 0x0a, 0x2b, value };
|
||||
data = { 0x11, g815_target, g815_feat_idx, 0x2b, value };
|
||||
data.resize(20, 0x00);
|
||||
return sendDataInternal(data);
|
||||
default:
|
||||
@ -858,7 +929,19 @@ bool LedKeyboard::setOnBoardMode(OnBoardMode onBoardMode) {
|
||||
byte_buffer_t data;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g815:
|
||||
data = { 0x11, 0xff, 0x11, 0x1a, static_cast<uint8_t>(onBoardMode) };
|
||||
case KeyboardModel::g915:
|
||||
unsigned char g815_target;
|
||||
unsigned char g815_feat_idx;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g915:
|
||||
g815_target = 0x01;
|
||||
g815_feat_idx = 0x15;
|
||||
break;
|
||||
default:
|
||||
g815_target = 0xff;
|
||||
g815_feat_idx = 0x11;
|
||||
}
|
||||
data = { 0x11, g815_target, g815_feat_idx, 0x1a, static_cast<uint8_t>(onBoardMode) };
|
||||
data.resize(20, 0x00);
|
||||
return sendDataInternal(data);
|
||||
default:
|
||||
@ -900,6 +983,8 @@ bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part,
|
||||
setNativeEffect(effect, LedKeyboard::NativeEffectPart::logo, period, color, storage));
|
||||
}
|
||||
|
||||
unsigned char target = 0xff;
|
||||
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g213:
|
||||
case KeyboardModel::g413:
|
||||
@ -920,6 +1005,10 @@ bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part,
|
||||
protocolBytes[0] = 0x0f;
|
||||
protocolBytes[1] = 0x1c;
|
||||
break;
|
||||
case KeyboardModel::g915:
|
||||
protocolBytes[0] = 0x0a;
|
||||
protocolBytes[1] = 0x1c;
|
||||
target = 0x01;
|
||||
case KeyboardModel::g910:
|
||||
protocolBytes[0] = 0x10;
|
||||
protocolBytes[1] = 0x3c;
|
||||
@ -929,7 +1018,7 @@ bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part,
|
||||
}
|
||||
|
||||
byte_buffer_t data = {
|
||||
0x11, 0xff, protocolBytes[0], protocolBytes[1],
|
||||
0x11, target, protocolBytes[0], protocolBytes[1],
|
||||
(uint8_t)part, static_cast<uint8_t>(effectGroup),
|
||||
// color of static-color and breathing effects
|
||||
color.red, color.green, color.blue,
|
||||
@ -951,7 +1040,19 @@ bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part,
|
||||
bool retval;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g815:
|
||||
setupData = { 0x11, 0xff, 0x0f, 0x5c, 0x01, 0x03, 0x03 };
|
||||
case KeyboardModel::g915:
|
||||
unsigned char g815_target;
|
||||
unsigned char g815_feat_idx;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g915:
|
||||
g815_target = 0x01;
|
||||
g815_feat_idx = 0x0a;
|
||||
break;
|
||||
default:
|
||||
g815_target = 0xff;
|
||||
g815_feat_idx = 0x0f;
|
||||
}
|
||||
setupData = { 0x11, g815_target, g815_feat_idx, 0x5c, 0x01, 0x03, 0x03 };
|
||||
setupData.resize(20, 0x00);
|
||||
retval = sendDataInternal(setupData);
|
||||
|
||||
@ -1030,20 +1131,32 @@ bool LedKeyboard::sendDataInternal(byte_buffer_t &data) {
|
||||
*/
|
||||
return true;
|
||||
#elif defined(libusb)
|
||||
int interface_num;
|
||||
int interrupt_endpoint;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g915:
|
||||
interface_num = 2;
|
||||
interrupt_endpoint = 0x83;
|
||||
break;
|
||||
default:
|
||||
interface_num = 1;
|
||||
interrupt_endpoint = 0x82;
|
||||
}
|
||||
|
||||
if (! m_isOpen) return false;
|
||||
if (data.size() > 20) {
|
||||
if(libusb_control_transfer(m_hidHandle, 0x21, 0x09, 0x0212, 1,
|
||||
if(libusb_control_transfer(m_hidHandle, 0x21, 0x09, 0x0212, interface_num,
|
||||
const_cast<unsigned char*>(data.data()), data.size(), 2000) < 0)
|
||||
return false;
|
||||
} else {
|
||||
if(libusb_control_transfer(m_hidHandle, 0x21, 0x09, 0x0211, 1,
|
||||
if(libusb_control_transfer(m_hidHandle, 0x21, 0x09, 0x0211, interface_num,
|
||||
const_cast<unsigned char*>(data.data()), data.size(), 2000) < 0)
|
||||
return false;
|
||||
}
|
||||
usleep(1000);
|
||||
unsigned char buffer[64];
|
||||
int len = 0;
|
||||
libusb_interrupt_transfer(m_hidHandle, 0x82, buffer, sizeof(buffer), &len, 1);
|
||||
libusb_interrupt_transfer(m_hidHandle, interrupt_endpoint, buffer, sizeof(buffer), &len, 1);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
@ -1089,17 +1202,29 @@ LedKeyboard::byte_buffer_t LedKeyboard::getKeyGroupAddress(LedKeyboard::KeyAddre
|
||||
}
|
||||
break;
|
||||
case KeyboardModel::g815:
|
||||
case KeyboardModel::g915:
|
||||
unsigned char g815_target;
|
||||
unsigned char g815_feat_idx;
|
||||
switch (currentDevice.model) {
|
||||
case KeyboardModel::g915:
|
||||
g815_target = 0x01;
|
||||
g815_feat_idx = 0x0b;
|
||||
break;
|
||||
default:
|
||||
g815_target = 0xff;
|
||||
g815_feat_idx = 0x10;
|
||||
}
|
||||
switch (keyAddressGroup) {
|
||||
case LedKeyboard::KeyAddressGroup::logo:
|
||||
return { 0x11, 0xff, 0x10, 0x1c };
|
||||
return { 0x11, g815_target, g815_feat_idx, 0x1c };
|
||||
case LedKeyboard::KeyAddressGroup::indicators:
|
||||
return { 0x11, 0xff, 0x10, 0x1c };
|
||||
return { 0x11, g815_target, g815_feat_idx, 0x1c };
|
||||
case LedKeyboard::KeyAddressGroup::gkeys:
|
||||
return { 0x11, 0xff, 0x10, 0x1c };
|
||||
return { 0x11, g815_target, g815_feat_idx, 0x1c };
|
||||
case LedKeyboard::KeyAddressGroup::multimedia:
|
||||
return { 0x11, 0xff, 0x10, 0x1c };
|
||||
return { 0x11, g815_target, g815_feat_idx, 0x1c };
|
||||
case LedKeyboard::KeyAddressGroup::keys:
|
||||
return { 0x11, 0xff, 0x10, 0x1c };
|
||||
return { 0x11, g815_target, g815_feat_idx, 0x1c };
|
||||
}
|
||||
break;
|
||||
case KeyboardModel::g910:
|
||||
|
@ -57,6 +57,7 @@ class LedKeyboard {
|
||||
{ 0x46d, 0xc33f, (uint16_t)KeyboardModel::g815 },
|
||||
{ 0x46d, 0xc32b, (uint16_t)KeyboardModel::g910 },
|
||||
{ 0x46d, 0xc335, (uint16_t)KeyboardModel::g910 },
|
||||
{ 0x46d, 0xc541, (uint16_t)KeyboardModel::g915 },
|
||||
{ 0x46d, 0xc339, (uint16_t)KeyboardModel::gpro }
|
||||
};
|
||||
|
||||
@ -71,6 +72,7 @@ class LedKeyboard {
|
||||
g810,
|
||||
g815,
|
||||
g910,
|
||||
g915,
|
||||
gpro
|
||||
};
|
||||
enum class StartupMode : uint8_t {
|
||||
|
@ -38,6 +38,7 @@ namespace help {
|
||||
else if(cmdName == "g810-led") return KeyboardFeatures::g810;
|
||||
else if(cmdName == "g815-led") return KeyboardFeatures::g815;
|
||||
else if(cmdName == "g910-led") return KeyboardFeatures::g910;
|
||||
else if(cmdName == "g915-led") return KeyboardFeatures::g915;
|
||||
else if(cmdName == "gpro-led") return KeyboardFeatures::gpro;
|
||||
return KeyboardFeatures::all;
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ namespace help {
|
||||
g810 = rgb | commit | logo1 | numpad | multimedia | setall | setgroup | setkey | setindicators | poweronfx,
|
||||
g815 = rgb | commit | logo1 | numpad | multimedia | gkeys | setall | setgroup | setkey | setindicators | onboardmode,
|
||||
g910 = rgb | commit | logo1 | logo2 | numpad | multimedia | gkeys | setall | setgroup | setkey | setindicators | poweronfx | userstoredlighting,
|
||||
g915 = rgb | commit | logo1 | numpad | multimedia | gkeys | setall | setgroup | setkey | setindicators | onboardmode,
|
||||
gpro = rgb | commit | logo1 | setall | setgroup | setkey | setindicators | poweronfx | userstoredlighting
|
||||
};
|
||||
inline KeyboardFeatures operator|(KeyboardFeatures a, KeyboardFeatures b);
|
||||
|
@ -306,6 +306,9 @@ int main(int argc, char **argv) {
|
||||
case 4:
|
||||
kbd.SupportedKeyboards = { { vendorID, productID, (uint16_t)LedKeyboard::KeyboardModel::g815 } };
|
||||
break;
|
||||
case 5:
|
||||
kbd.SupportedKeyboards = { { vendorID, productID, (uint16_t)LedKeyboard::KeyboardModel::g915 } };
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c3
|
||||
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c331", MODE="666" RUN+="/usr/bin/g810-led -p /etc/g810-led/profile"
|
||||
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c337", MODE="666" RUN+="/usr/bin/g810-led -p /etc/g810-led/profile"
|
||||
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c33f", MODE="666" RUN+="/usr/bin/g815-led -p /etc/g810-led/profile"
|
||||
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c541", MODE="666" RUN+="/usr/bin/g915-led -p /etc/g810-led/profile"
|
||||
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c32b", MODE="666" RUN+="/usr/bin/g910-led -p /etc/g810-led/profile"
|
||||
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c335", MODE="666" RUN+="/usr/bin/g910-led -p /etc/g810-led/profile"
|
||||
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c339", MODE="666" RUN+="/usr/bin/gpro-led -p /etc/g810-led/profile"
|
||||
|
Loading…
Reference in New Issue
Block a user