From e13e6ce071d27f4068b8e4f1926db0e6fb735c5b Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 21 May 2010 04:11:58 +0000 Subject: [PATCH] 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 --- legacy/eeze/configure.ac | 8 +- legacy/eeze/src/bin/eeze_udev_test.c | 15 +-- legacy/eeze/src/lib/udev/Eeze_Udev.h | 3 + legacy/eeze/src/lib/udev/Makefile.am | 1 + legacy/eeze/src/lib/udev/eeze_udev.c | 54 ++-------- legacy/eeze/src/lib/udev/eeze_udev_find.c | 25 +++-- legacy/eeze/src/lib/udev/eeze_udev_private.c | 22 ++-- legacy/eeze/src/lib/udev/eeze_udev_private.h | 2 +- legacy/eeze/src/lib/udev/eeze_udev_walk.c | 104 +++++++++++++++++++ legacy/eeze/src/lib/udev/eeze_udev_watch.c | 8 +- 10 files changed, 159 insertions(+), 83 deletions(-) create mode 100644 legacy/eeze/src/lib/udev/eeze_udev_walk.c diff --git a/legacy/eeze/configure.ac b/legacy/eeze/configure.ac index 480e6eebcf..44f0318ae9 100644 --- a/legacy/eeze/configure.ac +++ b/legacy/eeze/configure.ac @@ -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"]) diff --git a/legacy/eeze/src/bin/eeze_udev_test.c b/legacy/eeze/src/bin/eeze_udev_test.c index 4545140978..19da721d54 100644 --- a/legacy/eeze/src/bin/eeze_udev_test.c +++ b/legacy/eeze/src/bin/eeze_udev_test.c @@ -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 diff --git a/legacy/eeze/src/lib/udev/Eeze_Udev.h b/legacy/eeze/src/lib/udev/Eeze_Udev.h index 8d9c38a096..9476b6f6b1 100644 --- a/legacy/eeze/src/lib/udev/Eeze_Udev.h +++ b/legacy/eeze/src/lib/udev/Eeze_Udev.h @@ -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); diff --git a/legacy/eeze/src/lib/udev/Makefile.am b/legacy/eeze/src/lib/udev/Makefile.am index cc18f48284..20cb556d46 100644 --- a/legacy/eeze/src/lib/udev/Makefile.am +++ b/legacy/eeze/src/lib/udev/Makefile.am @@ -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@ diff --git a/legacy/eeze/src/lib/udev/eeze_udev.c b/legacy/eeze/src/lib/udev/eeze_udev.c index c75c6cd33f..a813f013ef 100644 --- a/legacy/eeze/src/lib/udev/eeze_udev.c +++ b/legacy/eeze/src/lib/udev/eeze_udev.c @@ -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; -} diff --git a/legacy/eeze/src/lib/udev/eeze_udev_find.c b/legacy/eeze/src/lib/udev/eeze_udev_find.c index d239170022..e781a683ec 100644 --- a/legacy/eeze/src/lib/udev/eeze_udev_find.c +++ b/legacy/eeze/src/lib/udev/eeze_udev_find.c @@ -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"))) diff --git a/legacy/eeze/src/lib/udev/eeze_udev_private.c b/legacy/eeze/src/lib/udev/eeze_udev_private.c index 6002865e86..6569dc39fb 100644 --- a/legacy/eeze/src/lib/udev/eeze_udev_private.c +++ b/legacy/eeze/src/lib/udev/eeze_udev_private.c @@ -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) diff --git a/legacy/eeze/src/lib/udev/eeze_udev_private.h b/legacy/eeze/src/lib/udev/eeze_udev_private.h index cd37edfa50..493a2123a6 100644 --- a/legacy/eeze/src/lib/udev/eeze_udev_private.h +++ b/legacy/eeze/src/lib/udev/eeze_udev_private.h @@ -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 diff --git a/legacy/eeze/src/lib/udev/eeze_udev_walk.c b/legacy/eeze/src/lib/udev/eeze_udev_walk.c new file mode 100644 index 0000000000..6adc35cab1 --- /dev/null +++ b/legacy/eeze/src/lib/udev/eeze_udev_walk.c @@ -0,0 +1,104 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#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; +} diff --git a/legacy/eeze/src/lib/udev/eeze_udev_watch.c b/legacy/eeze/src/lib/udev/eeze_udev_watch.c index 06be96b51b..6548b16976 100644 --- a/legacy/eeze/src/lib/udev/eeze_udev_watch.c +++ b/legacy/eeze/src/lib/udev/eeze_udev_watch.c @@ -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")))