diff options
Diffstat (limited to 'rust/qmk-hid-com/src_c/src')
-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 |
8 files changed, 569 insertions, 0 deletions
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); +} |