diff options
author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2024-12-30 18:22:41 +0100 |
---|---|---|
committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2024-12-30 18:22:41 +0100 |
commit | ba9f12810f7dc4969ac175f6e959d5fe6407747d (patch) | |
tree | f4039e46985d56bac471bd8568f96b159a92b2ae /rust/qmk-hid-com/src_c | |
parent | feat(src): Make usable (diff) | |
download | qmk_layout-ba9f12810f7dc4969ac175f6e959d5fe6407747d.zip |
feat(treewide): Migrate the Unicode handling to a custom c program, that works via rawhid
Diffstat (limited to '')
-rwxr-xr-x | rust/qmk-hid-com/src_c/build.sh | 18 | ||||
-rw-r--r-- | rust/qmk-hid-com/src_c/meson.build | 51 | ||||
-rw-r--r-- | rust/qmk-hid-com/src_c/protocol/meson.build | 37 | ||||
-rw-r--r-- | rust/qmk-hid-com/src_c/protocol/virtual-keyboard-unstable-v1.xml | 113 | ||||
-rw-r--r-- | rust/qmk-hid-com/src_c/src/error.c | 20 | ||||
-rw-r--r-- | rust/qmk-hid-com/src_c/src/error.h | 1 | ||||
-rw-r--r-- | rust/qmk-hid-com/src_c/src/hid/hid.c | 83 | ||||
-rw-r--r-- | rust/qmk-hid-com/src_c/src/hid/hid.h | 5 | ||||
-rw-r--r-- | rust/qmk-hid-com/src_c/src/keyboard/keyboard.c | 135 | ||||
-rw-r--r-- | rust/qmk-hid-com/src_c/src/keyboard/keyboard.h | 17 | ||||
-rw-r--r-- | rust/qmk-hid-com/src_c/src/keyboard/virtual-keyboard-unstable-v1-client-protocol.h | 280 | ||||
-rw-r--r-- | rust/qmk-hid-com/src_c/src/main.c | 28 |
12 files changed, 788 insertions, 0 deletions
diff --git a/rust/qmk-hid-com/src_c/build.sh b/rust/qmk-hid-com/src_c/build.sh new file mode 100755 index 0000000..de615f8 --- /dev/null +++ b/rust/qmk-hid-com/src_c/build.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env sh + +# Source: https://mesonbuild.com/Builtin-options.html +# Use gcc's wrappers to support lto +CC="gcc" AR="gcc-ar" RANLIB="gcc-ranlib" meson setup build_release \ + -Dbuildtype=release \ + -Ddebug=false \ + -Doptimization=3 \ + -Dstrip=true \ + -Dwarning_level=everything \ + -Dwerror=true \ + -Db_lundef=true \ + -Db_lto=true \ + -Db_ndebug=false \ + -Db_pgo=generate \ + -Db_staticpic=true \ + -Db_pie=false \ + -Dc_std=gnu2x diff --git a/rust/qmk-hid-com/src_c/meson.build b/rust/qmk-hid-com/src_c/meson.build new file mode 100644 index 0000000..9e8357f --- /dev/null +++ b/rust/qmk-hid-com/src_c/meson.build @@ -0,0 +1,51 @@ +# This is heavily based on `wtype` + +project( + 'qmk-unicode-type', 'c', + version: '0.1', + license: 'GPL-3.0-or-later', + default_options : [ + 'buildtype=release', + 'default_library=static' + ], +) + +git = find_program('git', native: true, required: false) + +if not git.found() + add_project_arguments('-DVERSION="@0@"'.format(meson.project_version()), language: 'c') +else + git_commit_hash = run_command([git.full_path(), 'describe', '--always', '--tags'], check: true).stdout().strip() + git_branch = run_command([git.full_path(), 'rev-parse', '--abbrev-ref', 'HEAD'], check: true).stdout().strip() + version = '"@0@ (" __DATE__ ", branch \'@1@\')"'.format(git_commit_hash, git_branch) + add_project_arguments('-DVERSION=@0@'.format(version), language: 'c') +endif +cc = meson.get_compiler('c') + + +wayland_client = dependency('wayland-client') +libhid = dependency('hidapi-hidraw') +rt = cc.find_library('rt') + + + +src_files = files( + './src/error.c', + './src/hid/hid.c', + './src/keyboard/keyboard.c', + './src/main.c', +) + +subdir('protocol') + +executable( + meson.project_name(), + src_files, + dependencies: [ + client_protos, + wayland_client, + libhid, + rt, + ], +) + diff --git a/rust/qmk-hid-com/src_c/protocol/meson.build b/rust/qmk-hid-com/src_c/protocol/meson.build new file mode 100644 index 0000000..1bfe9e0 --- /dev/null +++ b/rust/qmk-hid-com/src_c/protocol/meson.build @@ -0,0 +1,37 @@ +wayland_scanner = find_program('wayland-scanner') + +wayland_scanner_code = generator( + wayland_scanner, + output: '@BASENAME@-protocol.c', + arguments: ['private-code', '@INPUT@', '@OUTPUT@'], +) + +wayland_scanner_client = generator( + wayland_scanner, + output: '@BASENAME@-client-protocol.h', + arguments: ['client-header', '@INPUT@', '@OUTPUT@'], +) + + +client_protocols = [ + ['virtual-keyboard-unstable-v1.xml'], +] +client_protos_src = [] +client_protos_headers = [] + + +foreach p : client_protocols + xml = join_paths(p) + client_protos_src += wayland_scanner_code.process(xml) + client_protos_headers += wayland_scanner_client.process(xml) +endforeach +lib_client_protos = static_library( + 'client_protos', + client_protos_src + client_protos_headers, + dependencies: [wayland_client] +) + +client_protos = declare_dependency( + link_with: lib_client_protos, + sources: client_protos_headers, +) diff --git a/rust/qmk-hid-com/src_c/protocol/virtual-keyboard-unstable-v1.xml b/rust/qmk-hid-com/src_c/protocol/virtual-keyboard-unstable-v1.xml new file mode 100644 index 0000000..5095c91 --- /dev/null +++ b/rust/qmk-hid-com/src_c/protocol/virtual-keyboard-unstable-v1.xml @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="virtual_keyboard_unstable_v1"> + <copyright> + Copyright © 2008-2011 Kristian Høgsberg + Copyright © 2010-2013 Intel Corporation + Copyright © 2012-2013 Collabora, Ltd. + Copyright © 2018 Purism SPC + + 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 (including the next + paragraph) 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. + </copyright> + + <interface name="zwp_virtual_keyboard_v1" version="1"> + <description summary="virtual keyboard"> + The virtual keyboard provides an application with requests which emulate + the behaviour of a physical keyboard. + + This interface can be used by clients on its own to provide raw input + events, or it can accompany the input method protocol. + </description> + + <request name="keymap"> + <description summary="keyboard mapping"> + Provide a file descriptor to the compositor which can be + memory-mapped to provide a keyboard mapping description. + + Format carries a value from the keymap_format enumeration. + </description> + <arg name="format" type="uint" summary="keymap format"/> + <arg name="fd" type="fd" summary="keymap file descriptor"/> + <arg name="size" type="uint" summary="keymap size, in bytes"/> + </request> + + <enum name="error"> + <entry name="no_keymap" value="0" summary="No keymap was set"/> + </enum> + + <request name="key"> + <description summary="key event"> + A key was pressed or released. + The time argument is a timestamp with millisecond granularity, with an + undefined base. All requests regarding a single object must share the + same clock. + + Keymap must be set before issuing this request. + + State carries a value from the key_state enumeration. + </description> + <arg name="time" type="uint" summary="timestamp with millisecond granularity"/> + <arg name="key" type="uint" summary="key that produced the event"/> + <arg name="state" type="uint" summary="physical state of the key"/> + </request> + + <request name="modifiers"> + <description summary="modifier and group state"> + Notifies the compositor that the modifier and/or group state has + changed, and it should update state. + + The client should use wl_keyboard.modifiers event to synchronize its + internal state with seat state. + + Keymap must be set before issuing this request. + </description> + <arg name="mods_depressed" type="uint" summary="depressed modifiers"/> + <arg name="mods_latched" type="uint" summary="latched modifiers"/> + <arg name="mods_locked" type="uint" summary="locked modifiers"/> + <arg name="group" type="uint" summary="keyboard layout"/> + </request> + + <request name="destroy" type="destructor" since="1"> + <description summary="destroy the virtual keyboard keyboard object"/> + </request> + </interface> + + <interface name="zwp_virtual_keyboard_manager_v1" version="1"> + <description summary="virtual keyboard manager"> + A virtual keyboard manager allows an application to provide keyboard + input events as if they came from a physical keyboard. + </description> + + <enum name="error"> + <entry name="unauthorized" value="0" summary="client not authorized to use the interface"/> + </enum> + + <request name="create_virtual_keyboard"> + <description summary="Create a new virtual keyboard"> + Creates a new virtual keyboard associated to a seat. + + If the compositor enables a keyboard to perform arbitrary actions, it + should present an error when an untrusted client requests a new + keyboard. + </description> + <arg name="seat" type="object" interface="wl_seat"/> + <arg name="id" type="new_id" interface="zwp_virtual_keyboard_v1"/> + </request> + </interface> +</protocol> diff --git a/rust/qmk-hid-com/src_c/src/error.c b/rust/qmk-hid-com/src_c/src/error.c new file mode 100644 index 0000000..f970cfc --- /dev/null +++ b/rust/qmk-hid-com/src_c/src/error.c @@ -0,0 +1,20 @@ +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <wayland-client.h> + +#include "error.h" + +__attribute__((noreturn)) __attribute__((format(printf, 1, 2))) void +fail(const char *format, ...) { + va_list vas; + + va_start(vas, format); + fprintf(stderr, "Error: "); + vfprintf(stderr, format, vas); + va_end(vas); + + fprintf(stderr, "\n"); + + exit(EXIT_FAILURE); +} diff --git a/rust/qmk-hid-com/src_c/src/error.h b/rust/qmk-hid-com/src_c/src/error.h new file mode 100644 index 0000000..e0d6aaf --- /dev/null +++ b/rust/qmk-hid-com/src_c/src/error.h @@ -0,0 +1 @@ +void fail(const char *format, ...); diff --git a/rust/qmk-hid-com/src_c/src/hid/hid.c b/rust/qmk-hid-com/src_c/src/hid/hid.c new file mode 100644 index 0000000..d468ba8 --- /dev/null +++ b/rust/qmk-hid-com/src_c/src/hid/hid.c @@ -0,0 +1,83 @@ +#include <assert.h> +#include <hidapi/hidapi.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <unistd.h> + +#include "../error.h" +#include "hid.h" + +static hid_device *find_device_by_usage(uint32_t expected_usage, + uint32_t expected_usage_page) { + struct hid_device_info *devs; + devs = hid_enumerate(0x0, 0x0); + + hid_device *found_device = NULL; + bool found = false; + + struct hid_device_info *cur_dev = devs; + for (; cur_dev; cur_dev = cur_dev->next) { + // printf("Checking device: %ls, %d (%d:%d) at %s ..\n", + // cur_dev->product_string, cur_dev->product_id, cur_dev->usage, + // cur_dev->usage_page, cur_dev->path); + + if (cur_dev->usage == expected_usage && + cur_dev->usage_page == expected_usage_page) { + found_device = hid_open_path(cur_dev->path); + found = true; + + goto output; + } + } + +output: + hid_free_enumeration(devs); + if (!found_device) { + if (found) { + fail("Failed to open device usage (%d) and usage page (%d): %ls", + expected_usage, expected_usage_page, hid_error(found_device)); + } else { + fail("Can't find device with usage (%d) and usage page (%d): %ls", + expected_usage, expected_usage_page, hid_error(found_device)); + } + hid_exit(); + + return NULL; + } else { + return found_device; + } +} + +uint32_t read_next(uint32_t usage, uint32_t usage_page) { + hid_device *handle; + + if (hid_init()) { + fail("Failed to init hid"); + } + + handle = find_device_by_usage(usage, usage_page); + + uint8_t buf[4]; + int res = 0; + res = hid_read(handle, buf, sizeof(buf)); + if (res < 0) { + fail("Failed to read 4 bytes from hid device: %ls", hid_error(handle)); + } else if (res == 0) { + fail("Device did not send anything!"); + } + + hid_close(handle); + if (hid_exit()) { + fail("Failed to exit hid"); + } + + // Buf should only contain positive values. + assert(buf[0] >= 0 && buf[1] >= 0 && buf[2] >= 0 && buf[3] >= 0); + + // Only lower Endian supported, TODO add the other one + uint32_t key_code = + (uint32_t)(buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24)); + + return key_code; +} diff --git a/rust/qmk-hid-com/src_c/src/hid/hid.h b/rust/qmk-hid-com/src_c/src/hid/hid.h new file mode 100644 index 0000000..9ffb9d3 --- /dev/null +++ b/rust/qmk-hid-com/src_c/src/hid/hid.h @@ -0,0 +1,5 @@ +#pragma once + +#include <stdint.h> + +uint32_t read_next(uint32_t usage, uint32_t usage_page); diff --git a/rust/qmk-hid-com/src_c/src/keyboard/keyboard.c b/rust/qmk-hid-com/src_c/src/keyboard/keyboard.c new file mode 100644 index 0000000..4949085 --- /dev/null +++ b/rust/qmk-hid-com/src_c/src/keyboard/keyboard.c @@ -0,0 +1,135 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "virtual-keyboard-unstable-v1-client-protocol.h" + +#include "../error.h" +#include "keyboard.h" + + +static void handle_wl_event(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, + uint32_t version); +static void handle_wl_event_remove(void *data, struct wl_registry *registry, + uint32_t name); + +const struct wl_registry_listener registry_listener = { + .global = handle_wl_event, + .global_remove = handle_wl_event_remove, +}; + +struct qmk_unicode_type init_qmk_unicode() { + struct qmk_unicode_type qmk_unicode_type; + + memset(&qmk_unicode_type, 0, sizeof(qmk_unicode_type)); + qmk_unicode_type.display = wl_display_connect(NULL); + + if (qmk_unicode_type.display == NULL) { + fail("Wayland connection failed"); + } + + qmk_unicode_type.registry = wl_display_get_registry(qmk_unicode_type.display); + + wl_registry_add_listener(qmk_unicode_type.registry, ®istry_listener, + &qmk_unicode_type); + wl_display_dispatch(qmk_unicode_type.display); + wl_display_roundtrip(qmk_unicode_type.display); + + if (qmk_unicode_type.manager == NULL) { + fail("Compositor does not support the virtual keyboard protocol"); + } + if (qmk_unicode_type.seat == NULL) { + fail("No seat found"); + } + + qmk_unicode_type.keyboard = + zwp_virtual_keyboard_manager_v1_create_virtual_keyboard( + qmk_unicode_type.manager, qmk_unicode_type.seat); + + return qmk_unicode_type; +} +void destroy_qmk_unicode(struct qmk_unicode_type qmk_unicode_type) { + zwp_virtual_keyboard_v1_destroy(qmk_unicode_type.keyboard); + zwp_virtual_keyboard_manager_v1_destroy(qmk_unicode_type.manager); + wl_registry_destroy(qmk_unicode_type.registry); + wl_display_disconnect(qmk_unicode_type.display); +} + +static void upload_keymap(struct qmk_unicode_type *qmk_unicode_type, + uint32_t key_code); + +void type_keycode(struct qmk_unicode_type *qmk_unicode_type, + uint32_t key_code) { + upload_keymap(qmk_unicode_type, key_code); + + zwp_virtual_keyboard_v1_key(qmk_unicode_type->keyboard, 0, 1, + WL_KEYBOARD_KEY_STATE_PRESSED); + wl_display_roundtrip(qmk_unicode_type->display); + usleep(2000); + zwp_virtual_keyboard_v1_key(qmk_unicode_type->keyboard, 0, 1, + WL_KEYBOARD_KEY_STATE_RELEASED); + wl_display_roundtrip(qmk_unicode_type->display); + usleep(2000); +} + +static void handle_wl_event(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, + uint32_t version) { + struct qmk_unicode_type *qmk_unicode_type = (struct qmk_unicode_type *)data; + + if (!strcmp(interface, wl_seat_interface.name)) { + qmk_unicode_type->seat = (struct wl_seat *)wl_registry_bind( + registry, name, &wl_seat_interface, version <= 7 ? version : 7); + } else if (!strcmp(interface, + zwp_virtual_keyboard_manager_v1_interface.name)) { + qmk_unicode_type->manager = + (struct zwp_virtual_keyboard_manager_v1 *)wl_registry_bind( + registry, name, &zwp_virtual_keyboard_manager_v1_interface, 1); + } +} + +static void +handle_wl_event_remove(__attribute__((unused)) void *data, + __attribute__((unused)) struct wl_registry *_registry, + __attribute__((unused)) uint32_t _name) {} + +static void upload_keymap(struct qmk_unicode_type *qmk_unicode_type, + uint32_t key_code) { + char filename[] = "/tmp/qmk_unicode_type-XXXXXX"; + int fd = mkstemp(filename); + if (fd < 0) { + fail("Failed to create the temporary keymap file"); + } + unlink(filename); + FILE *f = fdopen(fd, "w"); + + fprintf(f, + "xkb_keymap {\n" + " xkb_keycodes \"(unnamed)\" {\n" + " minimum = 8;\n" + " maximum = 10;\n" + " <K1> = 9;\n" + " };\n" + // TODO: Is including "complete" here really a good idea? + " xkb_types \"(unnamed)\" { include \"complete\" };\n" + " xkb_compatibility \"(unnamed)\" { include \"complete\" };\n" + " xkb_symbols \"(unnamed)\" {\n" + " key <K1> {[U%X]};\n" + " };\n" + "};\n", + key_code); + + fputc('\0', f); + fflush(f); + + uint32_t keymap_size = (uint32_t)ftell(f); + zwp_virtual_keyboard_v1_keymap(qmk_unicode_type->keyboard, + WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fileno(f), + keymap_size); + + wl_display_roundtrip(qmk_unicode_type->display); + fclose(f); +} diff --git a/rust/qmk-hid-com/src_c/src/keyboard/keyboard.h b/rust/qmk-hid-com/src_c/src/keyboard/keyboard.h new file mode 100644 index 0000000..ac5d7bd --- /dev/null +++ b/rust/qmk-hid-com/src_c/src/keyboard/keyboard.h @@ -0,0 +1,17 @@ +#pragma once + +#include <stdint.h> + +struct qmk_unicode_type init_qmk_unicode(); +void destroy_qmk_unicode(struct qmk_unicode_type qmk_unicode_type); + +void type_keycode(struct qmk_unicode_type *qmk_unicode_type, uint32_t key_code); + +// Private +struct qmk_unicode_type { + struct wl_display *display; + struct wl_registry *registry; + struct wl_seat *seat; + struct zwp_virtual_keyboard_manager_v1 *manager; + struct zwp_virtual_keyboard_v1 *keyboard; +}; diff --git a/rust/qmk-hid-com/src_c/src/keyboard/virtual-keyboard-unstable-v1-client-protocol.h b/rust/qmk-hid-com/src_c/src/keyboard/virtual-keyboard-unstable-v1-client-protocol.h new file mode 100644 index 0000000..81cac0b --- /dev/null +++ b/rust/qmk-hid-com/src_c/src/keyboard/virtual-keyboard-unstable-v1-client-protocol.h @@ -0,0 +1,280 @@ +/* Generated by wayland-scanner 1.23.1 */ + +#ifndef VIRTUAL_KEYBOARD_UNSTABLE_V1_CLIENT_PROTOCOL_H +#define VIRTUAL_KEYBOARD_UNSTABLE_V1_CLIENT_PROTOCOL_H + +#include <stdint.h> +#include <stddef.h> +#include "wayland-client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @page page_virtual_keyboard_unstable_v1 The virtual_keyboard_unstable_v1 protocol + * @section page_ifaces_virtual_keyboard_unstable_v1 Interfaces + * - @subpage page_iface_zwp_virtual_keyboard_v1 - virtual keyboard + * - @subpage page_iface_zwp_virtual_keyboard_manager_v1 - virtual keyboard manager + * @section page_copyright_virtual_keyboard_unstable_v1 Copyright + * <pre> + * + * Copyright © 2008-2011 Kristian Høgsberg + * Copyright © 2010-2013 Intel Corporation + * Copyright © 2012-2013 Collabora, Ltd. + * Copyright © 2018 Purism SPC + * + * 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 (including the next + * paragraph) 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. + * </pre> + */ +struct wl_seat; +struct zwp_virtual_keyboard_manager_v1; +struct zwp_virtual_keyboard_v1; + +#ifndef ZWP_VIRTUAL_KEYBOARD_V1_INTERFACE +#define ZWP_VIRTUAL_KEYBOARD_V1_INTERFACE +/** + * @page page_iface_zwp_virtual_keyboard_v1 zwp_virtual_keyboard_v1 + * @section page_iface_zwp_virtual_keyboard_v1_desc Description + * + * The virtual keyboard provides an application with requests which emulate + * the behaviour of a physical keyboard. + * + * This interface can be used by clients on its own to provide raw input + * events, or it can accompany the input method protocol. + * @section page_iface_zwp_virtual_keyboard_v1_api API + * See @ref iface_zwp_virtual_keyboard_v1. + */ +/** + * @defgroup iface_zwp_virtual_keyboard_v1 The zwp_virtual_keyboard_v1 interface + * + * The virtual keyboard provides an application with requests which emulate + * the behaviour of a physical keyboard. + * + * This interface can be used by clients on its own to provide raw input + * events, or it can accompany the input method protocol. + */ +extern const struct wl_interface zwp_virtual_keyboard_v1_interface; +#endif +#ifndef ZWP_VIRTUAL_KEYBOARD_MANAGER_V1_INTERFACE +#define ZWP_VIRTUAL_KEYBOARD_MANAGER_V1_INTERFACE +/** + * @page page_iface_zwp_virtual_keyboard_manager_v1 zwp_virtual_keyboard_manager_v1 + * @section page_iface_zwp_virtual_keyboard_manager_v1_desc Description + * + * A virtual keyboard manager allows an application to provide keyboard + * input events as if they came from a physical keyboard. + * @section page_iface_zwp_virtual_keyboard_manager_v1_api API + * See @ref iface_zwp_virtual_keyboard_manager_v1. + */ +/** + * @defgroup iface_zwp_virtual_keyboard_manager_v1 The zwp_virtual_keyboard_manager_v1 interface + * + * A virtual keyboard manager allows an application to provide keyboard + * input events as if they came from a physical keyboard. + */ +extern const struct wl_interface zwp_virtual_keyboard_manager_v1_interface; +#endif + +#ifndef ZWP_VIRTUAL_KEYBOARD_V1_ERROR_ENUM +#define ZWP_VIRTUAL_KEYBOARD_V1_ERROR_ENUM +enum zwp_virtual_keyboard_v1_error { + /** + * No keymap was set + */ + ZWP_VIRTUAL_KEYBOARD_V1_ERROR_NO_KEYMAP = 0, +}; +#endif /* ZWP_VIRTUAL_KEYBOARD_V1_ERROR_ENUM */ + +#define ZWP_VIRTUAL_KEYBOARD_V1_KEYMAP 0 +#define ZWP_VIRTUAL_KEYBOARD_V1_KEY 1 +#define ZWP_VIRTUAL_KEYBOARD_V1_MODIFIERS 2 +#define ZWP_VIRTUAL_KEYBOARD_V1_DESTROY 3 + + +/** + * @ingroup iface_zwp_virtual_keyboard_v1 + */ +#define ZWP_VIRTUAL_KEYBOARD_V1_KEYMAP_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_virtual_keyboard_v1 + */ +#define ZWP_VIRTUAL_KEYBOARD_V1_KEY_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_virtual_keyboard_v1 + */ +#define ZWP_VIRTUAL_KEYBOARD_V1_MODIFIERS_SINCE_VERSION 1 +/** + * @ingroup iface_zwp_virtual_keyboard_v1 + */ +#define ZWP_VIRTUAL_KEYBOARD_V1_DESTROY_SINCE_VERSION 1 + +/** @ingroup iface_zwp_virtual_keyboard_v1 */ +static inline void +zwp_virtual_keyboard_v1_set_user_data(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_virtual_keyboard_v1, user_data); +} + +/** @ingroup iface_zwp_virtual_keyboard_v1 */ +static inline void * +zwp_virtual_keyboard_v1_get_user_data(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_virtual_keyboard_v1); +} + +static inline uint32_t +zwp_virtual_keyboard_v1_get_version(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_virtual_keyboard_v1); +} + +/** + * @ingroup iface_zwp_virtual_keyboard_v1 + * + * Provide a file descriptor to the compositor which can be + * memory-mapped to provide a keyboard mapping description. + * + * Format carries a value from the keymap_format enumeration. + */ +static inline void +zwp_virtual_keyboard_v1_keymap(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard_v1, uint32_t format, int32_t fd, uint32_t size) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_virtual_keyboard_v1, + ZWP_VIRTUAL_KEYBOARD_V1_KEYMAP, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_virtual_keyboard_v1), 0, format, fd, size); +} + +/** + * @ingroup iface_zwp_virtual_keyboard_v1 + * + * A key was pressed or released. + * The time argument is a timestamp with millisecond granularity, with an + * undefined base. All requests regarding a single object must share the + * same clock. + * + * Keymap must be set before issuing this request. + * + * State carries a value from the key_state enumeration. + */ +static inline void +zwp_virtual_keyboard_v1_key(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard_v1, uint32_t time, uint32_t key, uint32_t state) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_virtual_keyboard_v1, + ZWP_VIRTUAL_KEYBOARD_V1_KEY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_virtual_keyboard_v1), 0, time, key, state); +} + +/** + * @ingroup iface_zwp_virtual_keyboard_v1 + * + * Notifies the compositor that the modifier and/or group state has + * changed, and it should update state. + * + * The client should use wl_keyboard.modifiers event to synchronize its + * internal state with seat state. + * + * Keymap must be set before issuing this request. + */ +static inline void +zwp_virtual_keyboard_v1_modifiers(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard_v1, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_virtual_keyboard_v1, + ZWP_VIRTUAL_KEYBOARD_V1_MODIFIERS, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_virtual_keyboard_v1), 0, mods_depressed, mods_latched, mods_locked, group); +} + +/** + * @ingroup iface_zwp_virtual_keyboard_v1 + */ +static inline void +zwp_virtual_keyboard_v1_destroy(struct zwp_virtual_keyboard_v1 *zwp_virtual_keyboard_v1) +{ + wl_proxy_marshal_flags((struct wl_proxy *) zwp_virtual_keyboard_v1, + ZWP_VIRTUAL_KEYBOARD_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_virtual_keyboard_v1), WL_MARSHAL_FLAG_DESTROY); +} + +#ifndef ZWP_VIRTUAL_KEYBOARD_MANAGER_V1_ERROR_ENUM +#define ZWP_VIRTUAL_KEYBOARD_MANAGER_V1_ERROR_ENUM +enum zwp_virtual_keyboard_manager_v1_error { + /** + * client not authorized to use the interface + */ + ZWP_VIRTUAL_KEYBOARD_MANAGER_V1_ERROR_UNAUTHORIZED = 0, +}; +#endif /* ZWP_VIRTUAL_KEYBOARD_MANAGER_V1_ERROR_ENUM */ + +#define ZWP_VIRTUAL_KEYBOARD_MANAGER_V1_CREATE_VIRTUAL_KEYBOARD 0 + + +/** + * @ingroup iface_zwp_virtual_keyboard_manager_v1 + */ +#define ZWP_VIRTUAL_KEYBOARD_MANAGER_V1_CREATE_VIRTUAL_KEYBOARD_SINCE_VERSION 1 + +/** @ingroup iface_zwp_virtual_keyboard_manager_v1 */ +static inline void +zwp_virtual_keyboard_manager_v1_set_user_data(struct zwp_virtual_keyboard_manager_v1 *zwp_virtual_keyboard_manager_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_virtual_keyboard_manager_v1, user_data); +} + +/** @ingroup iface_zwp_virtual_keyboard_manager_v1 */ +static inline void * +zwp_virtual_keyboard_manager_v1_get_user_data(struct zwp_virtual_keyboard_manager_v1 *zwp_virtual_keyboard_manager_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_virtual_keyboard_manager_v1); +} + +static inline uint32_t +zwp_virtual_keyboard_manager_v1_get_version(struct zwp_virtual_keyboard_manager_v1 *zwp_virtual_keyboard_manager_v1) +{ + return wl_proxy_get_version((struct wl_proxy *) zwp_virtual_keyboard_manager_v1); +} + +/** @ingroup iface_zwp_virtual_keyboard_manager_v1 */ +static inline void +zwp_virtual_keyboard_manager_v1_destroy(struct zwp_virtual_keyboard_manager_v1 *zwp_virtual_keyboard_manager_v1) +{ + wl_proxy_destroy((struct wl_proxy *) zwp_virtual_keyboard_manager_v1); +} + +/** + * @ingroup iface_zwp_virtual_keyboard_manager_v1 + * + * Creates a new virtual keyboard associated to a seat. + * + * If the compositor enables a keyboard to perform arbitrary actions, it + * should present an error when an untrusted client requests a new + * keyboard. + */ +static inline struct zwp_virtual_keyboard_v1 * +zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(struct zwp_virtual_keyboard_manager_v1 *zwp_virtual_keyboard_manager_v1, struct wl_seat *seat) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_flags((struct wl_proxy *) zwp_virtual_keyboard_manager_v1, + ZWP_VIRTUAL_KEYBOARD_MANAGER_V1_CREATE_VIRTUAL_KEYBOARD, &zwp_virtual_keyboard_v1_interface, wl_proxy_get_version((struct wl_proxy *) zwp_virtual_keyboard_manager_v1), 0, seat, NULL); + + return (struct zwp_virtual_keyboard_v1 *) id; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rust/qmk-hid-com/src_c/src/main.c b/rust/qmk-hid-com/src_c/src/main.c new file mode 100644 index 0000000..48d490e --- /dev/null +++ b/rust/qmk-hid-com/src_c/src/main.c @@ -0,0 +1,28 @@ +#include <stdlib.h> + +#include "error.h" +#include "hid/hid.h" +#include "keyboard/keyboard.h" + +int main(int argc, const char *argv[]) { + if (argc != 3) { + fail("Usage: %s <usage> <usage_page>", argv[0]); + } + + char *ep; + uint32_t usage = (uint32_t)strtoul(argv[1], &ep, 0); + if (*ep != 0) { + fail("Invalid usage: %x", usage); + } + + uint32_t usage_page = (uint32_t)strtoul(argv[2], &ep, 0); + if (*ep != 0) { + fail("Invalid usage: %x", usage_page); + } + + uint32_t key_value = read_next(usage, usage_page); + + struct qmk_unicode_type qmk_unicode_type = init_qmk_unicode(); + type_keycode(&qmk_unicode_type, key_value); + destroy_qmk_unicode(qmk_unicode_type); +} |