pretty huge overhaul:

test app should be a bit more robust now
udev compat code is done (I think?)
added udev walk functions for easier device checking
fixed some potential segv in cases where errors checking was not complete enough


SVN revision: 49081
This commit is contained in:
Mike Blumenkrantz 2010-05-21 04:11:58 +00:00
parent 0cae05c2a8
commit e13e6ce071
10 changed files with 159 additions and 83 deletions

View File

@ -60,9 +60,11 @@ AS_IF(
[PKG_CHECK_MODULES(UDEV, libudev, [], [enable_eeze_udev="no"])]
)
udev_version=$(pkg-config udev --version | cut -d. -f2)
if test $udev_version -lt 23;then
AC_DEFINE([OLD_UDEV_RRRRRRRRRRRRRR],[1],[compat functionality for udev < 0.23])
udev_version=$(pkg-config libudev --modversion)
if test $udev_version -lt 142;then
AC_MSG_WARN([Old udev version detected, enabling compat code])
AC_DEFINE([OLD_UDEV_RRRRRRRRRRRRRR],[1],[compat functionality for udev < 142])
fi
AM_CONDITIONAL([BUILD_EEZE_UDEV], [test "x${enable_eeze_udev}" = "xyes"])

View File

@ -16,23 +16,19 @@ catch_events(const char *device, const char *event, void *data, Eeze_Udev_Watch
kbdmouse *akbdmouse = data;
Eina_List *l;
const char *name, *dev, *type;
int new = 0;
/* the device that comes through will be prefixed by "/sys"
* but the saved name will not, so we check for the saved name
* inside the device name
*/
EINA_LIST_FOREACH(akbdmouse->kbds, l, name)
if (strstr(device, name)) goto end;
if (strncmp(device + 5, name, strlen(device + 5) - 8)) goto end;
EINA_LIST_FOREACH(akbdmouse->mice, l, name)
if (strstr(device, name)) goto end;
if (strncmp(device + 5, name, strlen(device + 5) - 8)) goto end;
/* check to see if the device was just plugged in */
if (eeze_udev_syspath_is_kbd(device) || eeze_udev_syspath_is_mouse(device))
{
new = 1;
goto end;
}
goto end;
/* if we reach here, the device is neither a keyboard nor a mouse that we saw
* previously, so we print a moderately amusing message and bail
*/
@ -44,7 +40,7 @@ end:
* we can retrieve them now even though the device has been removed and
* is inaccessible to udev
*/
if (new)
if (!strcmp(event, "add"))
{
dev = eeze_udev_syspath_get_devpath(device);
type = "plugged in";
@ -119,8 +115,7 @@ int main()
{ /* add the devpath to the hash for use in the cb later */
if ((check = eeze_udev_syspath_get_devpath(name)))
eina_hash_direct_add(hash, name, check); /* get a property using the device's syspath */
if ((check = eeze_udev_syspath_get_property(name, "ID_VENDOR")))
printf("Found mouse %s with vendor: %s\n", name, check);
printf("Found mouse %s with vendor: %s\n", name, eeze_udev_walk_get_sysattr(name, "manufacturer"));
}
/* we save this list for later, because once a device is unplugged it can
* no longer be detected by udev, and any related properties are unusable unless

View File

@ -139,6 +139,9 @@ extern "C" {
EAPI Eina_Bool eeze_udev_syspath_is_mouse(const char *syspath);
EAPI Eina_Bool eeze_udev_syspath_is_kbd(const char *syspath);
EAPI Eina_Bool eeze_udev_syspath_is_touchpad(const char *syspath);
EAPI Eina_Bool eeze_udev_walk_check_sysattr(const char *syspath, const char *sysattr, const char *value);
EAPI const char *eeze_udev_walk_get_sysattr(const char *syspath, const char *sysattr);
EAPI Eeze_Udev_Watch *eeze_udev_watch_add(Eeze_Udev_Type type, int event, void(*func)(const char *, const char *, void *, Eeze_Udev_Watch *), void *user_data);
EAPI void *eeze_udev_watch_del(Eeze_Udev_Watch *watch);

View File

@ -15,6 +15,7 @@ eeze_udev.c \
eeze_udev_watch.c \
eeze_udev_main.c \
eeze_udev_find.c \
eeze_udev_walk.c \
eeze_udev_private.c
libeeze_udev_la_LIBADD = @ECORE_LIBS@ @UDEV_LIBS@

View File

@ -118,9 +118,10 @@ eeze_udev_syspath_get_devpath(const char *syspath)
eina_strbuf_append(sbuf, syspath);
device = udev_device_new_from_syspath(udev, eina_strbuf_string_get(sbuf));
if ((udev_device_get_property_value(device, "DEVNAME")))
name = eina_stringshare_add(eina_strbuf_string_get(sbuf));
if (!(name = udev_device_get_property_value(device, "DEVNAME")))
return NULL;
name = eina_stringshare_add(name);
udev_device_unref(device);
udev_unref(udev);
eina_strbuf_free(sbuf);
@ -356,7 +357,7 @@ eeze_udev_syspath_is_mouse(const char *syspath)
device = udev_device_new_from_syspath(udev, eina_strbuf_string_get(sbuf));
#ifdef OLD_UDEV_RRRRRRRRRRRRRR
mouse = _walk_parents_for_attr(device, "bInterfaceProtocol", "02");
mouse = _walk_parents_test_attr(device, "bInterfaceProtocol", "02");
if (!mouse)
{
test = udev_device_get_property_value(device, "ID_CLASS");
@ -403,7 +404,7 @@ eeze_udev_syspath_is_kbd(const char *syspath)
device = udev_device_new_from_syspath(udev, eina_strbuf_string_get(sbuf));
#ifdef OLD_UDEV_RRRRRRRRRRRRRR
kbd = _walk_parents_for_attr(device, "bInterfaceProtocol", "01");
kbd = _walk_parents_test_attr(device, "bInterfaceProtocol", "01");
if (!kbd)
{
test = udev_device_get_property_value(device, "ID_CLASS");
@ -437,7 +438,6 @@ eeze_udev_syspath_is_touchpad(const char *syspath)
struct udev_device *device;
Eina_Bool touchpad = 0;
Eina_Strbuf *sbuf;
const char *test = NULL;
if (!syspath) return 0;
udev = udev_new();
@ -450,7 +450,7 @@ eeze_udev_syspath_is_touchpad(const char *syspath)
device = udev_device_new_from_syspath(udev, eina_strbuf_string_get(sbuf));
#ifdef OLD_UDEV_RRRRRRRRRRRRRR
touchpad = _walk_parents_for_attr(device, "resolution", NULL);
touchpad = _walk_parents_test_attr(device, "resolution", NULL);
#else
test = udev_device_get_property_value(device, "ID_INPUT_TOUCHPAD");
if (test) touchpad = atoi(test);
@ -461,45 +461,3 @@ eeze_udev_syspath_is_touchpad(const char *syspath)
return touchpad;
}
/**
* Walks up the device chain starting at @p syspath,
* checking each device for @p sysattr with (optional) @p value.
*
* @param syspath The /sys/ path of the device to start at, with or without the /sys/
* @param sysattr The attribute to find
* @param value OPTIONAL: The value that @p sysattr should have, or NULL
*
* @return If the sysattr (with value) is found, returns TRUE. Else, false.
*/
EAPI Eina_Bool
eeze_udev_syspath_check_sysattr(const char *syspath, const char *sysattr, const char *value)
{
struct udev *udev;
struct udev_device *device, *child, *parent;
Eina_Strbuf *sbuf;
const char *test = NULL;
if (!syspath) return 0;
udev = udev_new();
if (!udev) return 0;
sbuf = eina_strbuf_new();
if (!strstr(syspath, "/sys/"))
eina_strbuf_append(sbuf, "/sys/");
eina_strbuf_append(sbuf, syspath);
device = udev_device_new_from_syspath(udev, eina_strbuf_string_get(sbuf));
for (parent = device; parent; child = parent, parent = udev_device_get_parent(child))
{
if ((test = udev_device_get_sysattr_value(parent, sysattr)))
if ((value) && (!strcmp(test, value)))
{
eina_strbuf_free(sbuf);
return 1;
}
}
eina_strbuf_free(sbuf);
return 0;
}

View File

@ -117,14 +117,15 @@ eeze_udev_find_unlisted_similar(Eina_List *list)
return;
}
device = udev_device_new_from_syspath(udev, dev);
vendor = udev_device_get_property_value(device, "ID_VENDOR_ID");
if (vendor)
if ((vendor = udev_device_get_property_value(device, "ID_VENDOR_ID")))
udev_enumerate_add_match_property(en, "ID_VENDOR_ID", vendor);
model = udev_device_get_property_value(device, "ID_MODEL_ID");
if (model)
else if ((vendor = udev_device_get_property_value(device, "ID_VENDOR")))
udev_enumerate_add_match_property(en, "ID_VENDOR", vendor);
if ((model = udev_device_get_property_value(device, "ID_MODEL_ID")))
udev_enumerate_add_match_property(en, "ID_MODEL_ID", model);
revision = udev_device_get_property_value(device, "ID_REVISION");
if (revision)
else if ((model = udev_device_get_property_value(device, "ID_MODEL")))
udev_enumerate_add_match_property(en, "ID_MODEL", model);
if ((revision = udev_device_get_property_value(device, "ID_REVISION")))
udev_enumerate_add_match_property(en, "ID_REVISION", revision);
udev_enumerate_scan_devices(en);
@ -185,15 +186,25 @@ eeze_udev_find_by_type(const Eeze_Udev_Type etype, const char *name)
break;
case EEZE_UDEV_TYPE_KEYBOARD:
udev_enumerate_add_match_subsystem(en, "input");
#ifndef OLD_UDEV_RRRRRRRRRRRRRR
udev_enumerate_add_match_property(en, "ID_INPUT_KEYBOARD", "1");
#else
udev_enumerate_add_match_property(en, "ID_CLASS", "kbd");
#endif
break;
case EEZE_UDEV_TYPE_MOUSE:
udev_enumerate_add_match_subsystem(en, "input");
#ifndef OLD_UDEV_RRRRRRRRRRRRRR
udev_enumerate_add_match_property(en, "ID_INPUT_MOUSE", "1");
#else
udev_enumerate_add_match_property(en, "ID_CLASS", "mouse");
#endif
break;
case EEZE_UDEV_TYPE_TOUCHPAD:
udev_enumerate_add_match_subsystem(en, "input");
#ifndef OLD_UDEV_RRRRRRRRRRRRRR
udev_enumerate_add_match_property(en, "ID_INPUT_TOUCHPAD", "1");
#endif
break;
case EEZE_UDEV_TYPE_DRIVE_MOUNTABLE:
udev_enumerate_add_match_subsystem(en, "block");
@ -245,7 +256,7 @@ eeze_udev_find_by_type(const Eeze_Udev_Type etype, const char *name)
if (etype == EEZE_UDEV_TYPE_IS_IT_HOT_OR_IS_IT_COLD_SENSOR)
{/* ensure that temp input exists somewhere in this device chain */
if (!_walk_parents_for_attr(device, "temp1_input", NULL))
if (!_walk_parents_test_attr(device, "temp1_input", NULL))
goto out;
/* if device is not the one which has the temp input, we must go up the chain */
if (!(test = udev_device_get_sysattr_value(device, "temp1_input")))

View File

@ -11,7 +11,7 @@
* with value $value
*/
Eina_Bool
_walk_parents_for_attr(struct udev_device *device, const char *sysattr, const char* value)
_walk_parents_test_attr(struct udev_device *device, const char *sysattr, const char* value)
{
struct udev_device *parent, *child = device;
const char *test;
@ -44,20 +44,22 @@ _get_unlisted_parents(Eina_List *list, struct udev_device *device)
Eina_List *l;
Eina_Bool found;
vendor = udev_device_get_property_value(child, "ID_VENDOR_ID");
model = udev_device_get_property_value(child, "ID_MODEL_ID");
if (!(vendor = udev_device_get_property_value(child, "ID_VENDOR_ID")))
vendor = udev_device_get_property_value(child, "ID_VENDOR");
if (!(model = udev_device_get_property_value(child, "ID_MODEL_ID")))
model = udev_device_get_property_value(child, "ID_MODEL");
parent = udev_device_get_parent(child);
for (; parent; child = parent, parent = udev_device_get_parent(child))
{
found = 0;
model2 = udev_device_get_property_value(parent, "ID_MODEL_ID");
vendor2 = udev_device_get_property_value(parent, "ID_VENDOR_ID");
if ((!model2 && model) || (model2 && !model))
if (!(vendor2 = udev_device_get_property_value(child, "ID_VENDOR_ID")))
vendor2 = udev_device_get_property_value(child, "ID_VENDOR");
if (!(model2 = udev_device_get_property_value(child, "ID_MODEL_ID")))
model2 = udev_device_get_property_value(child, "ID_MODEL");
if ((!model2 && model) || (model2 && !model) || (!vendor2 && vendor) || (vendor2 && !vendor))
break;
else if ((!vendor2 && vendor) || (vendor2 && !vendor))
break;
else if (strcmp(model, model2) ||
strcmp(vendor, vendor2))
else if (((model && model2) && (strcmp(model, model2))) ||
((vendor && vendor2) && (strcmp(vendor, vendor2))))
break;
devname = udev_device_get_syspath(parent);
EINA_LIST_FOREACH(list, l, test)

View File

@ -24,7 +24,7 @@ extern int _e_eeze_udev_log_dom;
#define ERR(...) EINA_LOG_DOM_ERR(_e_eeze_udev_log_dom, __VA_ARGS__)
/* from watch.c */
Eina_Bool _walk_parents_for_attr(struct udev_device *device, const char *sysattr, const char* value);
Eina_Bool _walk_parents_test_attr(struct udev_device *device, const char *sysattr, const char* value);
void _get_unlisted_parents(Eina_List *list, struct udev_device *device);
#endif

View File

@ -0,0 +1,104 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <Eeze_Udev.h>
#include "eeze_udev_private.h"
/**
* Walks up the device chain starting at @p syspath,
* checking each device for @p sysattr with (optional) @p value.
*
* @param syspath The /sys/ path of the device to start at, with or without the /sys/
* @param sysattr The attribute to find
* @param value OPTIONAL: The value that @p sysattr should have, or NULL
*
* @return If the sysattr (with value) is found, returns TRUE. Else, false.
*/
EAPI Eina_Bool
eeze_udev_walk_check_sysattr(const char *syspath, const char *sysattr, const char *value)
{
struct udev *udev;
struct udev_device *device, *child, *parent;
Eina_Strbuf *sbuf;
const char *test = NULL;
if (!syspath) return 0;
udev = udev_new();
if (!udev) return 0;
sbuf = eina_strbuf_new();
if (!strstr(syspath, "/sys/"))
eina_strbuf_append(sbuf, "/sys/");
eina_strbuf_append(sbuf, syspath);
device = udev_device_new_from_syspath(udev, eina_strbuf_string_get(sbuf));
for (parent = device; parent; child = parent, parent = udev_device_get_parent(child))
{
if ((test = udev_device_get_sysattr_value(parent, sysattr)))
{
if (value)
{
if (!strcmp(test, value))
{
eina_strbuf_free(sbuf);
udev_device_unref(device);
return 1;
}
}
else
{
eina_strbuf_free(sbuf);
udev_device_unref(device);
return 1;
}
}
}
eina_strbuf_free(sbuf);
udev_device_unref(device);
return 0;
}
/**
* Walks up the device chain starting at @p syspath,
* checking each device for @p sysattr, and returns the value if found.
*
* @param syspath The /sys/ path of the device to start at, with or without the /sys/
* @param sysattr The attribute to find
*
* @return The value of @p sysattr if found, or NULL
*/
EAPI const char*
eeze_udev_walk_get_sysattr(const char *syspath, const char *sysattr)
{
struct udev *udev;
struct udev_device *device, *child, *parent;
Eina_Strbuf *sbuf;
const char *test = NULL;
if (!syspath) return NULL;
udev = udev_new();
if (!udev) return NULL;
sbuf = eina_strbuf_new();
if (!strstr(syspath, "/sys/"))
eina_strbuf_append(sbuf, "/sys/");
eina_strbuf_append(sbuf, syspath);
device = udev_device_new_from_syspath(udev, eina_strbuf_string_get(sbuf));
for (parent = device; parent; child = parent, parent = udev_device_get_parent(child))
{
if ((test = udev_device_get_sysattr_value(parent, sysattr)))
{
eina_strbuf_free(sbuf);
test = eina_stringshare_add(test);
udev_device_unref(device);
return test;
}
}
eina_strbuf_free(sbuf);
udev_device_unref(device);
return NULL;
}

View File

@ -52,7 +52,7 @@ _get_syspath_from_watch(void *data, Ecore_Fd_Handler *fd_handler)
if ((!(test = udev_device_get_subsystem(device))) || (strcmp(test, "input")))
goto error;
test = udev_device_get_property_value(device, "ID_CLASS");
if ((_walk_parents_for_attr(device, "bInterfaceProtocol", "01")) || ((test) && (!strcmp(test, "kbd"))))
if ((_walk_parents_test_attr(device, "bInterfaceProtocol", "01")) || ((test) && (!strcmp(test, "kbd"))))
break;
goto error;
#endif
@ -64,7 +64,7 @@ _get_syspath_from_watch(void *data, Ecore_Fd_Handler *fd_handler)
if ((!(test = udev_device_get_subsystem(device))) || (strcmp(test, "input")))
goto error;
test = udev_device_get_property_value(device, "ID_CLASS");
if ((_walk_parents_for_attr(device, "bInterfaceProtocol", "02")) || ((test) && (!strcmp(test, "mouse"))))
if ((_walk_parents_test_attr(device, "bInterfaceProtocol", "02")) || ((test) && (!strcmp(test, "mouse"))))
break;
goto error;
#endif
@ -75,7 +75,7 @@ _get_syspath_from_watch(void *data, Ecore_Fd_Handler *fd_handler)
#ifdef OLD_UDEV_RRRRRRRRRRRRRR
if ((!(test = udev_device_get_subsystem(device))) || (strcmp(test, "input")))
goto error;
if (_walk_parents_for_attr(device, "resolution", NULL))
if (_walk_parents_test_attr(device, "resolution", NULL))
break;
goto error;
#endif
@ -142,7 +142,7 @@ _get_syspath_from_watch(void *data, Ecore_Fd_Handler *fd_handler)
if ((!(test = udev_device_get_subsystem(device))) || (strcmp(test, "hwmon")))
goto error;
#endif /* have to do stuff up here since we need info from the parent */
if (!_walk_parents_for_attr(device, "temp1_input", NULL))
if (!_walk_parents_test_attr(device, "temp1_input", NULL))
goto error;
/* if device is not the one which has the temp input, we must go up the chain */
if (!(test = udev_device_get_sysattr_value(device, "temp1_input")))