struct evf_filter { const struct evf_filter_ops *ops; struct evf_filter *next; char data[0]; };
This part of documentation describes how filters are implemented.
struct evf_filter { const struct evf_filter_ops *ops; struct evf_filter *next; char data[0]; };
The evf_filter structure is allocated when a new instance of a filter is created. The ops pointer points to a static structure and the data points to a filter private data structures.
Filters, for a specific device, are arranged in a linked list by the next pointer. When events are processed each filter passes, possibly modified, events to a process() callback of the next filter.
struct evf_filter_ops { const char *json_id; struct evf_filter* (*from_json)(json_object *json_data); void (*process)(struct evf_filter *self, struct input_event *ev); void (*free)(struct evf_filter *self); const char *desc; };
Filter is implemented as a set of callbacks.
The from_json() callback is used to initialize and allocate filter from a JSON configuration. Each filter can be as well allocated from a C call that ends with _alloc() suffix.
The json_id is a filter name that is used to locate correct from_json() callback when filters are loaded accordingly to the JSON configuration.
The free() callback can be used to clean up any additional resources that have been allocated. The memory that holds the filter instance itself is freed automatically.
The desc is a single sentence that describes the filter.
And finally the process() callbacks is where events are passed to and processed.
// SPDX-License-Identifier: LGPL-2.1-or-later /* * Copyright (C) 2008-2020 Cyril Hrubis <metan@ucw.cz> */ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <linux/input.h> #include "evf_struct.h" #include "evf_msg.h" #include "key_parser.h" #include "filters.h" struct priv { int key; int state; int eat_next_sync; }; static void key_lock_process(struct evf_filter *self, struct input_event *ev) { struct priv *priv = (struct priv*) self->data; if (priv->eat_next_sync) { priv->eat_next_sync = 0; if (ev->type == 0 && ev->code == 0 && ev->value == 0) return; } if (ev->type == EV_KEY && ev->code == priv->key) { /* key released */ if (ev->value == 0) { priv->eat_next_sync = 1; return; } /* key pressed */ if (ev->value == 1) { if (priv->state == 0) priv->state = 1; else { priv->state = 0; ev->value = 0; } } } evf_filter_process(self->next, ev); } static struct evf_filter *key_lock_from_json(json_object *json_data) { int key_val = -1; json_object_object_foreach(json_data, key, val) { if (!strcmp(key, "key")) { const char *key_str = json_object_get_string(val); key_val = keyparser_getkey(key_str); if (key_val == -1) { evf_msg(EVF_DEBUG, "Invalid key name %s", key_str); return NULL; } } else { evf_msg(EVF_DEBUG, "Invalid JSON key_lock key %s", key); return NULL; } } return evf_key_lock_alloc(key_val); } struct evf_filter_ops evf_key_lock_ops = { .json_id = "key_lock", .from_json = key_lock_from_json, .process = key_lock_process, .desc = "Locks key pressed on press, releases it on second press", }; struct evf_filter *evf_key_lock_alloc(int key) { struct evf_filter *evf = malloc(sizeof(struct evf_filter) + sizeof(struct priv)); struct priv *priv; if (!evf) return NULL; evf->ops = &evf_key_lock_ops; priv = (struct priv*) evf->data; priv->key = key; priv->state = 0; priv->eat_next_sync = 0; return evf; }