summarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO20
-rw-r--r--99-k290-config.rules1
-rw-r--r--LICENSE.MIT19
-rw-r--r--PKGBUILD39
-rwxr-xr-xk290-fnkeyctl.sh7
-rw-r--r--k290_fnkeyctl.cpp58
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;
+ }
+}
+