diff options
-rw-r--r-- | .SRCINFO | 20 | ||||
-rw-r--r-- | 99-k290-config.rules | 1 | ||||
-rw-r--r-- | LICENSE.MIT | 19 | ||||
-rw-r--r-- | PKGBUILD | 39 | ||||
-rwxr-xr-x | k290-fnkeyctl.sh | 7 | ||||
-rw-r--r-- | k290_fnkeyctl.cpp | 58 |
6 files changed, 144 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..3cc72fd88c91 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,20 @@ +pkgbase = k290-fnkeyctl + pkgdesc = Logitech K290 Fn-key configuration + pkgver = 1 + pkgrel = 3 + url = https://github.com/milgner/k290-fnkeyctl + arch = i686 + arch = x86_64 + license = MIT + depends = libusb + source = k290_fnkeyctl.cpp + source = 99-k290-config.rules + source = k290-fnkeyctl.sh + source = LICENSE.MIT + sha256sums = 7a2967f1fb89961b823e86d4ad7ad98ebc2421bcd96d02a598825c216a32630a + sha256sums = 53889796bce94b160363b27fe330cb2104bbd85ac28d028c3878747c38bf93ae + sha256sums = 686d674244ffb7a503b25b21ae7dfd4603efa1a480f2f4d754a754b99c79da02 + sha256sums = d30cadbdab051c6447e2113634166c453f101e8d2f47286049a898bf27c884dd + +pkgname = k290-fnkeyctl + diff --git a/99-k290-config.rules b/99-k290-config.rules new file mode 100644 index 000000000000..13cbd598df5d --- /dev/null +++ b/99-k290-config.rules @@ -0,0 +1 @@ +ATTR{idVendor}=="046d", ATTR{idProduct}=="c31f", RUN+="/usr/local/sbin/k290_fnkeyctl" diff --git a/LICENSE.MIT b/LICENSE.MIT new file mode 100644 index 000000000000..590d66f89ee9 --- /dev/null +++ b/LICENSE.MIT @@ -0,0 +1,19 @@ +Copyright (c) 2013 Marcus Ilgner <mail@marcusilgner.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
\ No newline at end of file diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..237483fa305c --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,39 @@ +# Maintainer: Marcus Ilgner <mail@marcusilgner.com> +pkgname=k290-fnkeyctl +pkgver=1 +pkgrel=3 +pkgdesc="Logitech K290 Fn-key configuration" +arch=('i686' 'x86_64') +url="https://github.com/milgner/k290-fnkeyctl" +license=('MIT') +groups=() +depends=('libusb') +source=(k290_fnkeyctl.cpp + 99-k290-config.rules + k290-fnkeyctl.sh + LICENSE.MIT) +sha256sums=(7a2967f1fb89961b823e86d4ad7ad98ebc2421bcd96d02a598825c216a32630a + 53889796bce94b160363b27fe330cb2104bbd85ac28d028c3878747c38bf93ae + 686d674244ffb7a503b25b21ae7dfd4603efa1a480f2f4d754a754b99c79da02 + d30cadbdab051c6447e2113634166c453f101e8d2f47286049a898bf27c884dd) + +build() { + cd "$srcdir" + g++ -std=gnu++0x -lusb-1.0 k290_fnkeyctl.cpp -o k290_fnkeyctl +} + +package() { + cd "$srcdir" + # main binary + mkdir -p "$pkgdir/usr/bin" + cp k290_fnkeyctl "$pkgdir/usr/bin" + # udev script + mkdir -p "$pkgdir/etc/udev/rules.d" + sed -e s/\\/usr\\/local\\/sbin\\//\\/usr\\/bin\\// 99-k290-config.rules > "$pkgdir/etc/udev/rules.d/99-k290-config.rules" + # systemd post-sleep script + mkdir -p "$pkgdir/usr/lib/systemd/system-sleep" + sed -e s/\\/usr\\/local\\/sbin\\//\\/usr\\/bin\\// k290-fnkeyctl.sh > "$pkgdir/usr/lib/systemd/system-sleep/k290-fnkeyctl.sh" + chmod +x "$pkgdir/usr/lib/systemd/system-sleep/k290-fnkeyctl.sh" + mkdir -p "$pkgdir/usr/share/licenses/k290-fnkeyctl" + cp LICENSE.MIT "$pkgdir/usr/share/licenses/k290-fnkeyctl/LICENSE" +} diff --git a/k290-fnkeyctl.sh b/k290-fnkeyctl.sh new file mode 100755 index 000000000000..8b9ed0f2d6b9 --- /dev/null +++ b/k290-fnkeyctl.sh @@ -0,0 +1,7 @@ +#!/bin/bash +case $1/$2 in + post/*) + /usr/local/sbin/k290_fnkeyctl + ;; +esac + diff --git a/k290_fnkeyctl.cpp b/k290_fnkeyctl.cpp new file mode 100644 index 000000000000..c6d010a9c037 --- /dev/null +++ b/k290_fnkeyctl.cpp @@ -0,0 +1,58 @@ +#include <iostream> +#include <memory> +#include <functional> +#include <cstring> + +#include <libusb-1.0/libusb.h> + +#define USB_VENDOR_LOGITECH 0x046d +#define USB_PRODUCT_K290 0xc31f + +std::shared_ptr<libusb_device_handle> getK290Device(std::shared_ptr<libusb_context>& context) { + libusb_device** rawList = nullptr; + auto numDevices = libusb_get_device_list(context.get(), &rawList); + if (0 == numDevices) { + return nullptr; + } + std::shared_ptr<libusb_device*> deviceList(rawList, std::bind(libusb_free_device_list, std::placeholders::_1, 1)); + for (int i = 0; i < numDevices; i++) { + libusb_device_descriptor deviceDescriptor; + auto device = deviceList.get()[i]; + libusb_get_device_descriptor(device, &deviceDescriptor); // always successful since 1.0.16 + if (USB_VENDOR_LOGITECH == deviceDescriptor.idVendor && USB_PRODUCT_K290 == deviceDescriptor.idProduct) { + libusb_device_handle* rawHandle = nullptr; + auto err = libusb_open(device, &rawHandle); + if (0 == err) { + return std::move(std::shared_ptr<libusb_device_handle>(rawHandle, libusb_close)); + } else { + std::cerr << "Could not open device: " << libusb_error_name(err) << std::endl; + } + } + } + return nullptr; +} + +int main(int argc, const char* const argv[]) { + libusb_context* rawUsbCtx = nullptr; + auto err = libusb_init(&rawUsbCtx); + if (0 != err) { + std::cerr << "Could not initialize libusb: " << libusb_error_name(err) << std::endl; + return 1; + } + std::shared_ptr<libusb_context> usbContext(rawUsbCtx, libusb_exit); + std::shared_ptr<libusb_device_handle> device(getK290Device(usbContext)); + if (nullptr == device) { + std::cerr << "Logitech K290 not found on this system" << std::endl; + return 2; + } + bool reset = ((argc > 1) && ((0 == strcmp(argv[1], "-r")) || 0 == strcmp(argv[1], "--reset"))); + err = libusb_control_transfer(device.get(), 0x40, 2, 0x001a, reset ? 0 : 1, nullptr, 0, 1000); + if (0 == err) { + std::cout << "Successfully set function keys to " << (reset ? "default" : "regular") << " behaviour" << std::endl; + return 0; + } else { + std::cerr << "Something went wrong when sending the command: " << libusb_error_name(err) << std::endl; + return 1; + } +} + |