1
0
mirror of https://github.com/MatMoul/g810-led.git synced 2025-04-04 15:21:45 +00:00
This commit is contained in:
Marcin Jaworski 2021-09-02 13:42:50 +02:00 committed by GitHub
commit cca5e0541b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 212 additions and 53 deletions

View File

@ -1,6 +1,6 @@
# g810-led</br> # 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> ## Compatible keyboards :</br>
- **G213 Prodigy**</br> - **G213 Prodigy**</br>
@ -14,6 +14,7 @@ Linux led controller for Logitech G213, G410, G413, G512, G513, G610, G810, G815
- **G815 LIGHTSYNC**</br> - **G815 LIGHTSYNC**</br>
- **G910 Orion Spark**</br> - **G910 Orion Spark**</br>
- **G910 Orion Spectrum**</br> - **G910 Orion Spectrum**</br>
- **G915 LIGHTSPEED**</br>
- **GPRO**</br> - **GPRO**</br>
## Contribute and evolution :</br> ## Contribute and evolution :</br>
@ -36,6 +37,7 @@ You can load predefined configurations on startup!
`g810-led --help`</br> `g810-led --help`</br>
`g815-led --help`</br> `g815-led --help`</br>
`g910-led --help`</br> `g910-led --help`</br>
`g915-led --help`</br>
`gpro-led --help`</br> `gpro-led --help`</br>
`g810-led --help-keys`</br> `g810-led --help-keys`</br>

View File

