Skip to content
Snippets Groups Projects
Commit c0141861 authored by Simon McVittie's avatar Simon McVittie
Browse files

input-device: Add the uevent data structure

parent c6d3478b
No related branches found
No related tags found
1 merge request!158Input device interface
......@@ -43,6 +43,7 @@
static FILE *original_stdout = NULL;
static gboolean opt_one_line = FALSE;
static gboolean opt_seq = FALSE;
static gboolean opt_verbose = FALSE;
static void
print_json (JsonBuilder *builder)
......@@ -114,6 +115,46 @@ added (SrtInputDeviceMonitor *monitor,
json_builder_end_array (builder);
}
if (opt_verbose)
{
g_autofree gchar *uevent = srt_input_device_dup_uevent (dev);
if (uevent != NULL)
{
const char *start = uevent;
const char *end;
/* uevent is conceptually a single string, but we
* present it as an array of lines here, because that's
* a lot easier to read! */
json_builder_set_member_name (builder, "uevent");
json_builder_begin_array (builder);
while (*start != '\0')
{
g_autofree gchar *valid = NULL;
while (*start == '\n')
start++;
if (*start == '\0')
break;
end = strchrnul (start, '\n');
valid = g_utf8_make_valid (start, (end - start) - 1);
json_builder_add_string_value (builder, valid);
if (*end == '\0')
break;
start = end + 1;
}
json_builder_end_array (builder);
}
}
/* TODO: Print more details here */
}
json_builder_end_object (builder);
......@@ -236,6 +277,8 @@ static const GOptionEntry option_entries[] =
NULL },
{ "udev", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, opt_udev_cb,
"Find devices using udev", NULL },
{ "verbose", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_verbose,
"Be more verbose", NULL },
{ "version", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_print_version,
"Print version number and exit", NULL },
{ NULL }
......
......@@ -36,6 +36,7 @@ struct _SrtInputDeviceInterface
const char * (*get_sys_path) (SrtInputDevice *device);
const char * (*get_subsystem) (SrtInputDevice *device);
gchar ** (*dup_udev_properties) (SrtInputDevice *device);
gchar * (*dup_uevent) (SrtInputDevice *device);
};
struct _SrtInputDeviceMonitorInterface
......
......@@ -135,6 +135,49 @@ srt_input_device_get_subsystem (SrtInputDevice *device)
return iface->get_subsystem (device);
}
/**
* srt_input_device_dup_uevent:
* @device: An object implementing #SrtInputDeviceInterface
*
* Return the `uevent` data from the kernel.
*
* Returns: (nullable) (transfer full): A multi-line string, or %NULL.
* Free with g_free().
*/
gchar *
srt_input_device_dup_uevent (SrtInputDevice *device)
{
SrtInputDeviceInterface *iface = SRT_INPUT_DEVICE_GET_INTERFACE (device);
g_return_val_if_fail (iface != NULL, NULL);
return iface->dup_uevent (device);
}
/*
* Default implementation: read the file in /sys. The kernel provides this,
* so it should always be present, except in containers.
*/
static gchar *
srt_input_device_default_dup_uevent (SrtInputDevice *device)
{
g_autofree gchar *uevent_path = NULL;
g_autofree gchar *contents = NULL;
const char *sys_path;
sys_path = srt_input_device_get_sys_path (device);
if (sys_path == NULL)
return NULL;
uevent_path = g_build_filename (sys_path, "uevent", NULL);
if (g_file_get_contents (uevent_path, &contents, NULL, NULL))
return g_steal_pointer (&contents);
return NULL;
}
/**
* srt_input_device_dup_udev_properties:
* @device: An object implementing #SrtInputDeviceInterface
......@@ -166,6 +209,7 @@ srt_input_device_default_init (SrtInputDeviceInterface *iface)
IMPLEMENT2 (get_sys_path, get_null_string);
IMPLEMENT2 (get_subsystem, get_null_string);
IMPLEMENT2 (dup_udev_properties, get_null_strv);
IMPLEMENT (dup_uevent);
#undef IMPLEMENT
#undef IMPLEMENT2
......
......@@ -52,6 +52,8 @@ _SRT_PUBLIC
const char *srt_input_device_get_subsystem (SrtInputDevice *device);
_SRT_PUBLIC
gchar **srt_input_device_dup_udev_properties (SrtInputDevice *device);
_SRT_PUBLIC
gchar *srt_input_device_dup_uevent (SrtInputDevice *device);
/**
* SrtInputDeviceMonitorFlags:
......
......@@ -64,6 +64,7 @@ static struct
const char *(*udev_device_get_syspath) (struct udev_device *);
struct udev_list_entry *(*udev_device_get_properties_list_entry) (struct udev_device *);
const char *(*udev_device_get_property_value) (struct udev_device *, const char *);
const char *(*udev_device_get_sysattr_value) (struct udev_device *, const char *);
struct udev_device *(*udev_device_ref) (struct udev_device *);
struct udev_device *(*udev_device_unref) (struct udev_device *);
......@@ -208,6 +209,14 @@ srt_udev_input_device_dup_udev_properties (SrtInputDevice *device)
return (gchar **) g_ptr_array_free (g_steal_pointer (&arr), FALSE);
}
static gchar *
srt_udev_input_device_dup_uevent (SrtInputDevice *device)
{
SrtUdevInputDevice *self = SRT_UDEV_INPUT_DEVICE (device);
return g_strdup (symbols.udev_device_get_sysattr_value (self->dev, "uevent"));
}
static void
srt_udev_input_device_iface_init (SrtInputDeviceInterface *iface)
{
......@@ -217,6 +226,7 @@ srt_udev_input_device_iface_init (SrtInputDeviceInterface *iface)
IMPLEMENT (get_sys_path);
IMPLEMENT (get_subsystem);
IMPLEMENT (dup_udev_properties);
IMPLEMENT (dup_uevent);
#undef IMPLEMENT
}
......@@ -380,6 +390,7 @@ srt_udev_input_device_monitor_initable_init (GInitable *initable,
SYMBOL (udev_device_get_syspath);
SYMBOL (udev_device_get_properties_list_entry);
SYMBOL (udev_device_get_property_value);
SYMBOL (udev_device_get_sysattr_value);
SYMBOL (udev_device_ref);
SYMBOL (udev_device_unref);
......
......@@ -103,6 +103,7 @@ test_input_device_usb (Fixture *f,
g_autoptr(MockInputDevice) mock_device = mock_input_device_new ();
SrtInputDevice *device = SRT_INPUT_DEVICE (mock_device);
g_auto(GStrv) udev_properties = NULL;
g_autofree gchar *uevent = NULL;
mock_device->dev_node = g_strdup ("/dev/input/event0");
mock_device->sys_path = g_strdup ("/sys/devices/mock/usb/hid/input/input0/event0");
......@@ -110,6 +111,7 @@ test_input_device_usb (Fixture *f,
mock_device->udev_properties = g_new0 (gchar *, 2);
mock_device->udev_properties[0] = g_strdup ("ID_INPUT_JOYSTICK=1");
mock_device->udev_properties[1] = NULL;
mock_device->uevent = g_strdup ("A=a\nB=b\n");
/* TODO: Fill in somewhat realistic details for a USB-attached
* Steam Controller */
......@@ -120,6 +122,9 @@ test_input_device_usb (Fixture *f,
"/sys/devices/mock/usb/hid/input/input0/event0");
g_assert_cmpstr (srt_input_device_get_subsystem (device), ==, "input");
uevent = srt_input_device_dup_uevent (device);
g_assert_cmpstr (uevent, ==, "A=a\nB=b\n");
udev_properties = srt_input_device_dup_udev_properties (device);
g_assert_nonnull (udev_properties);
g_assert_cmpstr (udev_properties[0], ==, "ID_INPUT_JOYSTICK=1");
......@@ -158,8 +163,12 @@ device_added_cb (SrtInputDeviceMonitor *monitor,
* so we have to just emit debug messages. */
if (f->config->type == MOCK)
{
g_autofree gchar *uevent = NULL;
g_auto(GStrv) udev_properties = NULL;
uevent = srt_input_device_dup_uevent (device);
g_assert_cmpstr (uevent, ==, "ONE=1\nTWO=2\n");
udev_properties = srt_input_device_dup_udev_properties (device);
g_assert_nonnull (udev_properties);
g_assert_cmpstr (udev_properties[0], ==, "ID_INPUT_JOYSTICK=1");
......
......@@ -64,6 +64,7 @@ mock_input_device_finalize (GObject *object)
g_clear_pointer (&self->dev_node, g_free);
g_clear_pointer (&self->subsystem, g_free);
g_clear_pointer (&self->udev_properties, g_strfreev);
g_clear_pointer (&self->uevent, g_free);
G_OBJECT_CLASS (mock_input_device_parent_class)->finalize (object);
}
......@@ -108,6 +109,14 @@ mock_input_device_dup_udev_properties (SrtInputDevice *device)
return g_strdupv (self->udev_properties);
}
static gchar *
mock_input_device_dup_uevent (SrtInputDevice *device)
{
MockInputDevice *self = MOCK_INPUT_DEVICE (device);
return g_strdup (self->uevent);
}
static void
mock_input_device_iface_init (SrtInputDeviceInterface *iface)
{
......@@ -117,6 +126,7 @@ mock_input_device_iface_init (SrtInputDeviceInterface *iface)
IMPLEMENT (get_sys_path);
IMPLEMENT (get_subsystem);
IMPLEMENT (dup_udev_properties);
IMPLEMENT (dup_uevent);
#undef IMPLEMENT
}
......@@ -271,6 +281,7 @@ add_steam_controller (MockInputDeviceMonitor *self,
device->sys_path = g_strdup_printf ("/sys/devices/mock/usb/hid/input/input0/event%s",
tail);
device->subsystem = g_strdup ("input");
device->uevent = g_strdup ("ONE=1\nTWO=2\n");
g_ptr_array_add (arr, g_strdup ("ID_INPUT_JOYSTICK=1"));
g_ptr_array_add (arr, NULL);
......
......@@ -53,6 +53,7 @@ struct _MockInputDevice
gchar *dev_node;
gchar *subsystem;
gchar **udev_properties;
gchar *uevent;
};
struct _MockInputDeviceClass
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment