diff options
| author | cbdev <cb@cbcdn.com> | 2018-03-02 03:20:11 +0100 | 
|---|---|---|
| committer | cbdev <cb@cbcdn.com> | 2018-03-02 03:20:11 +0100 | 
| commit | 2dfc564edc0c89c4a8de7e384806aae5d593426d (patch) | |
| tree | b1636ec14d3f35ed88b3f079e0c3d168f77b17b9 /evdev.c | |
| parent | be5df1c4e639ca6a7cd70a3122039a1de4588e28 (diff) | |
| download | midimonster-2dfc564edc0c89c4a8de7e384806aae5d593426d.tar.gz midimonster-2dfc564edc0c89c4a8de7e384806aae5d593426d.tar.bz2 midimonster-2dfc564edc0c89c4a8de7e384806aae5d593426d.zip | |
Move backend implementations to subdirectory
Diffstat (limited to 'evdev.c')
| -rw-r--r-- | evdev.c | 401 | 
1 files changed, 0 insertions, 401 deletions
| diff --git a/evdev.c b/evdev.c deleted file mode 100644 index ac63850..0000000 --- a/evdev.c +++ /dev/null @@ -1,401 +0,0 @@ -#include <fcntl.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <libevdev/libevdev.h> -#ifndef EVDEV_NO_UINPUT -#include <libevdev/libevdev-uinput.h> -#endif - -#include "midimonster.h" -#include "evdev.h" - -#define BACKEND_NAME "evdev" - -typedef union { -	struct { -		uint32_t pad; -		uint16_t type; -		uint16_t code; -	} fields; -	uint64_t label; -} evdev_channel_ident; - -int init(){ -	backend evdev = { -		.name = BACKEND_NAME, -		.conf = evdev_configure, -		.create = evdev_instance, -		.conf_instance = evdev_configure_instance, -		.channel = evdev_channel, -		.handle = evdev_set, -		.process = evdev_handle, -		.start = evdev_start, -		.shutdown = evdev_shutdown -	}; - -	if(mm_backend_register(evdev)){ -		fprintf(stderr, "Failed to register evdev backend\n"); -		return 1; -	} - -	return 0; -} - -static int evdev_configure(char* option, char* value) { -	fprintf(stderr, "The evdev backend does not take any global configuration\n"); -	return 1; -} - -static instance* evdev_instance(){ -	instance* inst = mm_instance(); -	if(!inst){ -		return NULL; -	} - -	evdev_instance_data* data = calloc(1, sizeof(evdev_instance_data)); -	if(!data){ -		fprintf(stderr, "Failed to allocate memory\n"); -		return NULL; -	} - -	data->input_fd = -1; -#ifndef EVDEV_NO_UINPUT -	data->output_proto = libevdev_new(); -	if(!data->output_proto){ -		fprintf(stderr, "Failed to initialize libevdev output prototype device\n"); -		free(data); -		return NULL; -	} -#endif - -	inst->impl = data; -	return inst; -} - -static int evdev_configure_instance(instance* inst, char* option, char* value) { -	evdev_instance_data* data = (evdev_instance_data*) inst->impl; -#ifndef EVDEV_NO_UINPUT -	char* next_token = NULL; -	struct input_absinfo abs_info = { -		0 -	}; -#endif - -	if(!strcmp(option, "input")){ -		if(data->input_fd >= 0){ -			fprintf(stderr, "Instance %s already was assigned an input device\n", inst->name); -			return 1; -		} - -		data->input_fd = open(value, O_RDONLY | O_NONBLOCK); -		if(data->input_fd < 0){ -			fprintf(stderr, "Failed to open evdev input device node %s: %s\n", value, strerror(errno)); -			return 1; -		} - -		if(libevdev_new_from_fd(data->input_fd, &data->input_ev)){ -			fprintf(stderr, "Failed to initialize libevdev for %s\n", value); -			close(data->input_fd); -			data->input_fd = -1; -			return 1; -		} - -		if(data->exclusive && libevdev_grab(data->input_ev, LIBEVDEV_GRAB)){ -			fprintf(stderr, "Failed to obtain exclusive device access on %s\n", value); -		} -	} -	else if(!strcmp(option, "exclusive")){ -		if(data->input_fd >= 0 && libevdev_grab(data->input_ev, LIBEVDEV_GRAB)){ -			fprintf(stderr, "Failed to obtain exclusive device access on %s\n", inst->name); -		} -		data->exclusive = 1; -	} -#ifndef EVDEV_NO_UINPUT -	else if(!strcmp(option, "name")){ -		data->output_enabled = 1; -		libevdev_set_name(data->output_proto, value); -	} -	else if(!strcmp(option, "id")){ -		next_token = value; -		libevdev_set_id_vendor(data->output_proto, strtol(next_token, &next_token, 0)); -		libevdev_set_id_product(data->output_proto, strtol(next_token, &next_token, 0)); -		libevdev_set_id_version(data->output_proto, strtol(next_token, &next_token, 0)); -	} -	else if(!strncmp(option, "axis.", 5)){ -		//value minimum maximum fuzz flat resolution -		next_token = value; -		abs_info.value = strtol(next_token, &next_token, 0); -		abs_info.minimum = strtol(next_token, &next_token, 0); -		abs_info.maximum = strtol(next_token, &next_token, 0); -		abs_info.fuzz = strtol(next_token, &next_token, 0); -		abs_info.flat = strtol(next_token, &next_token, 0); -		abs_info.resolution = strtol(next_token, &next_token, 0); -		if(libevdev_enable_event_code(data->output_proto, EV_ABS, libevdev_event_code_from_name(EV_ABS, option + 5), &abs_info)){ -			fprintf(stderr, "Failed to enable absolute axis %s for output\n", option + 5); -			return 1; -		} -	} -#endif -	else{ -		fprintf(stderr, "Unknown configuration parameter %s for evdev backend\n", option); -		return 1; -	} -	return 0; -} - -static channel* evdev_channel(instance* inst, char* spec){ -#ifndef EVDEV_NO_UINPUT -	evdev_instance_data* data = (evdev_instance_data*) inst->impl; -#endif -	char* separator = strchr(spec, '.'); -	evdev_channel_ident ident = { -		.label = 0 -	}; - -	if(!separator){ -		fprintf(stderr, "Invalid evdev channel specification %s\n", spec); -		return NULL; -	} - -	*(separator++) = 0; - -	if(libevdev_event_type_from_name(spec) < 0){ -		fprintf(stderr, "Invalid evdev type specification: %s", spec); -		return NULL; -	} -	ident.fields.type = libevdev_event_type_from_name(spec); - -	if(libevdev_event_code_from_name(ident.fields.type, separator) >= 0){ -		ident.fields.code = libevdev_event_code_from_name(ident.fields.type, separator); -	} -	else{ -		fprintf(stderr, "evdev Code name not recognized, using as number: %s\n", separator); -		ident.fields.code = strtoul(separator, NULL, 10); -	} - -#ifndef EVDEV_NO_UINPUT -	if(data->output_enabled){ -		if(!libevdev_has_event_code(data->output_proto, ident.fields.type, ident.fields.code)){ -			//enable the event on the device -			//the previous check is necessary to not fail while enabling axes, which require additional information -			if(libevdev_enable_event_code(data->output_proto, ident.fields.type, ident.fields.code, NULL)){ -				fprintf(stderr, "Failed to enable output event %s.%s%s\n", -						libevdev_event_type_get_name(ident.fields.type), -						libevdev_event_code_get_name(ident.fields.type, ident.fields.code), -						(ident.fields.type == EV_ABS) ? ": To output absolute axes, specify their details in the configuration":""); -				return NULL; -			} -		} -	} -#endif - -	return mm_channel(inst, ident.label, 1); -} - -static int evdev_push_event(instance* inst, evdev_instance_data* data, struct input_event event){ -	uint64_t range = 0; -	channel_value val; -	evdev_channel_ident ident = { -		.fields.type = event.type, -		.fields.code = event.code -	}; -	channel* chan = mm_channel(inst, ident.label, 0); - -	if(chan){ -		val.raw.u64 = event.value; -		switch(event.type){ -			case EV_REL: -				val.normalised = 0.5 + ((event.value < 0) ? 0.5 : -0.5); -				break; -			case EV_ABS: -				range = libevdev_get_abs_maximum(data->input_ev, event.code) - libevdev_get_abs_minimum(data->input_ev, event.code); -				val.normalised = (event.value - libevdev_get_abs_minimum(data->input_ev, event.code)) / (double) range; -				break; -			case EV_KEY: -			case EV_SW: -			default: -				val.normalised = 1.0 * event.value; -				break; -		} - -		if(mm_channel_event(chan, val)){ -			fprintf(stderr, "Failed to push evdev channel event to core\n"); -			return 1; -		} -	} - -	return 0; -} - -static int evdev_handle(size_t num, managed_fd* fds){ -	instance* inst = NULL; -	evdev_instance_data* data = NULL; -	size_t fd; -	unsigned int read_flags = LIBEVDEV_READ_FLAG_NORMAL; -	int read_status; -	struct input_event ev; - -	if(!num){ -		return 0; -	} - -	for(fd = 0; fd < num; fd++){ -		inst = (instance*) fds[fd].impl; -		if(!inst){ -			fprintf(stderr, "evdev backend signaled for unknown fd\n"); -			continue; -		} - -		data = (evdev_instance_data*) inst->impl; - -		for(read_status = libevdev_next_event(data->input_ev, read_flags, &ev); read_status >= 0; read_status = libevdev_next_event(data->input_ev, read_flags, &ev)){ -			read_flags = LIBEVDEV_READ_FLAG_NORMAL; -			if(read_status == LIBEVDEV_READ_STATUS_SYNC){ -				read_flags = LIBEVDEV_READ_FLAG_SYNC; -			} - -			//handle event -			if(evdev_push_event(inst, data, ev)){ -				return 1; -			} -		} -	} - -	return 0; -} - -static int evdev_start(){ -	size_t n, u, fds = 0; -	instance** inst = NULL; -	evdev_instance_data* data = NULL; - -	if(mm_backend_instances(BACKEND_NAME, &n, &inst)){ -		fprintf(stderr, "Failed to fetch instance list\n"); -		return 1; -	} - -	if(!n){ -		free(inst); -		return 0; -	} - -	for(u = 0; u < n; u++){ -		data = (evdev_instance_data*) inst[u]->impl; - -#ifndef EVDEV_NO_UINPUT -		if(data->output_enabled){ -			if(libevdev_uinput_create_from_device(data->output_proto, LIBEVDEV_UINPUT_OPEN_MANAGED, &data->output_ev)){ -				fprintf(stderr, "Failed to create evdev output device: %s\n", strerror(errno)); -				return 1; -			} -			fprintf(stderr, "Created device node %s for instance %s\n", libevdev_uinput_get_devnode(data->output_ev), inst[u]->name); -		} -#endif - -		inst[u]->ident = data->input_fd; -		if(data->input_fd >= 0){ -			if(mm_manage_fd(data->input_fd, BACKEND_NAME, 1, inst[u])){ -				fprintf(stderr, "Failed to register event input descriptor for instance %s\n", inst[u]->name); -				free(inst); -				return 1; -			} -			fds++; -		} - -	} - -	fprintf(stderr, "evdev backend registered %zu descriptors to core\n", fds); -	free(inst); -	return 0; -} - -static int evdev_set(instance* inst, size_t num, channel** c, channel_value* v) { -#ifndef EVDEV_NO_UINPUT -	size_t evt = 0; -	evdev_instance_data* data = (evdev_instance_data*) inst->impl; -	evdev_channel_ident ident = { -		.label = 0 -	}; -	int32_t value = 0; -	uint64_t range = 0; - -	if(!num){ -		return 0; -	} - -	if(!data->output_enabled){ -		fprintf(stderr, "Instance %s not enabled for output\n", inst->name); -		return 0; -	} - -	for(evt = 0; evt < num; evt++){ -		ident.label = c[evt]->ident; - -		switch(ident.fields.type){ -			case EV_REL: -				value = (v[evt].normalised < 0.5) ? -1 : ((v[evt].normalised > 0.5) ? 1 : 0); -				break; -			case EV_ABS: -				range = libevdev_get_abs_maximum(data->output_proto, ident.fields.code) - libevdev_get_abs_minimum(data->output_proto, ident.fields.code); -				value = (range * v[evt].normalised) + libevdev_get_abs_minimum(data->output_proto, ident.fields.code); -				break; -			case EV_KEY: -			case EV_SW: -			default: -				value = (v[evt].normalised > 0.9) ? 1 : 0; -				break; -		} - -		if(libevdev_uinput_write_event(data->output_ev, ident.fields.type, ident.fields.code, value)){ -			fprintf(stderr, "Failed to output event on instance %s\n", inst->name); -			return 1; -		} -	} - -	//send syn event to publish all events -	if(libevdev_uinput_write_event(data->output_ev, EV_SYN, SYN_REPORT, 0)){ -		fprintf(stderr, "Failed to output sync event on instance %s\n", inst->name); -		return 1; -	} - -	return 0; -#else -	fprintf(stderr, "The evdev backend does not support output on this platform\n"); -	return 1; -#endif -} - -static int evdev_shutdown(){ -	evdev_instance_data* data = NULL; -	instance** instances = NULL; -	size_t n, u; - -	if(mm_backend_instances(BACKEND_NAME, &n, &instances)){ -		fprintf(stderr, "Failed to fetch instance list\n"); -		return 1; -	} - -	for(u = 0; u < n; u++){ -		data = (evdev_instance_data*) instances[u]->impl; - -		if(data->input_fd >= 0){ -			libevdev_free(data->input_ev); -			close(data->input_fd); -		} - -#ifndef EVDEV_NO_UINPUT -		if(data->output_enabled){ -			libevdev_uinput_destroy(data->output_ev); -		} - -		libevdev_free(data->output_proto); -#endif -		free(data); -	} - -	free(instances); -	return 0; -} | 