@ -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/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/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/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 @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 sample_profiles/* $(DESTDIR)/etc/$(PROGN)/samples
@cp udev/$(PROGN).rules $(DESTDIR)/etc/udev/rules.d @cp udev/$(PROGN).rules $(DESTDIR)/etc/udev/rules.d
@ -114,6 +115,7 @@ uninstall:
@rm /usr/bin/g610-led @rm /usr/bin/g610-led
@rm /usr/bin/g815-led @rm /usr/bin/g815-led
@rm /usr/bin/g910-led @rm /usr/bin/g910-led
@rm /usr/bin/g915-led
@rm /usr/bin/gpro-led @rm /usr/bin/gpro-led
@rm /usr/bin/$(PROGN) @rm /usr/bin/$(PROGN)

View File

@ -163,7 +163,7 @@ bool LedKeyboard::open(uint16_t vendorID, uint16_t productID, string serial) {
while (dev) { while (dev) {
for (int i=0; i<(int)SupportedKeyboards.size(); i++) { for (int i=0; i<(int)SupportedKeyboards.size(); i++) {
if (dev->vendor_id == SupportedKeyboards[i][0] && dev->product_id == SupportedKeyboards[i][1]) { if (dev->vendor_id == SupportedKeyboards[i][0] && dev->product_id == SupportedKeyboards[i][1] && dev->interface_number == SupportedKeyboards[i][2]) {
if (!serial.empty() && dev->serial_number != NULL && wideSerial.compare(dev->serial_number) != 0) break; //Serial didn't match if (!serial.empty() && dev->serial_number != NULL && wideSerial.compare(dev->serial_number) != 0) break; //Serial didn't match
if (dev->serial_number != NULL) { if (dev->serial_number != NULL) {
@ -188,7 +188,8 @@ bool LedKeyboard::open(uint16_t vendorID, uint16_t productID, string serial) {
currentDevice.vendorID = dev->vendor_id; currentDevice.vendorID = dev->vendor_id;
currentDevice.productID = dev->product_id; currentDevice.productID = dev->product_id;
currentDevice.model = (KeyboardModel)SupportedKeyboards[i][2]; currentDevice.path = dev->path;
currentDevice.model = (KeyboardModel)SupportedKeyboards[i][3];
break; break;
} }
} }
@ -204,8 +205,7 @@ bool LedKeyboard::open(uint16_t vendorID, uint16_t productID, string serial) {
return false; return false;
} }
if (wideSerial.empty()) m_hidHandle = hid_open(currentDevice.vendorID, currentDevice.productID, NULL); m_hidHandle = hid_open_path(currentDevice.path.c_str());
else m_hidHandle = hid_open(currentDevice.vendorID, currentDevice.productID, wideSerial.c_str());
if(m_hidHandle == 0) { if(m_hidHandle == 0) {
hid_exit(); hid_exit();
@ -248,7 +248,7 @@ bool LedKeyboard::open(uint16_t vendorID, uint16_t productID, string serial) {
currentDevice.serialNumber = serial; currentDevice.serialNumber = serial;
currentDevice.vendorID = desc.idVendor; currentDevice.vendorID = desc.idVendor;
currentDevice.productID = desc.idProduct; currentDevice.productID = desc.idProduct;
currentDevice.model = (KeyboardModel)SupportedKeyboards[i][2]; currentDevice.model = (KeyboardModel)SupportedKeyboards[i][3];
dev = device; dev = device;
libusb_close(m_hidHandle); libusb_close(m_hidHandle);
@ -276,7 +276,7 @@ bool LedKeyboard::open(uint16_t vendorID, uint16_t productID, string serial) {
} }
currentDevice.vendorID = desc.idVendor; currentDevice.vendorID = desc.idVendor;
currentDevice.productID = desc.idProduct; currentDevice.productID = desc.idProduct;
currentDevice.model = (KeyboardModel)SupportedKeyboards[i][2]; currentDevice.model = (KeyboardModel)SupportedKeyboards[i][3];
if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iManufacturer, buf, 256) >= 1) currentDevice.manufacturer = string((char*)buf); if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iManufacturer, buf, 256) >= 1) currentDevice.manufacturer = string((char*)buf);
if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iProduct, buf, 256) >= 1) currentDevice.product = string((char*)buf); if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iProduct, buf, 256) >= 1) currentDevice.product = string((char*)buf);
if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iSerialNumber, buf, 256) >= 1) currentDevice.serialNumber = string((char*)buf); if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iSerialNumber, buf, 256) >= 1) currentDevice.serialNumber = string((char*)buf);
@ -306,9 +306,18 @@ bool LedKeyboard::open(uint16_t vendorID, uint16_t productID, string serial) {
m_ctx = NULL; m_ctx = NULL;
return false; return false;
} }
if(libusb_kernel_driver_active(m_hidHandle, 1) == 1) { int interface_num;
if(libusb_detach_kernel_driver(m_hidHandle, 1) != 0) { 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); libusb_exit(m_ctx);
m_ctx = NULL; m_ctx = NULL;
return false; return false;
@ -316,9 +325,9 @@ bool LedKeyboard::open(uint16_t vendorID, uint16_t productID, string serial) {
m_isKernellDetached = true; m_isKernellDetached = true;
} }
if(libusb_claim_interface(m_hidHandle, 1) < 0) { if(libusb_claim_interface(m_hidHandle, interface_num) < 0) {
if(m_isKernellDetached==true) { if(m_isKernellDetached==true) {
libusb_attach_kernel_driver(m_hidHandle, 1); libusb_attach_kernel_driver(m_hidHandle, interface_num);
m_isKernellDetached = false; m_isKernellDetached = false;
} }
libusb_exit(m_ctx); libusb_exit(m_ctx);
@ -348,9 +357,19 @@ bool LedKeyboard::close() {
return true; return true;
#elif defined(libusb) #elif defined(libusb)
if (m_hidHandle == NULL) return true; 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) { if(m_isKernellDetached==true) {
libusb_attach_kernel_driver(m_hidHandle, 1); libusb_attach_kernel_driver(m_hidHandle, interface_num);
m_isKernellDetached = false; m_isKernellDetached = false;
} }
libusb_close(m_hidHandle); libusb_close(m_hidHandle);
@ -388,6 +407,9 @@ bool LedKeyboard::commit() {
case KeyboardModel::g910: case KeyboardModel::g910:
data = { 0x11, 0xff, 0x0f, 0x5d }; data = { 0x11, 0xff, 0x0f, 0x5d };
break; break;
case KeyboardModel::g915:
data = { 0x11, 0x01, 0x0b, 0x7f };
break;
default: default:
return false; return false;
} }
@ -411,6 +433,18 @@ bool LedKeyboard::setKeys(KeyValueArray keyValues) {
switch (currentDevice.model) { switch (currentDevice.model) {
case KeyboardModel::g815: 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++) { 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 ); 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, {})); 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; uint8_t gi = 0;
while (gi < x.second.size()) { while (gi < x.second.size()) {
size_t data_size = 20; 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.red);
data.push_back(x.second[0].color.green); data.push_back(x.second[0].color.green);
data.push_back(x.second[0].color.blue); data.push_back(x.second[0].color.blue);
@ -693,6 +727,7 @@ bool LedKeyboard::setAllKeys(LedKeyboard::Color color) {
case KeyboardModel::g810: case KeyboardModel::g810:
case KeyboardModel::g815: case KeyboardModel::g815:
case KeyboardModel::g910: case KeyboardModel::g910:
case KeyboardModel::g915:
case KeyboardModel::gpro: case KeyboardModel::gpro:
for (uint8_t i = 0; i < keyGroupLogo.size(); i++) keyValues.push_back({keyGroupLogo[i], color}); 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}); 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; LedKeyboard::byte_buffer_t data;
switch (currentDevice.model) { switch (currentDevice.model) {
case KeyboardModel::g815: 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) { switch (value) {
case 0x00: case 0x00:
case 0x01: case 0x01:
data = { 0x11, 0xff, 0x0c, 0x0c, value }; data = { 0x11, g815_target, g815_feat_idx, 0x0c, value };
data.resize(20, 0x00); data.resize(20, 0x00);
return sendDataInternal(data); return sendDataInternal(data);
default: default:
@ -747,17 +794,29 @@ bool LedKeyboard::setMNKey(uint8_t value) {
LedKeyboard::byte_buffer_t data; LedKeyboard::byte_buffer_t data;
switch (currentDevice.model) { switch (currentDevice.model) {
case KeyboardModel::g815: 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) { switch (value) {
case 0x01: case 0x01:
data = { 0x11, 0xff, 0x0b, 0x1c, 0x01 }; data = { 0x11, g815_target, g815_feat_idx, 0x1c, 0x01 };
data.resize(20, 0x00); data.resize(20, 0x00);
return sendDataInternal(data); return sendDataInternal(data);
case 0x02: case 0x02:
data = { 0x11, 0xff, 0x0b, 0x1c, 0x02 }; data = { 0x11, g815_target, g815_feat_idx, 0x1c, 0x02 };
data.resize(20, 0x00); data.resize(20, 0x00);
return sendDataInternal(data); return sendDataInternal(data);
case 0x03: case 0x03:
data = { 0x11, 0xff, 0x0b, 0x1c, 0x04 }; data = { 0x11, g815_target, g815_feat_idx, 0x1c, 0x04 };
data.resize(20, 0x00); data.resize(20, 0x00);
return sendDataInternal(data); return sendDataInternal(data);
default: default:
@ -791,10 +850,22 @@ bool LedKeyboard::setGKeysMode(uint8_t value) {
LedKeyboard::byte_buffer_t data; LedKeyboard::byte_buffer_t data;
switch (currentDevice.model) { switch (currentDevice.model) {
case KeyboardModel::g815: 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) { switch (value) {
case 0x00: case 0x00:
case 0x01: case 0x01:
data = { 0x11, 0xff, 0x0a, 0x2b, value }; data = { 0x11, g815_target, g815_feat_idx, 0x2b, value };
data.resize(20, 0x00); data.resize(20, 0x00);
return sendDataInternal(data); return sendDataInternal(data);
default: default:
@ -858,7 +929,19 @@ bool LedKeyboard::setOnBoardMode(OnBoardMode onBoardMode) {
byte_buffer_t data; byte_buffer_t data;
switch (currentDevice.model) { switch (currentDevice.model) {
case KeyboardModel::g815: 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); data.resize(20, 0x00);
return sendDataInternal(data); return sendDataInternal(data);
default: default:
@ -900,6 +983,8 @@ bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part,
setNativeEffect(effect, LedKeyboard::NativeEffectPart::logo, period, color, storage)); setNativeEffect(effect, LedKeyboard::NativeEffectPart::logo, period, color, storage));
} }
unsigned char target = 0xff;
switch (currentDevice.model) { switch (currentDevice.model) {
case KeyboardModel::g213: case KeyboardModel::g213:
case KeyboardModel::g413: case KeyboardModel::g413:
@ -920,6 +1005,10 @@ bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part,
protocolBytes[0] = 0x0f; protocolBytes[0] = 0x0f;
protocolBytes[1] = 0x1c; protocolBytes[1] = 0x1c;
break; break;
case KeyboardModel::g915:
protocolBytes[0] = 0x0a;
protocolBytes[1] = 0x1c;
target = 0x01;
case KeyboardModel::g910: case KeyboardModel::g910:
protocolBytes[0] = 0x10; protocolBytes[0] = 0x10;
protocolBytes[1] = 0x3c; protocolBytes[1] = 0x3c;
@ -929,7 +1018,7 @@ bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part,
} }
byte_buffer_t data = { byte_buffer_t data = {
0x11, 0xff, protocolBytes[0], protocolBytes[1], 0x11, target, protocolBytes[0], protocolBytes[1],
(uint8_t)part, static_cast<uint8_t>(effectGroup), (uint8_t)part, static_cast<uint8_t>(effectGroup),
// color of static-color and breathing effects // color of static-color and breathing effects
color.red, color.green, color.blue, color.red, color.green, color.blue,
@ -951,7 +1040,19 @@ bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part,
bool retval; bool retval;
switch (currentDevice.model) { switch (currentDevice.model) {
case KeyboardModel::g815: 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); setupData.resize(20, 0x00);
retval = sendDataInternal(setupData); retval = sendDataInternal(setupData);
@ -1030,20 +1131,32 @@ bool LedKeyboard::sendDataInternal(byte_buffer_t &data) {
*/ */
return true; return true;
#elif defined(libusb) #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 (! m_isOpen) return false;
if (data.size() > 20) { 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) const_cast<unsigned char*>(data.data()), data.size(), 2000) < 0)
return false; return false;
} else { } 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) const_cast<unsigned char*>(data.data()), data.size(), 2000) < 0)
return false; return false;
} }
usleep(1000); usleep(1000);
unsigned char buffer[64]; unsigned char buffer[64];
int len = 0; 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; return true;
#endif #endif
} }
@ -1089,17 +1202,29 @@ LedKeyboard::byte_buffer_t LedKeyboard::getKeyGroupAddress(LedKeyboard::KeyAddre
} }
break; break;
case KeyboardModel::g815: 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) { switch (keyAddressGroup) {
case LedKeyboard::KeyAddressGroup::logo: case LedKeyboard::KeyAddressGroup::logo:
return { 0x11, 0xff, 0x10, 0x1c }; return { 0x11, g815_target, g815_feat_idx, 0x1c };
case LedKeyboard::KeyAddressGroup::indicators: case LedKeyboard::KeyAddressGroup::indicators:
return { 0x11, 0xff, 0x10, 0x1c }; return { 0x11, g815_target, g815_feat_idx, 0x1c };
case LedKeyboard::KeyAddressGroup::gkeys: case LedKeyboard::KeyAddressGroup::gkeys:
return { 0x11, 0xff, 0x10, 0x1c }; return { 0x11, g815_target, g815_feat_idx, 0x1c };
case LedKeyboard::KeyAddressGroup::multimedia: case LedKeyboard::KeyAddressGroup::multimedia:
return { 0x11, 0xff, 0x10, 0x1c }; return { 0x11, g815_target, g815_feat_idx, 0x1c };
case LedKeyboard::KeyAddressGroup::keys: case LedKeyboard::KeyAddressGroup::keys:
return { 0x11, 0xff, 0x10, 0x1c }; return { 0x11, g815_target, g815_feat_idx, 0x1c };
} }
break; break;
case KeyboardModel::g910: case KeyboardModel::g910:

