From bcdcee88f10bb0d4007458b44f12668fea09fdbd Mon Sep 17 00:00:00 2001 From: MatMoul Date: Sat, 21 Jan 2017 22:45:48 +0100 Subject: [PATCH] Switch to hidapi --- INSTALL.md | 28 ++-- makefile | 56 +++++--- src/classes/Keyboard.cpp | 303 +++++++++++++++++++++++++-------------- src/classes/Keyboard.h | 19 ++- src/main.cpp | 1 - udev/g810-led.rules | 14 +- 6 files changed, 273 insertions(+), 148 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 21bfb55..b637ad4 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -6,21 +6,29 @@ * make ## Dependencies :
-* libusb -* systemd +* hidapi or libusb + +## hidapi vs libusb :
+hidapi is the new implementation but need to be tested.
+hidapi is very more speed than libusb (~20ms vs ~150ms).
+hidapi seem not work on CentOS, writing on hidraw is not allowed.
+hidapi is recommended but if you encounter problem on your system, switch to libusb.
## Installation of dependencies :
ArchLinux :
-`sudo pacman -S git gcc make libusb`
+`sudo pacman -S git gcc make hidapi` (for hidapi)
+`sudo pacman -S git gcc make libusb` (for libusb)
Debian :
-`sudo apt-get install git g++ make libusb-1.0-0-dev`
+`sudo apt-get install git g++ make libhidapi-dev` (for hidapi)
+`sudo apt-get install git g++ make libusb-1.0-0-dev` (for libusb)
Fedora :
-`sudo dnf install git make gcc-c++ libusb-devel`
+`sudo dnf install git make gcc-c++ hidapi-devel` (for hidapi)
+`sudo dnf install git make gcc-c++ libusbx-devel` (for libusb)
## Installation :
`git clone https://github.com/MatMoul/g810-led.git`
`cd g810-led`
-`make`
+`make` or `make LIB=libusb`
`sudo make install`
## Update :
@@ -30,8 +38,8 @@ Same as install, but your profile and reboot files are preserved.
`sudo make uninstall`
## Boot profiles :
-g810-led has 2 systemd units (g810-led and g810-led-reboot).
+If your system use systemd, g810-led has 2 systemd units (g810-led and g810-led-reboot).
These 2 units set the keyboard profile on boot and reboot.
-Profiles are stored in /etc/g810 :
-* /etc/g810/profile -* /etc/g810/reboot +Profiles are stored in /etc/g810-led :
+* /etc/g810-led/profile +* /etc/g810-led/reboot diff --git a/makefile b/makefile index 917f0bc..46fd1cc 100644 --- a/makefile +++ b/makefile @@ -1,16 +1,23 @@ CC=g++ CFLAGS=-Wall -O2 -std=gnu++11 -LDFLAGS=-lusb-1.0 +LIB?=hidapi +ifeq ($(LIB),libusb) + CPPFLAGS=-Dlibusb + LDFLAGS=-lusb-1.0 +else + CPPFLAGS=-Dhidapi + LDFLAGS=-lhidapi-hidraw +endif PROGN=g810-led SYSTEMDDIR?=/usr/lib/systemd -.PHONY: all debug clean +.PHONY: all debug clean install uninstall all: bin/$(PROGN) bin/$(PROGN): src/main.cpp src/helpers/*.cpp src/helpers/*.h src/classes/*.cpp src/classes/*.h @mkdir -p bin - $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) + $(CC) $(CPPFLAGS) $(CFLAGS) $^ -o $@ $(LDFLAGS) debug: CFLAGS += -g -Wextra -pedantic debug: bin/$(PROGN) @@ -20,36 +27,43 @@ clean: install: @install -m 755 -d \ - $(DESTDIR)/etc/$(PROGN)/samples \ $(DESTDIR)/etc/udev/rules.d \ - $(DESTDIR)$(SYSTEMDDIR)/system \ $(DESTDIR)/usr/bin @cp bin/$(PROGN) $(DESTDIR)/usr/bin @test -s $(DESTDIR)/usr/bin/g410-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g410-led @test -s $(DESTDIR)/usr/bin/g610-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g610-led @test -s $(DESTDIR)/usr/bin/g910-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g910-led + @cp udev/$(PROGN).rules $(DESTDIR)/etc/udev/rules.d - @cp sample_profiles/* $(DESTDIR)/etc/$(PROGN)/samples - @test -s $(DESTDIR)/etc/$(PROGN)/profile || cp $(DESTDIR)/etc/$(PROGN)/samples/group_keys $(DESTDIR)/etc/$(PROGN)/profile - @test -s $(DESTDIR)/etc/$(PROGN)/reboot || cp $(DESTDIR)/etc/$(PROGN)/samples/all_off $(DESTDIR)/etc/$(PROGN)/reboot - @cp systemd/$(PROGN).service $(DESTDIR)$(SYSTEMDDIR)/system - @cp systemd/$(PROGN)-reboot.service $(DESTDIR)$(SYSTEMDDIR)/system @udevadm control --reload-rules - @systemctl daemon-reload - @systemctl start $(PROGN) - @systemctl enable $(PROGN) - @systemctl enable $(PROGN)-reboot - + + @test -s /usr/bin/systemd-run && \ + install -m 755 -d \ + $(DESTDIR)/etc/$(PROGN)/samples \ + $(DESTDIR)$(SYSTEMDDIR)/system && \ + cp sample_profiles/* $(DESTDIR)/etc/$(PROGN)/samples && \ + test -s $(DESTDIR)/etc/$(PROGN)/profile || cp $(DESTDIR)/etc/$(PROGN)/samples/group_keys $(DESTDIR)/etc/$(PROGN)/profile && \ + test -s $(DESTDIR)/etc/$(PROGN)/reboot || cp $(DESTDIR)/etc/$(PROGN)/samples/all_off $(DESTDIR)/etc/$(PROGN)/reboot && \ + cp systemd/$(PROGN).service $(DESTDIR)$(SYSTEMDDIR)/system && \ + cp systemd/$(PROGN)-reboot.service $(DESTDIR)$(SYSTEMDDIR)/system && \ + systemctl daemon-reload && \ + systemctl start $(PROGN) && \ + systemctl enable $(PROGN) && \ + systemctl enable $(PROGN)-reboot + uninstall: - @systemctl disable $(PROGN) - @systemctl disable $(PROGN)-reboot - @rm $(SYSTEMDDIR)/system/$(PROGN).service - @rm $(SYSTEMDDIR)/system/$(PROGN)-reboot.service - @systemctl daemon-reload + @test -s /usr/bin/systemd-run && \ + systemctl disable $(PROGN) && \ + systemctl disable $(PROGN)-reboot && \ + rm $(SYSTEMDDIR)/system/$(PROGN).service && \ + rm $(SYSTEMDDIR)/system/$(PROGN)-reboot.service && \ + systemctl daemon-reload && \ + rm -R /etc/$(PROGN) + @rm /usr/bin/g410-led @rm /usr/bin/g610-led @rm /usr/bin/g910-led @rm /usr/bin/$(PROGN) - @rm -R /etc/$(PROGN) + @rm /etc/udev/rules.d/$(PROGN).rules @udevadm control --reload-rules diff --git a/src/classes/Keyboard.cpp b/src/classes/Keyboard.cpp index 1a37ca1..808ddd5 100644 --- a/src/classes/Keyboard.cpp +++ b/src/classes/Keyboard.cpp @@ -4,7 +4,11 @@ #include #include -#include "libusb-1.0/libusb.h" +#if defined(hidapi) + #include "hidapi/hidapi.h" +#elif defined(libusb) + #include "libusb-1.0/libusb.h" +#endif using namespace std; @@ -17,61 +21,38 @@ LedKeyboard::~LedKeyboard() { bool LedKeyboard::listKeyboards() { - libusb_context *ctx = NULL; - if(libusb_init(&m_ctx) < 0) return false; - - libusb_device **devs; - ssize_t cnt = libusb_get_device_list(ctx, &devs); - if(cnt >= 0) { - for(ssize_t i = 0; i < cnt; i++) { - libusb_device *device = devs[i]; - libusb_device_descriptor desc = { - 0, // bLength - 0, // bDescriptorType - 0, // bcdUSB - 0, // bDeviceClass - 0, // bDeviceSubClass - 0, // bDeviceProtocol - 0, // bMaxPacketSize0 - 0, // idVendor - 0, // idProduct - 0, // bcdDevice - 0, // iManufacturer - 0, // iProduct - 0, // iSerialNumber - 0 // bNumConfigurations - }; - libusb_get_device_descriptor(device, &desc); + #if defined(hidapi) + if (hid_init() < 0) return false; + + struct hid_device_info *devs, *dev; + devs = hid_enumerate(0x0, 0x0); + dev = devs; + while (dev) { for (int i=0; i<(int)SuportedKeyboards.size(); i++) { - if (desc.idVendor == SuportedKeyboards[i][0]) { - if (desc.idProduct == SuportedKeyboards[i][1]) { - cout<<"0x"<vendor_id == SuportedKeyboards[i][0]) { + if (dev->product_id == SuportedKeyboards[i][1]) { + cout<<"0x"<vendor_id \ + <<" 0x"<product_id \ + <<" "<serial_number \ + <<" "<path<<" "; + dev = dev->next; + cout<serial_number<<" "<path<next; } - libusb_free_device_list(devs, 1); - libusb_exit(m_ctx); - } else return false; - - return true; -} - - -bool LedKeyboard::isOpen() { - return m_isOpen; -} - -bool LedKeyboard::open() { - if (m_isOpen) return true; - - if(libusb_init(&m_ctx) < 0) return false; - - if (m_keyboardModel == KeyboardModel::unknown) { + hid_free_enumeration(devs); + + hid_exit(); + #elif defined(libusb) + libusb_context *ctx = NULL; + if(libusb_init(&m_ctx) < 0) return false; + libusb_device **devs; - ssize_t cnt = libusb_get_device_list(m_ctx, &devs); + ssize_t cnt = libusb_get_device_list(ctx, &devs); if(cnt >= 0) { for(ssize_t i = 0; i < cnt; i++) { libusb_device *device = devs[i]; @@ -95,72 +76,170 @@ bool LedKeyboard::open() { for (int i=0; i<(int)SuportedKeyboards.size(); i++) { if (desc.idVendor == SuportedKeyboards[i][0]) { if (desc.idProduct == SuportedKeyboards[i][1]) { - m_vendorID = desc.idVendor; - m_productID = desc.idProduct; + cout<<"0x"<vendor_id == SuportedKeyboards[i][0]) { + if (dev->product_id == SuportedKeyboards[i][1]) { + m_vendorID = dev->vendor_id; + m_productID = dev->product_id; m_keyboardModel = (KeyboardModel)SuportedKeyboards[i][2]; break; } } } - if (m_keyboardModel != KeyboardModel::unknown) break; - + dev = dev->next; + } + hid_free_enumeration(devs); + + if (! dev) { + cout<<"Keyboard not found"<= 0) { + for(ssize_t i = 0; i < cnt; i++) { + libusb_device *device = devs[i]; + libusb_device_descriptor desc = { + 0, // bLength + 0, // bDescriptorType + 0, // bcdUSB + 0, // bDeviceClass + 0, // bDeviceSubClass + 0, // bDeviceProtocol + 0, // bMaxPacketSize0 + 0, // idVendor + 0, // idProduct + 0, // bcdDevice + 0, // iManufacturer + 0, // iProduct + 0, // iSerialNumber + 0 // bNumConfigurations + }; + libusb_get_device_descriptor(device, &desc); + for (int i=0; i<(int)SuportedKeyboards.size(); i++) { + if (desc.idVendor == SuportedKeyboards[i][0]) { + if (desc.idProduct == SuportedKeyboards[i][1]) { + m_vendorID = desc.idVendor; + m_productID = desc.idProduct; + m_keyboardModel = (KeyboardModel)SuportedKeyboards[i][2]; + break; + } + } + } + + if (m_keyboardModel != KeyboardModel::unknown) break; + + } + libusb_free_device_list(devs, 1); + } + } + + if (m_keyboardModel == KeyboardModel::unknown) { + cout<<"Keyboard not found"< 20) r = libusb_control_transfer(m_hidHandle, 0x21, 0x09, 0x0212, 1, const_cast(data.data()), data.size(), 2000); - else r = libusb_control_transfer(m_hidHandle, 0x21, 0x09, 0x0211, 1, const_cast(data.data()), data.size(), 2000); - usleep(1000); - if (r < 0) return false; - unsigned char buffer[64]; - int len = 0; - r = libusb_interrupt_transfer(m_hidHandle, 0x82, buffer, sizeof(buffer), &len, 1); + + if (data.size() > 0) { + #if defined(hidapi) + data.insert(data.begin(), 0x00); + if (hid_write(m_hidHandle, const_cast(data.data()), data.size()) < 0) { + std::cout<<"Error: Can not write to hidraw, try with the libusb version"<(data2.data()), data2.size(), 0); + #elif defined(libusb) + int r; + if (data.size() > 20) r = libusb_control_transfer(m_hidHandle, 0x21, 0x09, 0x0212, 1, const_cast(data.data()), data.size(), 2000); + else r = libusb_control_transfer(m_hidHandle, 0x21, 0x09, 0x0211, 1, const_cast(data.data()), data.size(), 2000); + usleep(1000); + if (r < 0) return false; + unsigned char buffer[64]; + int len = 0; + r = libusb_interrupt_transfer(m_hidHandle, 0x82, buffer, sizeof(buffer), &len, 1); + #endif + } + return true; } diff --git a/src/classes/Keyboard.h b/src/classes/Keyboard.h index 8aa57fb..b59343f 100644 --- a/src/classes/Keyboard.h +++ b/src/classes/Keyboard.h @@ -4,7 +4,11 @@ #include #include -#include "libusb-1.0/libusb.h" +#if defined(hidapi) + #include "hidapi/hidapi.h" +#elif defined(libusb) + #include "libusb-1.0/libusb.h" +#endif class LedKeyboard { @@ -180,15 +184,20 @@ class LedKeyboard { }; bool m_isOpen = false; - bool m_isKernellDetached = false; uint16_t m_vendorID = 0; uint16_t m_productID = 0; KeyboardModel m_keyboardModel = KeyboardModel::unknown; - libusb_device_handle *m_hidHandle; - libusb_context *m_ctx = NULL; + + #if defined(hidapi) + hid_device *m_hidHandle; + #elif defined(libusb) + bool m_isKernellDetached = false; + libusb_device_handle *m_hidHandle; + libusb_context *m_ctx = NULL; + #endif - bool sendDataInternal(const byte_buffer_t &data); + bool sendDataInternal(byte_buffer_t &data); byte_buffer_t getKeyGroupAddress(KeyAddressGroup keyAddressGroup); }; diff --git a/src/main.cpp b/src/main.cpp index c33047f..c582bc9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -186,7 +186,6 @@ int pipeProfile(LedKeyboard &kbd) { int main(int argc, char **argv) { - if (argc > 1) { std::string arg = argv[1]; diff --git a/udev/g810-led.rules b/udev/g810-led.rules index e4c5401..8cb72ec 100644 --- a/udev/g810-led.rules +++ b/udev/g810-led.rules @@ -1,7 +1,7 @@ -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c331", MODE="660", GROUP="users" -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c337", MODE="660", GROUP="users" -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c330", MODE="660", GROUP="users" -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c333", MODE="660", GROUP="users" -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c338", MODE="660", GROUP="users" -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c32b", MODE="660", GROUP="users" -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c335", MODE="660", GROUP="users" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c331", MODE="666" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c337", MODE="666" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c330", MODE="666" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c333", MODE="666" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c338", MODE="666" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c32b", MODE="666" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c335", MODE="666"