summaryrefslogtreecommitdiff
path: root/ltunify.c
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2013-04-26 00:27:23 +0200
committerPeter Wu <lekensteyn@gmail.com>2013-04-26 00:27:23 +0200
commit7f870c0ca5f27827a411d1ee7a11ef5103432413 (patch)
treeaebbfd73cf7261dfab86f17d8fcfba551f98a67f /ltunify.c
parent1e0054ecacd1e0e781ee5dee277107147dca8c6c (diff)
downloadltunify-7f870c0ca5f27827a411d1ee7a11ef5103432413.tar.gz
ltunify: implement fkeyswap command
Warning: I am sleepy so there may be bugs or ugly code. It is tested and works on a K800 keyboard though (and of course it should abort when trying on my M525 mouse).
Diffstat (limited to 'ltunify.c')
-rw-r--r--ltunify.c75
1 files changed, 74 insertions, 1 deletions
diff --git a/ltunify.c b/ltunify.c
index e972618..0afb3c4 100644
--- a/ltunify.c
+++ b/ltunify.c
@@ -61,6 +61,7 @@ typedef unsigned char u8;
#define REG_ENABLED_NOTIFS 0x00
#define REG_CONNECTION_STATE 0x02
+#define REG_FKEY_FUNC 0x09 /* undocumented */
/* Device Connection and Disconnection (Pairing) */
#define REG_DEVICE_PAIRING 0xB2
#define REG_DEVICE_ACTIVITY 0xB3
@@ -150,6 +151,14 @@ struct val_reg_devpair {
u8 open_lock_timeout; // timeout in seconds, 0 = default (30s)
};
+// Register 0x09 "F Key functions" (undocumented)
+struct val_reg_fkey {
+ u8 _dunno1;
+#define FKEY_SWAP 0x01
+ u8 flags;
+ u8 _dunno2;
+};
+
// Register 0xF1 Version Info (undocumented)
struct val_reg_version {
// v1.v2.xxx
@@ -183,6 +192,7 @@ struct version {
u8 bl_minor;
};
+
#define DEVICES_MAX 6u
struct device {
bool device_present; // whether the device is paired
@@ -213,9 +223,11 @@ static const char * error_messages[0xFF] = {
[0x0d] = "WRONG_PIN_CODE",
};
+#define DEVTYPE_KEYBOARD 0x01
+
static const char * device_type[0x0F] = {
[0x00] = "Unknown",
- [0x01] = "Keyboard",
+ [DEVTYPE_KEYBOARD] = "Keyboard",
[0x02] = "Mouse",
[0x03] = "Numpad",
[0x04] = "Presenter",
@@ -869,6 +881,10 @@ static void print_usage(const char *program_name) {
" unpair idx - Unpair device\n"
" info idx - Show more detailed information for a device\n"
" receiver-info - Show information about the receiver\n"
+" fkeyswap action [nidx] - Control the F key state of a keyboard. Valid\n"
+" actions are: on off status. nidx is an optional numeric\n"
+" device index for a keyboard.\n"
+"\n"
"In the above lines, \"idx\" refers to the device number shown in the\n"
" first column of the list command (between 1 and 6). Alternatively, you\n"
" can use the following names (case-insensitive):\n"
@@ -947,6 +963,19 @@ static int validate_args(int argc, char **argv, char ***argsp, char **hidraw_pat
print_device_types();
return -1;
}
+ } else if (!strcmp(cmd, "fkeyswap")) {
+ if (args_count < 1) {
+ fprintf(stderr, "Missing action, must be one of: on off status\n");
+ return -1;
+ }
+ if (strcmp(args[1], "status") && strcmp(args[1], "on") && strcmp(args[1], "off")) {
+ fprintf(stderr, "Invalid action, must be one of: on off status\n");
+ return -1;
+ }
+ if (args_count >= 2 && !is_numeric_device_index(args[2])) {
+ fprintf(stderr, "Device index must be a number (for a keyboard device)\n");
+ return -1;
+ }
} else {
fprintf(stderr, "Unrecognized command: %s\n", cmd);
return -1;
@@ -1130,6 +1159,50 @@ int main(int argc, char **argv) {
}
} else if (!strcmp(cmd, "receiver-info")) {
get_and_print_recv_fw(fd);
+ } else if (!strcmp(cmd, "fkeyswap")) {
+ u8 device_index;
+ bool fetched_devices = false;
+ const char *dev_index = "keyboard";
+
+ if (args_count >= 2) {
+ dev_index = args[2];
+ }
+
+ device_index = find_device_index_for_type(fd, dev_index, &fetched_devices);
+ if (device_index && !fetched_devices &&
+ !get_device_pair_info(fd, device_index)) {
+ // device not found - reset
+ device_index = 0;
+ }
+ if (!device_index) {
+ fprintf(stderr, "Device %s not found\n", args[1]);
+ } else if (devices[device_index - 1].device_type != DEVTYPE_KEYBOARD) {
+ fprintf(stderr, "fkeyswap works only for keyboards\n");
+ } else {
+ struct hidpp_message msg;
+ struct val_reg_fkey cval = {0};
+ if (!get_short_register(fd, device_index, REG_FKEY_FUNC, NULL, &msg)) {
+ fprintf(stderr, "Unable to check fkey status\n");
+ } else {
+ memcpy(&cval, msg.msg_short.value, sizeof cval);
+ if (!strcmp(args[1], "status")) {
+ printf("F key functions are %sswapped\n", cval.flags & FKEY_SWAP ? "" : "not ");
+ } else {
+ bool is_swap = !strcmp(args[1], "on");
+ if (is_swap) {
+ cval.flags |= FKEY_SWAP;
+ } else {
+ cval.flags &= ~FKEY_SWAP;
+ }
+ if (set_short_register(fd, device_index, REG_FKEY_FUNC, (u8 *) &cval, &msg)) {
+ printf("F key functions are now %s\n",
+ is_swap ? "swapped" : "normal");
+ } else {
+ fprintf(stderr, "Could not change F key functions\n");
+ }
+ }
+ }
+ }
} else {
fprintf(stderr, "Unhandled command: %s\n", cmd);
}