View File

@ -45,19 +45,20 @@ class LedKeyboard {
public: public:
std::vector<std::vector<uint16_t>> SupportedKeyboards = { std::vector<std::vector<uint16_t>> SupportedKeyboards = {
{ 0x46d, 0xc336, (uint16_t)KeyboardModel::g213 }, { 0x46d, 0xc336, 1, (uint16_t)KeyboardModel::g213 },
{ 0x46d, 0xc330, (uint16_t)KeyboardModel::g410 }, { 0x46d, 0xc330, 1, (uint16_t)KeyboardModel::g410 },
{ 0x46d, 0xc33a, (uint16_t)KeyboardModel::g413 }, { 0x46d, 0xc33a, 1, (uint16_t)KeyboardModel::g413 },
{ 0x46d, 0xc342, (uint16_t)KeyboardModel::g512 }, { 0x46d, 0xc342, 1, (uint16_t)KeyboardModel::g512 },
{ 0x46d, 0xc33c, (uint16_t)KeyboardModel::g513 }, { 0x46d, 0xc33c, 1, (uint16_t)KeyboardModel::g513 },
{ 0x46d, 0xc333, (uint16_t)KeyboardModel::g610 }, { 0x46d, 0xc333, 1, (uint16_t)KeyboardModel::g610 },
{ 0x46d, 0xc338, (uint16_t)KeyboardModel::g610 }, { 0x46d, 0xc338, 1, (uint16_t)KeyboardModel::g610 },
{ 0x46d, 0xc331, (uint16_t)KeyboardModel::g810 }, { 0x46d, 0xc331, 1, (uint16_t)KeyboardModel::g810 },
{ 0x46d, 0xc337, (uint16_t)KeyboardModel::g810 }, { 0x46d, 0xc337, 1, (uint16_t)KeyboardModel::g810 },
{ 0x46d, 0xc33f, (uint16_t)KeyboardModel::g815 }, { 0x46d, 0xc33f, 1, (uint16_t)KeyboardModel::g815 },
{ 0x46d, 0xc32b, (uint16_t)KeyboardModel::g910 }, { 0x46d, 0xc32b, 1, (uint16_t)KeyboardModel::g910 },
{ 0x46d, 0xc335, (uint16_t)KeyboardModel::g910 }, { 0x46d, 0xc335, 1, (uint16_t)KeyboardModel::g910 },
{ 0x46d, 0xc339, (uint16_t)KeyboardModel::gpro } { 0x46d, 0xc541, 2, (uint16_t)KeyboardModel::g915 },
{ 0x46d, 0xc339, 1, (uint16_t)KeyboardModel::gpro }
}; };
enum class KeyboardModel : uint8_t { enum class KeyboardModel : uint8_t {
@ -71,6 +72,7 @@ class LedKeyboard {
g810, g810,
g815, g815,
g910, g910,
g915,
gpro gpro
}; };
enum class StartupMode : uint8_t { enum class StartupMode : uint8_t {
@ -165,6 +167,7 @@ class LedKeyboard {
std::string manufacturer = ""; std::string manufacturer = "";
std::string product = ""; std::string product = "";
std::string serialNumber = ""; std::string serialNumber = "";
std::string path = "";
KeyboardModel model; KeyboardModel model;
} DeviceInfo; } DeviceInfo;

View File

@ -38,6 +38,7 @@ namespace help {
else if(cmdName == "g810-led") return KeyboardFeatures::g810; else if(cmdName == "g810-led") return KeyboardFeatures::g810;
else if(cmdName == "g815-led") return KeyboardFeatures::g815; else if(cmdName == "g815-led") return KeyboardFeatures::g815;
else if(cmdName == "g910-led") return KeyboardFeatures::g910; else if(cmdName == "g910-led") return KeyboardFeatures::g910;
else if(cmdName == "g915-led") return KeyboardFeatures::g915;
else if(cmdName == "gpro-led") return KeyboardFeatures::gpro; else if(cmdName == "gpro-led") return KeyboardFeatures::gpro;
return KeyboardFeatures::all; return KeyboardFeatures::all;
} }
@ -107,7 +108,8 @@ namespace help {
cout<<" -dv\t\t\t\t\tDevice vendor ID, such as 046d for Logitech. Can be omitted to match any vendor ID"<<endl; cout<<" -dv\t\t\t\t\tDevice vendor ID, such as 046d for Logitech. Can be omitted to match any vendor ID"<<endl;
cout<<" -dp\t\t\t\t\tDevice product ID, such as c337 for Logitech G810. Can be omitted to match any product ID"<<endl; cout<<" -dp\t\t\t\t\tDevice product ID, such as c337 for Logitech G810. Can be omitted to match any product ID"<<endl;
cout<<" -ds\t\t\t\t\tDevice serial number, Can be omitted to match the first device found"<<endl; cout<<" -ds\t\t\t\t\tDevice serial number, Can be omitted to match the first device found"<<endl;
cout<<" -tuk\t\t\t\t\tTest unsupported keyboard with one of supported protocol (1-3) -dv and -dp are required"<<endl; cout<<" -di\t\t\t\t\tDevice interface number. Can be used with -tuk argument to specify non-default device interface number"<<endl;
cout<<" -tuk\t\t\t\t\tTest unsupported keyboard with one of supported protocol (1-5) -dv and -dp are required"<<endl;
cout<<endl; cout<<endl;
cout<<"Values:"<<endl; cout<<"Values:"<<endl;
if((features | KeyboardFeatures::rgb) == features) if((features | KeyboardFeatures::rgb) == features)
@ -124,8 +126,10 @@ namespace help {
cout<<" key values :\t\t\t\tabc... 123... and other (use --help-keys for more detail)"<<endl; cout<<" key values :\t\t\t\tabc... 123... and other (use --help-keys for more detail)"<<endl;
if((features | KeyboardFeatures::setgroup) == features) if((features | KeyboardFeatures::setgroup) == features)
cout<<" group values :\t\t\tlogo, indicators, fkeys, ... (use --help-keys for more detail)"<<endl; cout<<" group values :\t\t\tlogo, indicators, fkeys, ... (use --help-keys for more detail)"<<endl;
cout<<" startup mode :\t\t\twave, color"<<endl; if ((features | KeyboardFeatures::poweronfx) == features)
cout<<" on-board mode :\t\t\tboard, software"<<endl; cout<<" startup mode :\t\t\twave, color"<<endl;
if ((features | KeyboardFeatures::onboardmode) == features)
cout<<" on-board mode :\t\t\tboard, software"<<endl;
cout<<endl; cout<<endl;
} }

View File

@ -54,6 +54,7 @@ namespace help {
g810 = rgb | commit | logo1 | numpad | multimedia | setall | setgroup | setkey | setindicators | poweronfx, g810 = rgb | commit | logo1 | numpad | multimedia | setall | setgroup | setkey | setindicators | poweronfx,
g815 = rgb | commit | logo1 | numpad | multimedia | gkeys | setall | setgroup | setkey | setindicators | onboardmode, 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, 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 gpro = rgb | commit | logo1 | setall | setgroup | setkey | setindicators | poweronfx | userstoredlighting
}; };
inline KeyboardFeatures operator|(KeyboardFeatures a, KeyboardFeatures b); inline KeyboardFeatures operator|(KeyboardFeatures a, KeyboardFeatures b);

View File

@ -271,6 +271,7 @@ int main(int argc, char **argv) {
std::string serial; std::string serial;
uint16_t vendorID = 0x0; uint16_t vendorID = 0x0;
uint16_t productID = 0x0; uint16_t productID = 0x0;
uint8_t interfaceNumber = 0xff;
int argIndex = 1; int argIndex = 1;
while (argIndex < argc) while (argIndex < argc)
@ -286,29 +287,49 @@ int main(int argc, char **argv) {
if (! utils::parseUInt16(argv[argIndex + 1], vendorID)) return 1; if (! utils::parseUInt16(argv[argIndex + 1], vendorID)) return 1;
argIndex += 2; argIndex += 2;
continue; continue;
} else if (argc > (argIndex + 1) && arg == "-dp"){ } else if (argc > (argIndex + 1) && arg == "-dp") {
if (! utils::parseUInt16(argv[argIndex + 1], productID)) return 1; if (!utils::parseUInt16(argv[argIndex + 1], productID)) return 1;
argIndex += 2;
continue;
} else if (argc > (argIndex + 1) && arg == "-di") {
if (!utils::parseUInt8(argv[argIndex + 1], interfaceNumber)) return 1;
argIndex += 2; argIndex += 2;
continue; continue;
} else if (argc > (argIndex + 1) && arg == "-tuk"){ } else if (argc > (argIndex + 1) && arg == "-tuk"){
uint8_t kbdProtocol = 0; uint8_t kbdProtocol = 0;
if (! utils::parseUInt8(argv[argIndex + 1], kbdProtocol)) return 1; if (! utils::parseUInt8(argv[argIndex + 1], kbdProtocol)) return 1;
uint8_t ifNum;
LedKeyboard::KeyboardModel model = LedKeyboard::KeyboardModel::unknown;
switch(kbdProtocol) { switch(kbdProtocol) {
case 1: case 1:
kbd.SupportedKeyboards = { { vendorID, productID, (uint16_t)LedKeyboard::KeyboardModel::g810 } }; ifNum = 1;
model = LedKeyboard::KeyboardModel::g810;
break; break;
case 2: case 2:
kbd.SupportedKeyboards = { { vendorID, productID, (uint16_t)LedKeyboard::KeyboardModel::g910 } }; ifNum = 1;
model = LedKeyboard::KeyboardModel::g910;
break; break;
case 3: case 3:
kbd.SupportedKeyboards = { { vendorID, productID, (uint16_t)LedKeyboard::KeyboardModel::g213 } }; ifNum = 1;
model = LedKeyboard::KeyboardModel::g213;
break; break;
case 4: case 4:
kbd.SupportedKeyboards = { { vendorID, productID, (uint16_t)LedKeyboard::KeyboardModel::g815 } }; ifNum = 1;
model = LedKeyboard::KeyboardModel::g815;
break;
case 5:
ifNum = 2;
model = LedKeyboard::KeyboardModel::g915;
break; break;
default: default:
break; break;
} }
if (model != LedKeyboard::KeyboardModel::unknown) {
if (interfaceNumber != 0xff) ifNum = interfaceNumber;
kbd.SupportedKeyboards = { { vendorID, productID, ifNum, (uint16_t)model } };
}
argIndex += 2; argIndex += 2;
continue; continue;
} }

View File

@ -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}=="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}=="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}=="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}=="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}=="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" ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c339", MODE="666" RUN+="/usr/bin/gpro-led -p /etc/g810-led/profile"