diff --git a/src/classes/Keyboard.cpp b/src/classes/Keyboard.cpp index 7dae4fd..e422010 100644 --- a/src/classes/Keyboard.cpp +++ b/src/classes/Keyboard.cpp @@ -5,6 +5,7 @@ #include #if defined(hidapi) + #include #include "hidapi/hidapi.h" #elif defined(libusb) #include "libusb-1.0/libusb.h" @@ -20,38 +21,57 @@ LedKeyboard::~LedKeyboard() { } -bool LedKeyboard::listKeyboards() { +vector LedKeyboard::listKeyboards() { + vector deviceList; + #if defined(hidapi) - if (hid_init() < 0) return false; + if (hid_init() < 0) return deviceList; struct hid_device_info *devs, *dev; devs = hid_enumerate(0x0, 0x0); dev = devs; while (dev) { - for (int i=0; i<(int)SupportedKeyboards.size(); i++) { + for (size_t i=0; ivendor_id == SupportedKeyboards[i][0]) { if (dev->product_id == SupportedKeyboards[i][1]) { - cout<<"0x"<vendor_id \ - <<" 0x"<product_id \ - <<" "<serial_number \ - <<" "<path<<" "; + DeviceInfo deviceInfo; + deviceInfo.vendorID=dev->vendor_id; + deviceInfo.productID=dev->product_id; + + 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; - cout<serial_number<<" "<path<next; + if (dev != NULL) dev = dev->next; } hid_free_enumeration(devs); - hid_exit(); - return true; #elif defined(libusb) libusb_context *ctx = NULL; - if(libusb_init(&m_ctx) < 0) return false; + if(libusb_init(&m_ctx) < 0) return deviceList; libusb_device **devs; ssize_t cnt = libusb_get_device_list(ctx, &devs); @@ -62,20 +82,37 @@ bool LedKeyboard::listKeyboards() { for (int i=0; i<(int)SupportedKeyboards.size(); i++) { if (desc.idVendor == SupportedKeyboards[i][0]) { if (desc.idProduct == SupportedKeyboards[i][1]) { - cout<<"0x"<= 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; } } } } libusb_free_device_list(devs, 1); + + if (m_hidHandle != NULL) { + libusb_close(m_hidHandle); + m_hidHandle = NULL; + } libusb_exit(m_ctx); - return true; + m_ctx = NULL; #endif - return false; + return deviceList; } @@ -86,114 +123,204 @@ bool LedKeyboard::isOpen() { bool LedKeyboard::open() { 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 (hid_init() < 0) return false; - - if (m_keyboardModel == KeyboardModel::unknown) { - struct hid_device_info *devs, *dev; - devs = hid_enumerate(0x0, 0x0); - dev = devs; - m_keyboardModel = KeyboardModel::unknown; - while (dev) { - for (int i=0; i<(int)SupportedKeyboards.size(); i++) { - if (dev->vendor_id == SupportedKeyboards[i][0]) { - if (dev->product_id == SupportedKeyboards[i][1]) { - m_vendorID = dev->vendor_id; - m_productID = dev->product_id; - m_keyboardModel = (KeyboardModel)SupportedKeyboards[i][2]; - break; - } + if (hid_init() < 0) return false; + + struct hid_device_info *devs, *dev; + devs = hid_enumerate(vendorID, productID); + dev = devs; + wstring wideSerial; + + if (!serial.empty()) { + wchar_t tempSerial[256]; + if (mbstowcs(tempSerial, serial.c_str(), 256) < 1) return false; + wideSerial = wstring(tempSerial); + } + + while (dev) { + 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"<next; + } + + hid_free_enumeration(devs); + + if (! dev) { + currentDevice.model = KeyboardModel::unknown; + hid_exit(); + return false; + } + + if (wideSerial.empty()) m_hidHandle = hid_open(currentDevice.vendorID, currentDevice.productID, NULL); + 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) - if(libusb_init(&m_ctx) < 0) return false; + if (libusb_init(&m_ctx) < 0) return false; - if (m_keyboardModel == KeyboardModel::unknown) { - libusb_device **devs; - ssize_t cnt = libusb_get_device_list(m_ctx, &devs); - if(cnt >= 0) { - for(ssize_t i = 0; i < cnt; i++) { - libusb_device *device = devs[i]; - libusb_device_descriptor desc; - libusb_get_device_descriptor(device, &desc); + libusb_device **devs; + libusb_device *dev = NULL; + ssize_t cnt = libusb_get_device_list(m_ctx, &devs); + if(cnt >= 0) { + for(ssize_t i = 0; i < cnt; i++) { + libusb_device *device = devs[i]; + libusb_device_descriptor 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++) { if (desc.idVendor == SupportedKeyboards[i][0]) { if (desc.idProduct == SupportedKeyboards[i][1]) { - m_vendorID = desc.idVendor; - m_productID = desc.idProduct; - m_keyboardModel = (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); + 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; } } } - 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 + } } + + //For the case where serial is not specified, find first supported device + 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 (m_keyboardModel == KeyboardModel::unknown) { - cout<<"Keyboard not found"<(static_cast(keyValues[i].key) >> 8 )) { case LedKeyboard::KeyAddressGroup::logo: - switch (m_keyboardModel) { + switch (currentDevice.model) { case LedKeyboard::KeyboardModel::g610: case LedKeyboard::KeyboardModel::g810: 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]); break; case LedKeyboard::KeyAddressGroup::multimedia: - switch (m_keyboardModel) { + switch (currentDevice.model) { case LedKeyboard::KeyboardModel::g610: case LedKeyboard::KeyboardModel::g810: if (SortedKeys[2].size() <= 5) SortedKeys[2].push_back(keyValues[i]); @@ -295,7 +422,7 @@ bool LedKeyboard::setKeys(KeyValueArray keyValues) { } break; case LedKeyboard::KeyAddressGroup::gkeys: - switch (m_keyboardModel) { + switch (currentDevice.model) { case LedKeyboard::KeyboardModel::g910: if (SortedKeys[3].size() <= 9) SortedKeys[3].push_back(keyValues[i]); break; @@ -304,7 +431,7 @@ bool LedKeyboard::setKeys(KeyValueArray keyValues) { } break; case LedKeyboard::KeyAddressGroup::keys: - switch (m_keyboardModel) { + switch (currentDevice.model) { case LedKeyboard::KeyboardModel::g610: case LedKeyboard::KeyboardModel::g810: case LedKeyboard::KeyboardModel::g910: @@ -433,7 +560,7 @@ bool LedKeyboard::setGroupKeys(KeyGroup keyGroup, LedKeyboard::Color color) { bool LedKeyboard::setAllKeys(LedKeyboard::Color color) { KeyValueArray keyValues; - switch (m_keyboardModel) { + switch (currentDevice.model) { case KeyboardModel::g213: for (uint8_t rIndex=0x01; rIndex <= 0x05; rIndex++) if (! setRegion(rIndex, color)) return false; return true; @@ -461,7 +588,7 @@ bool LedKeyboard::setAllKeys(LedKeyboard::Color color) { bool LedKeyboard::setMRKey(uint8_t value) { LedKeyboard::byte_buffer_t data; - switch (m_keyboardModel) { + switch (currentDevice.model) { case KeyboardModel::g910: switch (value) { case 0x00: @@ -481,7 +608,7 @@ bool LedKeyboard::setMRKey(uint8_t value) { bool LedKeyboard::setMNKey(uint8_t value) { LedKeyboard::byte_buffer_t data; - switch (m_keyboardModel) { + switch (currentDevice.model) { case KeyboardModel::g910: switch (value) { case 0x00: @@ -507,7 +634,7 @@ bool LedKeyboard::setMNKey(uint8_t value) { bool LedKeyboard::setGKeysMode(uint8_t value) { LedKeyboard::byte_buffer_t data; - switch (m_keyboardModel) { + switch (currentDevice.model) { case KeyboardModel::g910: switch (value) { case 0x00: @@ -527,7 +654,7 @@ bool LedKeyboard::setGKeysMode(uint8_t value) { bool LedKeyboard::setRegion(uint8_t region, LedKeyboard::Color color) { LedKeyboard::byte_buffer_t data; - switch (m_keyboardModel) { + switch (currentDevice.model) { case KeyboardModel::g213: data = { 0x11, 0xff, 0x0c, 0x3a, region, 0x01, color.red, color.green, color.blue }; data.resize(20,0x00); @@ -542,7 +669,7 @@ bool LedKeyboard::setRegion(uint8_t region, LedKeyboard::Color color) { bool LedKeyboard::setStartupMode(StartupMode startupMode) { byte_buffer_t data; - switch (m_keyboardModel) { + switch (currentDevice.model) { case KeyboardModel::g213: case KeyboardModel::g410: case KeyboardModel::g610: @@ -564,7 +691,7 @@ bool LedKeyboard::setStartupMode(StartupMode startupMode) { bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part, uint8_t speed, Color color) { uint8_t protocolByte = 0; - switch (m_keyboardModel) { + switch (currentDevice.model) { case KeyboardModel::g213: protocolByte = 0x0c; 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) { - switch (m_keyboardModel) { + switch (currentDevice.model) { case KeyboardModel::g213: return {}; // Device doesn't support per-key setting case KeyboardModel::g410: diff --git a/src/classes/Keyboard.h b/src/classes/Keyboard.h index d99adda..b87698d 100644 --- a/src/classes/Keyboard.h +++ b/src/classes/Keyboard.h @@ -109,7 +109,15 @@ class LedKeyboard { ctrl_right, shift_right, alt_right, win_right }; - + + typedef struct { + uint16_t vendorID = 0x0; + uint16_t productID = 0x0; + std::string manufacturer = ""; + std::string product = ""; + std::string serialNumber = ""; + KeyboardModel model; + } DeviceInfo; struct Color { uint8_t red; @@ -127,10 +135,12 @@ class LedKeyboard { ~LedKeyboard(); - bool listKeyboards(); + std::vector listKeyboards(); bool isOpen(); bool open(); + bool open(uint16_t vendorID, uint16_t productID, std::string serial); + DeviceInfo getCurrentDevice(); bool close(); KeyboardModel getKeyboardModel(); @@ -152,7 +162,6 @@ class LedKeyboard { bool setNativeEffect(NativeEffect effect, NativeEffectPart part, uint8_t speed, Color color); - private: typedef std::vector byte_buffer_t; @@ -191,9 +200,7 @@ class LedKeyboard { }; bool m_isOpen = false; - uint16_t m_vendorID = 0; - uint16_t m_productID = 0; - KeyboardModel m_keyboardModel = KeyboardModel::unknown; + DeviceInfo currentDevice; #if defined(hidapi) hid_device *m_hidHandle;