aboutsummaryrefslogtreecommitdiffstats
path: root/libgamepad_get_attachment_event.c
blob: 4462356029ad7f35b7ed0d7610d78fa3a0b36ac8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/* See LICENSE file for copyright and license details. */
#include "common.h"


int
libgamepad_get_attachment_event(LIBGAMEPAD_ATTACHMENT_MONITOR *monitor, char **syspathp, size_t *sizep,
                                enum libgamepad_attachment_event_type *typep)
{
	struct udev_device *device;
	const char *action;
	const char *syspath;
	size_t len;
	void *new;
	char *syspath_end;
	int saved_errno;

	device = udev_monitor_receive_device(monitor->monitor);
	if (!device)
		return -1;

	action = udev_device_get_action(device);
	if (!strcmp(action, "bind"))
		*typep = LIBGAMEPAD_ADDED;
	else if (!strcmp(action, "unbind"))
		*typep = LIBGAMEPAD_REMOVED;
	else
		goto suppress;

	syspath = udev_device_get_syspath(device);
	if (!syspath || !*syspath)
		goto suppress;
	len = strlen(syspath) + sizeof("/hidraw");
	if (len > *sizep) {
		new = realloc(*syspathp, len);
		if (!new) {
			udev_device_unref(device);
			return -1;
		}
		*syspathp = new;
		*sizep = len;
	}
	syspath_end = stpcpy(*syspathp, syspath);

	if (*typep == LIBGAMEPAD_ADDED) {
		stpcpy(syspath_end, "/hidraw");
		saved_errno = errno;
		if (access(*syspathp, F_OK)) {
			errno = saved_errno;
			goto suppress;
		}
		*syspath_end = '\0';
	}

	udev_device_unref(device);
	return 1;

suppress:
	udev_device_unref(device);
	return 0;
}