summaryrefslogtreecommitdiff
path: root/cras/src/server/cras_gpio_jack.c
blob: 70219087833d12d02a7a5376876efb856a08f285 (plain)
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <fcntl.h>
#include <linux/input.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <libudev.h>

#include "cras_util.h"
#include "cras_gpio_jack.h"

int gpio_switch_open(const char *pathname)
{
	return open(pathname, O_RDONLY);
}

int gpio_switch_read(int fd, void *buf, size_t n_bytes)
{
	return read(fd, buf, n_bytes);
}

int gpio_switch_eviocgname(int fd, char *name, size_t n_bytes)
{
	return ioctl(fd, EVIOCGNAME(n_bytes), name);
}

int gpio_switch_eviocgbit(int fd, void *buf, size_t n_bytes)
{
	return ioctl(fd, EVIOCGBIT(EV_SW, n_bytes), buf);
}

int gpio_switch_eviocgsw(int fd, void *bits, size_t n_bytes)
{
	return ioctl(fd, EVIOCGSW(n_bytes), bits);
}

char *sys_input_get_device_name(const char *path)
{
	char name[256];
	int fd = open(path, O_RDONLY);

	if (fd >= 0) {
		gpio_switch_eviocgname(fd, name, sizeof(name));
		close(fd);
		return strdup(name);
	} else {
		syslog(LOG_WARNING, "Could not open '%s': %s", path,
		       strerror(errno));
		return NULL;
	}
}

void gpio_switch_list_for_each(gpio_switch_list_callback callback, void *arg)
{
	struct udev *udev;
	struct udev_enumerate *enumerate;
	struct udev_list_entry *dl;
	struct udev_list_entry *dev_list_entry;

	if (!callback)
		return;

	udev = udev_new();
	assert(udev != NULL);
	enumerate = udev_enumerate_new(udev);
	udev_enumerate_add_match_subsystem(enumerate, "input");
	udev_enumerate_scan_devices(enumerate);
	dl = udev_enumerate_get_list_entry(enumerate);

	udev_list_entry_foreach(dev_list_entry, dl)
	{
		const char *path = udev_list_entry_get_name(dev_list_entry);
		struct udev_device *dev =
			udev_device_new_from_syspath(udev, path);
		const char *devnode = udev_device_get_devnode(dev);
		char *ioctl_name;

		if (devnode == NULL)
			continue;

		ioctl_name = sys_input_get_device_name(devnode);
		if (ioctl_name == NULL)
			continue;

		if (callback(devnode, ioctl_name, arg)) {
			free(ioctl_name);
			break;
		}
		free(ioctl_name);
	}
	udev_enumerate_unref(enumerate);
	udev_unref(udev);
}