Skip to content

Instantly share code, notes, and snippets.

Created May 29, 2016 16:29
Show Gist options
  • Save anonymous/0eaa66d0e0f94817232f778591de3717 to your computer and use it in GitHub Desktop.
Save anonymous/0eaa66d0e0f94817232f778591de3717 to your computer and use it in GitHub Desktop.
Invert fn keys for Logitech K81x series (Linux)
/*
* Copyright 2012 Mario Scholz <[email protected]>
*
* based on pairing_tool.c from Benjamin Tissoires <[email protected]>
* see also https://lkml.org/lkml/2011/9/22/367
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/input.h>
#include <linux/hidraw.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#define HID_VENDOR_ID_LOGITECH (__u32)0x046d
#define HID_DEVICE_ID_K810 (__s16)0xb319
#define HID_DEVICE_ID_K811 (__s16)0xb317
const char k810_seq_fkeys_on[] = {0x10, 0xff, 0x06, 0x15, 0x00, 0x00, 0x00};
const char k810_seq_fkeys_off[] = {0x10, 0xff, 0x06, 0x15, 0x01, 0x00, 0x00};
const char opt_on[] = "on";
const char opt_off[] = "off";
void send(const int fd, const char * buf, const int len)
{
int res;
/* Send sequence to the Device */
res = write(fd, buf, len);
if (res < 0)
{
printf("Error: %d\n", errno);
perror("write");
}
else if (res == len)
{
// printf("Configuration sent.\n");
}
else
{
errno = ENOMEM;
printf("write: %d were written instead of %ld.\n", res, len);
}
}
int main(int argc, char **argv)
{
int fd;
int res;
struct hidraw_devinfo info;
const char * seq;
char *dev = NULL;
int flag_fkeys = 1;
int c;
if (argc < 5)
{
printf("Logitech K810 Keyboard Configurator (by trial-n-error)\n\n");
printf("Usage: %s -d /dev/hidraw{0,1,...} -f {on|off}:\n\n", argv[0]);
printf("-d /dev/hidrawX\n"
" Path to hidraw device. Determine by e.g.:\n"
" ls /sys/class/hidraw/hidraw*/device/uevent\n"
" and/or\n"
" cat /sys/class/hidraw/hidraw*/device/uevent\n");
printf("-f <on|off>\n"
" To enable direct access to F-keys.\n");
printf("\n");
}
while ((c = getopt (argc, argv, "d:f:")) != -1)
{
switch (c)
{
case 'd':
dev = optarg;
break;
case 'f':
if (strcmp(opt_on, optarg) == 0)
{
flag_fkeys = 1;
}
else if (strcmp(opt_off, optarg) == 0)
{
flag_fkeys = 0;
}
else
{
fprintf (stderr, "Option -%c requires argument '%s' or '%s'.\n", optopt, opt_on, opt_off);
return 1;
}
break;
case '?':
if (optopt == 'f')
{
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
}
else if (isprint (optopt))
{
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
}
else
{
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
}
return 1;
default:
abort ();
}
}
/* Open the Device with non-blocking reads. */
fd = open(dev, O_RDWR|O_NONBLOCK);
if (fd < 0)
{
perror("Unable to open device");
return 1;
}
/* Get Raw Info */
res = ioctl(fd, HIDIOCGRAWINFO, &info);
if (res < 0)
{
perror("error while getting info from device");
fprintf(stderr,"%d", res);
return 1;
}
if ((info.bustype == BUS_BLUETOOTH &&
info.vendor == HID_VENDOR_ID_LOGITECH) &&
(info.product == HID_DEVICE_ID_K811 ||
info.product == HID_DEVICE_ID_K810))
{
if (flag_fkeys)
{
send(fd, k810_seq_fkeys_on, sizeof(k810_seq_fkeys_on));
}
else
{
send(fd, k810_seq_fkeys_off, sizeof(k810_seq_fkeys_off));
}
}
else
{
errno = EPERM;
perror("The given device is not a supported "
"Logitech keyboard");
close(fd);
return 1;
}
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment