1
0
mirror of https://github.com/MatMoul/g810-led.git synced 2024-12-23 01:06:11 +00:00

Merge pull request #73 from pearsonk/SpecDevice

Support specifying a specific device for executing commands
This commit is contained in:
MatMoul 2017-04-29 15:15:44 +02:00 committed by GitHub
commit cbb416527b
6 changed files with 362 additions and 166 deletions

View File

@ -5,6 +5,7 @@
#include <vector> #include <vector>
#if defined(hidapi) #if defined(hidapi)
#include <locale>
#include "hidapi/hidapi.h" #include "hidapi/hidapi.h"
#elif defined(libusb) #elif defined(libusb)
#include "libusb-1.0/libusb.h" #include "libusb-1.0/libusb.h"
@ -20,38 +21,57 @@ LedKeyboard::~LedKeyboard() {
} }
bool LedKeyboard::listKeyboards() { vector<LedKeyboard::DeviceInfo> LedKeyboard::listKeyboards() {
vector<LedKeyboard::DeviceInfo> deviceList;
#if defined(hidapi) #if defined(hidapi)
if (hid_init() < 0) return false; if (hid_init() < 0) return deviceList;
struct hid_device_info *devs, *dev; struct hid_device_info *devs, *dev;
devs = hid_enumerate(0x0, 0x0); devs = hid_enumerate(0x0, 0x0);
dev = devs; dev = devs;
while (dev) { while (dev) {
for (int i=0; i<(int)SupportedKeyboards.size(); i++) { for (size_t i=0; i<SupportedKeyboards.size(); i++) {
if (dev->vendor_id == SupportedKeyboards[i][0]) { if (dev->vendor_id == SupportedKeyboards[i][0]) {
if (dev->product_id == SupportedKeyboards[i][1]) { if (dev->product_id == SupportedKeyboards[i][1]) {
cout<<"0x"<<std::hex<<dev->vendor_id \ DeviceInfo deviceInfo;
<<" 0x"<<std::hex<<dev->product_id \ deviceInfo.vendorID=dev->vendor_id;
<<" "<<dev->serial_number \ deviceInfo.productID=dev->product_id;
<<" "<<dev->path<<" ";
if (dev->serial_number != NULL) {
char buf[256];
wcstombs(buf,dev->serial_number,256);
deviceInfo.serialNumber = string(buf);
}
if (dev->manufacturer_string != NULL)
{
char buf[256];
wcstombs(buf,dev->manufacturer_string,256);
deviceInfo.manufacturer = string(buf);
}
if (dev->product_string != NULL)
{
char buf[256];
wcstombs(buf,dev->product_string,256);
deviceInfo.product = string(buf);
}
deviceList.push_back(deviceInfo);
dev = dev->next; dev = dev->next;
cout<<dev->serial_number<<" "<<dev->path<<endl;
i++;
break; break;
} }
} }
} }
dev = dev->next; if (dev != NULL) dev = dev->next;
} }
hid_free_enumeration(devs); hid_free_enumeration(devs);
hid_exit(); hid_exit();
return true;
#elif defined(libusb) #elif defined(libusb)
libusb_context *ctx = NULL; libusb_context *ctx = NULL;
if(libusb_init(&m_ctx) < 0) return false; if(libusb_init(&m_ctx) < 0) return deviceList;
libusb_device **devs; libusb_device **devs;
ssize_t cnt = libusb_get_device_list(ctx, &devs); ssize_t cnt = libusb_get_device_list(ctx, &devs);
@ -62,8 +82,20 @@ bool LedKeyboard::listKeyboards() {
for (int i=0; i<(int)SupportedKeyboards.size(); i++) { for (int i=0; i<(int)SupportedKeyboards.size(); i++) {
if (desc.idVendor == SupportedKeyboards[i][0]) { if (desc.idVendor == SupportedKeyboards[i][0]) {
if (desc.idProduct == SupportedKeyboards[i][1]) { if (desc.idProduct == SupportedKeyboards[i][1]) {
cout<<"0x"<<std::hex<<desc.idVendor \ unsigned char buf[256];
<<" 0x"<<std::hex<<desc.idProduct<<endl; DeviceInfo deviceInfo;
deviceInfo.vendorID=desc.idVendor;
deviceInfo.productID=desc.idProduct;
if (libusb_open(device, &m_hidHandle) != 0) continue;
if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iSerialNumber, buf, 256) >= 1) deviceInfo.serialNumber = string((char*)buf);
if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iManufacturer, buf, 256) >= 1) deviceInfo.manufacturer = string((char*)buf);
if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iProduct, buf, 256) >= 1) deviceInfo.product = string((char*)buf);
deviceList.push_back(deviceInfo);
libusb_close(m_hidHandle);
m_hidHandle = NULL;
break; break;
} }
} }
@ -71,11 +103,16 @@ bool LedKeyboard::listKeyboards() {
} }
libusb_free_device_list(devs, 1); libusb_free_device_list(devs, 1);
if (m_hidHandle != NULL) {
libusb_close(m_hidHandle);
m_hidHandle = NULL;
}
libusb_exit(m_ctx); libusb_exit(m_ctx);
return true; m_ctx = NULL;
#endif #endif
return false; return deviceList;
} }
@ -86,114 +123,204 @@ bool LedKeyboard::isOpen() {
bool LedKeyboard::open() { bool LedKeyboard::open() {
if (m_isOpen) return true; if (m_isOpen) return true;
return open(0x0,0x0,"");
}
bool LedKeyboard::open(uint16_t vendorID, uint16_t productID, string serial) {
if (m_isOpen && ! close()) return false;
currentDevice.model = KeyboardModel::unknown;
#if defined(hidapi) #if defined(hidapi)
if (hid_init() < 0) return false; if (hid_init() < 0) return false;
if (m_keyboardModel == KeyboardModel::unknown) { struct hid_device_info *devs, *dev;
struct hid_device_info *devs, *dev; devs = hid_enumerate(vendorID, productID);
devs = hid_enumerate(0x0, 0x0); dev = devs;
dev = devs; wstring wideSerial;
m_keyboardModel = KeyboardModel::unknown;
while (dev) { if (!serial.empty()) {
for (int i=0; i<(int)SupportedKeyboards.size(); i++) { wchar_t tempSerial[256];
if (dev->vendor_id == SupportedKeyboards[i][0]) { if (mbstowcs(tempSerial, serial.c_str(), 256) < 1) return false;
if (dev->product_id == SupportedKeyboards[i][1]) { wideSerial = wstring(tempSerial);
m_vendorID = dev->vendor_id; }
m_productID = dev->product_id;
m_keyboardModel = (KeyboardModel)SupportedKeyboards[i][2]; while (dev) {
break; for (int i=0; i<(int)SupportedKeyboards.size(); i++) {
} if (dev->vendor_id == SupportedKeyboards[i][0]) {
if (dev->product_id == SupportedKeyboards[i][1]) {
if (!serial.empty() && dev->serial_number != NULL && wideSerial.compare(dev->serial_number) != 0) break; //Serial didn't match
if (dev->serial_number != NULL) {
char buf[256];
wcstombs(buf,dev->serial_number,256);
currentDevice.serialNumber=string(buf);
} }
if (dev->manufacturer_string != NULL)
{
char buf[256];
wcstombs(buf,dev->manufacturer_string,256);
currentDevice.manufacturer = string(buf);
}
if (dev->product_string != NULL)
{
char buf[256];
wcstombs(buf,dev->product_string,256);
currentDevice.product = string(buf);
}
currentDevice.vendorID = dev->vendor_id;
currentDevice.productID = dev->product_id;
currentDevice.model = (KeyboardModel)SupportedKeyboards[i][2];
break;
} }
if (m_keyboardModel != KeyboardModel::unknown) break;
dev = dev->next;
}
hid_free_enumeration(devs);
if (! dev) {
cout<<"Keyboard not found"<<endl;
m_keyboardModel = KeyboardModel::unknown;
hid_exit();
return false;
} }
} }
if (currentDevice.model != KeyboardModel::unknown) break;
dev = dev->next;
}
m_hidHandle = hid_open(m_vendorID, m_productID, NULL); hid_free_enumeration(devs);
if(m_hidHandle == 0) { if (! dev) {
hid_exit(); currentDevice.model = KeyboardModel::unknown;
return false; hid_exit();
} return false;
}
m_isOpen = true; if (wideSerial.empty()) m_hidHandle = hid_open(currentDevice.vendorID, currentDevice.productID, NULL);
return true; else m_hidHandle = hid_open(currentDevice.vendorID, currentDevice.productID, wideSerial.c_str());
if(m_hidHandle == 0) {
hid_exit();
return false;
}
m_isOpen = true;
return true;
#elif defined(libusb) #elif defined(libusb)
if(libusb_init(&m_ctx) < 0) return false; if (libusb_init(&m_ctx) < 0) return false;
if (m_keyboardModel == KeyboardModel::unknown) { libusb_device **devs;
libusb_device **devs; libusb_device *dev = NULL;
ssize_t cnt = libusb_get_device_list(m_ctx, &devs); ssize_t cnt = libusb_get_device_list(m_ctx, &devs);
if(cnt >= 0) { if(cnt >= 0) {
for(ssize_t i = 0; i < cnt; i++) { for(ssize_t i = 0; i < cnt; i++) {
libusb_device *device = devs[i]; libusb_device *device = devs[i];
libusb_device_descriptor desc; libusb_device_descriptor desc;
libusb_get_device_descriptor(device, &desc); libusb_get_device_descriptor(device, &desc);
if (vendorID != 0x0 && desc.idVendor != vendorID) continue;
else if (productID != 0x0 && desc.idProduct != productID) continue;
else if (! serial.empty()) {
if (desc.iSerialNumber <= 0) continue; //Device does not populate serial number
unsigned char buf[256];
if (libusb_open(device, &m_hidHandle) != 0){
m_hidHandle = NULL;
continue;
}
if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iSerialNumber, buf, 256) >= 1 && serial.compare((char*)buf) == 0) {
//Make sure entry is a supported keyboard and get model
for (int i=0; i<(int)SupportedKeyboards.size(); i++) { for (int i=0; i<(int)SupportedKeyboards.size(); i++) {
if (desc.idVendor == SupportedKeyboards[i][0]) { if (desc.idVendor == SupportedKeyboards[i][0]) {
if (desc.idProduct == SupportedKeyboards[i][1]) { if (desc.idProduct == SupportedKeyboards[i][1]) {
m_vendorID = desc.idVendor; if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iManufacturer, buf, 256) >= 1) currentDevice.manufacturer = string((char*)buf);
m_productID = desc.idProduct; if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iProduct, buf, 256) >= 1) currentDevice.product = string((char*)buf);
m_keyboardModel = (KeyboardModel)SupportedKeyboards[i][2]; currentDevice.serialNumber = serial;
currentDevice.vendorID = desc.idVendor;
currentDevice.productID = desc.idProduct;
currentDevice.model = (KeyboardModel)SupportedKeyboards[i][2];
dev = device;
libusb_close(m_hidHandle);
m_hidHandle = NULL;
break; break;
} }
} }
} }
if (m_keyboardModel != KeyboardModel::unknown) break;
} }
libusb_free_device_list(devs, 1); else {
libusb_close(m_hidHandle);
m_hidHandle = NULL;
continue; //Serial number set but doesn't match
}
} }
}
if (m_keyboardModel == KeyboardModel::unknown) { //For the case where serial is not specified, find first supported device
cout<<"Keyboard not found"<<endl; for (int i=0; i<(int)SupportedKeyboards.size(); i++) {
if (desc.idVendor == SupportedKeyboards[i][0]) {
if (desc.idProduct == SupportedKeyboards[i][1]) {
unsigned char buf[256];
if (libusb_open(device, &m_hidHandle) != 0){
m_hidHandle = NULL;
continue;
}
currentDevice.vendorID = desc.idVendor;
currentDevice.productID = desc.idProduct;
currentDevice.model = (KeyboardModel)SupportedKeyboards[i][2];
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.iSerialNumber, buf, 256) >= 1) currentDevice.serialNumber = string((char*)buf);
libusb_close(m_hidHandle);
m_hidHandle=NULL;
break;
}
}
}
if (currentDevice.model != KeyboardModel::unknown) break;
}
libusb_free_device_list(devs, 1);
}
if (currentDevice.model == KeyboardModel::unknown) {
libusb_exit(m_ctx);
m_ctx = NULL;
return false;
}
if (dev == NULL) m_hidHandle = libusb_open_device_with_vid_pid(m_ctx, currentDevice.vendorID, currentDevice.productID);
else libusb_open(dev, &m_hidHandle);
if(m_hidHandle == NULL) {
libusb_exit(m_ctx);
m_ctx = NULL;
return false;
}
if(libusb_kernel_driver_active(m_hidHandle, 1) == 1) {
if(libusb_detach_kernel_driver(m_hidHandle, 1) != 0) {
libusb_exit(m_ctx); libusb_exit(m_ctx);
m_ctx = NULL; m_ctx = NULL;
return false; return false;
} }
m_isKernellDetached = true;
}
m_hidHandle = libusb_open_device_with_vid_pid(m_ctx, m_vendorID, m_productID); if(libusb_claim_interface(m_hidHandle, 1) < 0) {
if(m_hidHandle == 0) { if(m_isKernellDetached==true) {
libusb_exit(m_ctx); libusb_attach_kernel_driver(m_hidHandle, 1);
m_ctx = NULL; m_isKernellDetached = false;
return false;
} }
libusb_exit(m_ctx);
m_ctx = NULL;
return false;
}
if(libusb_kernel_driver_active(m_hidHandle, 1) == 1) { m_isOpen = true;
if(libusb_detach_kernel_driver(m_hidHandle, 1) != 0) { return true;
libusb_exit(m_ctx);
m_ctx = NULL;
return false;
}
m_isKernellDetached = true;
}
if(libusb_claim_interface(m_hidHandle, 1) < 0) {
if(m_isKernellDetached==true) {
libusb_attach_kernel_driver(m_hidHandle, 1);
m_isKernellDetached = false;
}
libusb_exit(m_ctx);
m_ctx = NULL;
return false;
}
m_isOpen = true;
return true;
#endif #endif
return false; return false; //In case neither is defined
}
LedKeyboard::DeviceInfo LedKeyboard::getCurrentDevice()
{
return currentDevice;
} }
bool LedKeyboard::close() { bool LedKeyboard::close() {
@ -202,11 +329,12 @@ bool LedKeyboard::close() {
#if defined(hidapi) #if defined(hidapi)
hid_close(m_hidHandle); hid_close(m_hidHandle);
m_hidHandle = 0; m_hidHandle = NULL;
hid_exit(); hid_exit();
return true; return true;
#elif defined(libusb) #elif defined(libusb)
if (m_hidHandle == NULL) return true;
if(libusb_release_interface(m_hidHandle, 1) != 0) return false; if(libusb_release_interface(m_hidHandle, 1) != 0) return false;
if(m_isKernellDetached==true) { if(m_isKernellDetached==true) {
libusb_attach_kernel_driver(m_hidHandle, 1); libusb_attach_kernel_driver(m_hidHandle, 1);
@ -224,13 +352,12 @@ bool LedKeyboard::close() {
LedKeyboard::KeyboardModel LedKeyboard::getKeyboardModel() { LedKeyboard::KeyboardModel LedKeyboard::getKeyboardModel() {
return m_keyboardModel; return currentDevice.model;
} }
bool LedKeyboard::commit() { bool LedKeyboard::commit() {
byte_buffer_t data; byte_buffer_t data;
switch (m_keyboardModel) { switch (currentDevice.model) {
case KeyboardModel::g213: case KeyboardModel::g213:
break; // Keyboard is non-transactional break; // Keyboard is non-transactional
case KeyboardModel::g410: case KeyboardModel::g410:
@ -268,7 +395,7 @@ bool LedKeyboard::setKeys(KeyValueArray keyValues) {
for (uint8_t i = 0; i < keyValues.size(); i++) { for (uint8_t i = 0; i < keyValues.size(); i++) {
switch(static_cast<LedKeyboard::KeyAddressGroup>(static_cast<uint16_t>(keyValues[i].key) >> 8 )) { switch(static_cast<LedKeyboard::KeyAddressGroup>(static_cast<uint16_t>(keyValues[i].key) >> 8 )) {
case LedKeyboard::KeyAddressGroup::logo: case LedKeyboard::KeyAddressGroup::logo:
switch (m_keyboardModel) { switch (currentDevice.model) {
case LedKeyboard::KeyboardModel::g610: case LedKeyboard::KeyboardModel::g610:
case LedKeyboard::KeyboardModel::g810: case LedKeyboard::KeyboardModel::g810:
if (SortedKeys[0].size() <= 1 && keyValues[i].key == LedKeyboard::Key::logo) if (SortedKeys[0].size() <= 1 && keyValues[i].key == LedKeyboard::Key::logo)
@ -285,7 +412,7 @@ bool LedKeyboard::setKeys(KeyValueArray keyValues) {
if (SortedKeys[1].size() <= 5) SortedKeys[1].push_back(keyValues[i]); if (SortedKeys[1].size() <= 5) SortedKeys[1].push_back(keyValues[i]);
break; break;
case LedKeyboard::KeyAddressGroup::multimedia: case LedKeyboard::KeyAddressGroup::multimedia:
switch (m_keyboardModel) { switch (currentDevice.model) {
case LedKeyboard::KeyboardModel::g610: case LedKeyboard::KeyboardModel::g610:
case LedKeyboard::KeyboardModel::g810: case LedKeyboard::KeyboardModel::g810:
if (SortedKeys[2].size() <= 5) SortedKeys[2].push_back(keyValues[i]); if (SortedKeys[2].size() <= 5) SortedKeys[2].push_back(keyValues[i]);
@ -295,7 +422,7 @@ bool LedKeyboard::setKeys(KeyValueArray keyValues) {
} }
break; break;
case LedKeyboard::KeyAddressGroup::gkeys: case LedKeyboard::KeyAddressGroup::gkeys:
switch (m_keyboardModel) { switch (currentDevice.model) {
case LedKeyboard::KeyboardModel::g910: case LedKeyboard::KeyboardModel::g910:
if (SortedKeys[3].size() <= 9) SortedKeys[3].push_back(keyValues[i]); if (SortedKeys[3].size() <= 9) SortedKeys[3].push_back(keyValues[i]);
break; break;
@ -304,7 +431,7 @@ bool LedKeyboard::setKeys(KeyValueArray keyValues) {
} }
break; break;
case LedKeyboard::KeyAddressGroup::keys: case LedKeyboard::KeyAddressGroup::keys:
switch (m_keyboardModel) { switch (currentDevice.model) {
case LedKeyboard::KeyboardModel::g610: case LedKeyboard::KeyboardModel::g610:
case LedKeyboard::KeyboardModel::g810: case LedKeyboard::KeyboardModel::g810:
case LedKeyboard::KeyboardModel::g910: case LedKeyboard::KeyboardModel::g910:
@ -433,7 +560,7 @@ bool LedKeyboard::setGroupKeys(KeyGroup keyGroup, LedKeyboard::Color color) {
bool LedKeyboard::setAllKeys(LedKeyboard::Color color) { bool LedKeyboard::setAllKeys(LedKeyboard::Color color) {
KeyValueArray keyValues; KeyValueArray keyValues;
switch (m_keyboardModel) { switch (currentDevice.model) {
case KeyboardModel::g213: case KeyboardModel::g213:
for (uint8_t rIndex=0x01; rIndex <= 0x05; rIndex++) if (! setRegion(rIndex, color)) return false; for (uint8_t rIndex=0x01; rIndex <= 0x05; rIndex++) if (! setRegion(rIndex, color)) return false;
return true; return true;
@ -461,7 +588,7 @@ bool LedKeyboard::setAllKeys(LedKeyboard::Color color) {
bool LedKeyboard::setMRKey(uint8_t value) { bool LedKeyboard::setMRKey(uint8_t value) {
LedKeyboard::byte_buffer_t data; LedKeyboard::byte_buffer_t data;
switch (m_keyboardModel) { switch (currentDevice.model) {
case KeyboardModel::g910: case KeyboardModel::g910:
switch (value) { switch (value) {
case 0x00: case 0x00:
@ -481,7 +608,7 @@ bool LedKeyboard::setMRKey(uint8_t value) {
bool LedKeyboard::setMNKey(uint8_t value) { bool LedKeyboard::setMNKey(uint8_t value) {
LedKeyboard::byte_buffer_t data; LedKeyboard::byte_buffer_t data;
switch (m_keyboardModel) { switch (currentDevice.model) {
case KeyboardModel::g910: case KeyboardModel::g910:
switch (value) { switch (value) {
case 0x00: case 0x00:
@ -507,7 +634,7 @@ bool LedKeyboard::setMNKey(uint8_t value) {
bool LedKeyboard::setGKeysMode(uint8_t value) { bool LedKeyboard::setGKeysMode(uint8_t value) {
LedKeyboard::byte_buffer_t data; LedKeyboard::byte_buffer_t data;
switch (m_keyboardModel) { switch (currentDevice.model) {
case KeyboardModel::g910: case KeyboardModel::g910:
switch (value) { switch (value) {
case 0x00: case 0x00:
@ -527,7 +654,7 @@ bool LedKeyboard::setGKeysMode(uint8_t value) {
bool LedKeyboard::setRegion(uint8_t region, LedKeyboard::Color color) { bool LedKeyboard::setRegion(uint8_t region, LedKeyboard::Color color) {
LedKeyboard::byte_buffer_t data; LedKeyboard::byte_buffer_t data;
switch (m_keyboardModel) { switch (currentDevice.model) {
case KeyboardModel::g213: case KeyboardModel::g213:
data = { 0x11, 0xff, 0x0c, 0x3a, region, 0x01, color.red, color.green, color.blue }; data = { 0x11, 0xff, 0x0c, 0x3a, region, 0x01, color.red, color.green, color.blue };
data.resize(20,0x00); data.resize(20,0x00);
@ -542,7 +669,7 @@ bool LedKeyboard::setRegion(uint8_t region, LedKeyboard::Color color) {
bool LedKeyboard::setStartupMode(StartupMode startupMode) { bool LedKeyboard::setStartupMode(StartupMode startupMode) {
byte_buffer_t data; byte_buffer_t data;
switch (m_keyboardModel) { switch (currentDevice.model) {
case KeyboardModel::g213: case KeyboardModel::g213:
case KeyboardModel::g410: case KeyboardModel::g410:
case KeyboardModel::g610: case KeyboardModel::g610:
@ -564,7 +691,7 @@ bool LedKeyboard::setStartupMode(StartupMode startupMode) {
bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part, uint8_t speed, Color color) { bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part, uint8_t speed, Color color) {
uint8_t protocolByte = 0; uint8_t protocolByte = 0;
switch (m_keyboardModel) { switch (currentDevice.model) {
case KeyboardModel::g213: case KeyboardModel::g213:
protocolByte = 0x0c; protocolByte = 0x0c;
if (part == NativeEffectPart::logo) return false; //Does not have logo component if (part == NativeEffectPart::logo) return false; //Does not have logo component
@ -686,7 +813,7 @@ bool LedKeyboard::sendDataInternal(byte_buffer_t &data) {
} }
LedKeyboard::byte_buffer_t LedKeyboard::getKeyGroupAddress(LedKeyboard::KeyAddressGroup keyAddressGroup) { LedKeyboard::byte_buffer_t LedKeyboard::getKeyGroupAddress(LedKeyboard::KeyAddressGroup keyAddressGroup) {
switch (m_keyboardModel) { switch (currentDevice.model) {
case KeyboardModel::g213: case KeyboardModel::g213:
return {}; // Device doesn't support per-key setting return {}; // Device doesn't support per-key setting
case KeyboardModel::g410: case KeyboardModel::g410:

View File

@ -110,6 +110,14 @@ class LedKeyboard {
}; };
typedef struct {
uint16_t vendorID = 0x0;
uint16_t productID = 0x0;
std::string manufacturer = "";
std::string product = "";
std::string serialNumber = "";
KeyboardModel model;
} DeviceInfo;
struct Color { struct Color {
uint8_t red; uint8_t red;
@ -127,10 +135,12 @@ class LedKeyboard {
~LedKeyboard(); ~LedKeyboard();
bool listKeyboards(); std::vector<DeviceInfo> listKeyboards();
bool isOpen(); bool isOpen();
bool open(); bool open();
bool open(uint16_t vendorID, uint16_t productID, std::string serial);
DeviceInfo getCurrentDevice();
bool close(); bool close();
KeyboardModel getKeyboardModel(); KeyboardModel getKeyboardModel();
@ -152,7 +162,6 @@ class LedKeyboard {
bool setNativeEffect(NativeEffect effect, NativeEffectPart part, uint8_t speed, Color color); bool setNativeEffect(NativeEffect effect, NativeEffectPart part, uint8_t speed, Color color);
private: private:
typedef std::vector<unsigned char> byte_buffer_t; typedef std::vector<unsigned char> byte_buffer_t;
@ -191,9 +200,7 @@ class LedKeyboard {
}; };
bool m_isOpen = false; bool m_isOpen = false;
uint16_t m_vendorID = 0; DeviceInfo currentDevice;
uint16_t m_productID = 0;
KeyboardModel m_keyboardModel = KeyboardModel::unknown;
#if defined(hidapi) #if defined(hidapi)
hid_device *m_hidHandle; hid_device *m_hidHandle;

View File

@ -14,6 +14,8 @@ namespace help {
cout<<"--------"<<endl; cout<<"--------"<<endl;
cout<<"Version : "<<VERSION<<endl; cout<<"Version : "<<VERSION<<endl;
cout<<endl; cout<<endl;
cout<<"Usage: "<<cmdName<<" [OPTIONS...] [command] (command arguments)"<<endl;
cout<<"Commands:"<<endl;
cout<<" -a {color}\t\t\t\tSet all keys color"<<endl; cout<<" -a {color}\t\t\t\tSet all keys color"<<endl;
cout<<" -g {keygroup} {color}\t\t\tSet key group color"<<endl; cout<<" -g {keygroup} {color}\t\t\tSet key group color"<<endl;
cout<<" -k {key} {color}\t\t\tSet key color"<<endl; cout<<" -k {key} {color}\t\t\tSet key color"<<endl;
@ -40,13 +42,18 @@ namespace help {
cout<<" --startup-mode {startup mode}\t\tSet startup mode"<<endl; cout<<" --startup-mode {startup mode}\t\tSet startup mode"<<endl;
cout<<endl; cout<<endl;
cout<<" --list-keyboards \t\t\tList connected keyboards"<<endl; cout<<" --list-keyboards \t\t\tList connected keyboards"<<endl;
cout<<" --print-device\t\t\tPrint device information for the keyboard"<<endl;
cout<<endl; cout<<endl;
cout<<" --help\t\t\t\tThis help"<<endl; cout<<" --help\t\t\t\tThis help"<<endl;
cout<<" --help-keys\t\t\t\tHelp for keys in groups"<<endl; cout<<" --help-keys\t\t\t\tHelp for keys in groups"<<endl;
cout<<" --help-effects\t\t\tHelp for native effects"<<endl; cout<<" --help-effects\t\t\tHelp for native effects"<<endl;
cout<<" --help-samples\t\t\tUsage samples"<<endl; cout<<" --help-samples\t\t\tUsage samples"<<endl;
cout<<""<<endl; cout<<endl;
cout<<""<<endl; cout<<"Options:"<<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<<" -ds\t\t\t\t\tDevice serial number, Can be omitted to match the first device found"<<endl;
cout<<"--------"<<endl;
if (cmdName == "g610-led") if (cmdName == "g610-led")
cout<<"color formats :\t\t\t\tII (hex value for intensity)"<<endl; cout<<"color formats :\t\t\t\tII (hex value for intensity)"<<endl;
else else
@ -59,7 +66,7 @@ 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;
cout<<"group values :\t\t\t\tlogo, indicators, fkeys, ... (use --help-keys for more detail)"<<endl; cout<<"group values :\t\t\t\tlogo, indicators, fkeys, ... (use --help-keys for more detail)"<<endl;
cout<<"startup mode :\t\t\t\twave, color"<<endl; cout<<"startup mode :\t\t\t\twave, color"<<endl;
cout<<""<<endl; cout<<endl;
} }
void keys(char *arg0) { void keys(char *arg0) {

View File

@ -216,4 +216,12 @@ namespace utils {
return true; return true;
} }
bool parseUInt16(std::string val, uint16_t &uint16) {
if (val.length() == 1) val = "0" + val;
if (val.length() == 2) val = "0" + val;
if (val.length() == 3) val = "0" + val;
if (val.length() != 4) return false;
uint16 = std::stoul("0x" + val, nullptr, 16);
return true;
}
} }

View File

@ -16,6 +16,7 @@ namespace utils {
bool parseColor(std::string val, LedKeyboard::Color &color); bool parseColor(std::string val, LedKeyboard::Color &color);
bool parseSpeed(std::string val, uint8_t &speed); bool parseSpeed(std::string val, uint8_t &speed);
bool parseUInt8(std::string val, uint8_t &uint8); bool parseUInt8(std::string val, uint8_t &uint8);
bool parseUInt16(std::string val, uint16_t &uint16);
} }

View File

@ -1,3 +1,4 @@
#include <iomanip>
#include <iostream> #include <iostream>
#include <unistd.h> #include <unistd.h>
#include <fstream> #include <fstream>
@ -14,6 +15,27 @@ int commit(LedKeyboard &kbd) {
return 1; return 1;
} }
void printDeviceInfo(LedKeyboard::DeviceInfo device)
{
std::cout<<"Device: "<<device.manufacturer<<" - "<<device.product<<std::endl;
std::cout<<"\tVendor ID: "<<std::hex<<std::setw(4)<<std::setfill('0')<<device.vendorID<<std::endl;
std::cout<<"\tProduct ID: "<<std::hex<<std::setw(4)<<std::setfill('0')<<device.productID<<std::endl;
std::cout<<"\tSerial Number: "<<device.serialNumber<<std::endl;
}
int listKeyboards(LedKeyboard &kbd) {
std::vector<LedKeyboard::DeviceInfo> deviceList = kbd.listKeyboards();
if (deviceList.empty()) return 1;
std::vector<LedKeyboard::DeviceInfo>::iterator iterator;
for (iterator = deviceList.begin(); iterator != deviceList.end(); iterator++) {
LedKeyboard::DeviceInfo device = *iterator;
printDeviceInfo(device);
}
return 0;
}
int setAllKeys(LedKeyboard &kbd, std::string arg2, bool commit = true) { int setAllKeys(LedKeyboard &kbd, std::string arg2, bool commit = true) {
LedKeyboard::Color color; LedKeyboard::Color color;
if (! utils::parseColor(arg2, color)) return 1; if (! utils::parseColor(arg2, color)) return 1;
@ -226,47 +248,71 @@ int pipeProfile(LedKeyboard &kbd) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
if (argc > 1) { if (argc < 2) {
help::usage(argv[0]);
std::string arg = argv[1]; return 1;
if (arg == "--help" || arg == "-h") help::usage(argv[0]);
else if (arg == "--help-keys") help::keys(argv[0]);
else if (arg == "--help-effects") help::effects(argv[0]);
else if (arg == "--help-samples") help::samples(argv[0]);
else {
LedKeyboard kbd;
if (arg == "--list-keyboards") kbd.listKeyboards();
else if (arg == "-c") return commit(kbd);
else if (argc > 2 && arg == "-a") return setAllKeys(kbd, argv[2]);
else if (argc > 3 && arg == "-g") return setGroupKeys(kbd, argv[2], argv[3]);
else if (argc > 3 && arg == "-k") return setKey(kbd, argv[2], argv[3]);
else if (argc > 2 && arg == "-mr") return setMRKey(kbd, argv[2]);
else if (argc > 2 && arg == "-mn") return setMNKey(kbd, argv[2]);
else if (argc > 2 && arg == "-an") return setAllKeys(kbd, argv[2], false);
else if (argc > 3 && arg == "-gn") return setGroupKeys(kbd, argv[2], argv[3], false);
else if (argc > 3 && arg == "-kn") return setKey(kbd, argv[2], argv[3], false);
else if (argc > 3 && arg == "-r") return setRegion(kbd, argv[2], argv[3]);
else if (argc > 2 && arg == "-gkm") return setGKeysMode(kbd, argv[2]);
else if (argc > 2 && arg == "-p") return loadProfile(kbd, argv[2]);
else if (argc > 1 && arg == "-pp") return pipeProfile(kbd);
else if (argc > 5 && arg == "-fx") return setFX(kbd, argv[2], argv[3], argv[4], argv[5]);
else if (argc > 4 && arg == "-fx") return setFX(kbd, argv[2], argv[3], argv[4]);
else if (argc > 2 && arg == "--startup-mode") return setStartupMode(kbd, argv[2]);
else { help::usage(argv[0]); return 1; }
}
return 0;
} }
help::usage(argv[0]); LedKeyboard kbd;
return 1; std::string serial;
uint16_t vendorID = 0x0;
uint16_t productID = 0x0;
int argIndex = 1;
while (argIndex < argc)
{
std::string arg = argv[argIndex];
// Non-Command arguments
if (argc > (argIndex + 1) && arg == "-ds") {
serial = argv[argIndex + 1];
argIndex += 2;
continue;
}
else if (argc > (argIndex + 1) && arg == "-dv"){
if (! utils::parseUInt16(argv[argIndex + 1], vendorID)) return 1;
argIndex += 2;
continue;
}
else if (argc > (argIndex + 1) && arg == "-dp"){
if (! utils::parseUInt16(argv[argIndex + 1], productID)) return 1;
argIndex += 2;
continue;
}
//Commands that do not need to initialize a specific device
if (arg == "--help" || arg == "-h") {help::usage(argv[0]); return 0;}
else if (arg == "--list-keyboards") return listKeyboards(kbd);
else if (arg == "--help-keys") {help::keys(argv[0]); return 0;}
else if (arg == "--help-effects") {help::effects(argv[0]); return 0;}
else if (arg == "--help-samples") {help::samples(argv[0]); return 0;}
//Initialize the device for use
if (!kbd.open(vendorID, productID, serial)) {
std::cout << "Matching or compatible device not found" << std::endl;
return 2;
}
// Command arguments, these will cause parsing to ignore anything beyond the command and its arguments
if (arg == "-c") return commit(kbd);
else if (arg == "--print-device") {printDeviceInfo(kbd.getCurrentDevice()); return 0;}
else if (argc > (argIndex + 1) && arg == "-a") return setAllKeys(kbd, argv[argIndex + 1]);
else if (argc > (argIndex + 2) && arg == "-g") return setGroupKeys(kbd, argv[argIndex + 1], argv[argIndex + 2]);
else if (argc > (argIndex + 2) && arg == "-k") return setKey(kbd, argv[argIndex + 1], argv[argIndex + 2]);
else if (argc > (argIndex + 1) && arg == "-mr") return setMRKey(kbd, argv[argIndex + 1]);
else if (argc > (argIndex + 1) && arg == "-mn") return setMNKey(kbd, argv[argIndex + 1]);
else if (argc > (argIndex + 1) && arg == "-an") return setAllKeys(kbd, argv[argIndex + 1], false);
else if (argc > (argIndex + 2) && arg == "-gn") return setGroupKeys(kbd, argv[argIndex + 1], argv[argIndex + 2], false);
else if (argc > (argIndex + 2) && arg == "-kn") return setKey(kbd, argv[argIndex + 1], argv[argIndex + 2], false);
else if (argc > (argIndex + 2) && arg == "-r") return setRegion(kbd, argv[argIndex + 1], argv[argIndex + 2]);
else if (argc > (argIndex + 1) && arg == "-gkm") return setGKeysMode(kbd, argv[argIndex + 1]);
else if (argc > (argIndex + 1) && arg == "-p") return loadProfile(kbd, argv[argIndex + 1]);
else if (arg == "-pp") return pipeProfile(kbd);
else if (argc > (argIndex + 4) && arg == "-fx") return setFX(kbd, argv[argIndex + 1], argv[argIndex + 2], argv[argIndex + 3], argv[argIndex + 4]);
else if (argc > (argIndex + 3) && arg == "-fx") return setFX(kbd, argv[argIndex + 1], argv[argIndex + 2], argv[argIndex + 3]);
else if (argc > (argIndex + 1) && arg == "--startup-mode") return setStartupMode(kbd, argv[argIndex + 1]);
else { help::usage(argv[0]); return 1; }
}
return 0;
} }