From 567664a1a3e9311e68872cb55c200d9123872310 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Mon, 17 May 2010 02:59:07 +0000 Subject: [PATCH] massive update. strbuf fixes, new functions, more compat for old udev, updates to test app, version bump, use config.h, split more functions into other files SVN revision: 48935 --- legacy/eeze/Makefile.am | 2 +- legacy/eeze/configure.ac | 5 +- legacy/eeze/src/bin/eeze_udev_test.c | 39 +- legacy/eeze/src/lib/udev/Eeze_Udev.h | 6 +- legacy/eeze/src/lib/udev/Makefile.am | 6 +- legacy/eeze/src/lib/udev/eeze_udev.c | 243 +++++-------- legacy/eeze/src/lib/udev/eeze_udev_find.c | 357 +++++++++++++++++++ legacy/eeze/src/lib/udev/eeze_udev_private.c | 73 ++++ legacy/eeze/src/lib/udev/eeze_udev_private.h | 6 +- legacy/eeze/src/lib/udev/eeze_udev_watch.c | 32 +- 10 files changed, 565 insertions(+), 204 deletions(-) create mode 100644 legacy/eeze/src/lib/udev/eeze_udev_find.c create mode 100644 legacy/eeze/src/lib/udev/eeze_udev_private.c diff --git a/legacy/eeze/Makefile.am b/legacy/eeze/Makefile.am index 69beee2f54..d0319f4e24 100644 --- a/legacy/eeze/Makefile.am +++ b/legacy/eeze/Makefile.am @@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS = -I m4 SUBDIRS = src doc -MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in \ +MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in* \ config.log config.sub configure depcomp \ install-sh ltmain.sh missing compile eeze*doc*tar* \ m4/l* diff --git a/legacy/eeze/configure.ac b/legacy/eeze/configure.ac index e7623edaf9..480e6eebcf 100644 --- a/legacy/eeze/configure.ac +++ b/legacy/eeze/configure.ac @@ -1,7 +1,7 @@ # get rid of that stupid cache mechanism rm -f config.cache -AC_INIT([eeze], [0.0.1], [enlightenment-devel@lists.sourceforge.net]) +AC_INIT([eeze], [0.1.0], [enlightenment-devel@lists.sourceforge.net]) release="ver-pre-svn-05" AC_PREREQ([2.52]) AC_CONFIG_SRCDIR([configure.ac]) @@ -62,8 +62,7 @@ AS_IF( udev_version=$(pkg-config udev --version | cut -d. -f2) if test $udev_version -lt 23;then - EEZE_UDEV_CFLAGS="-DOLD_UDEV_RRRRRRRRRRRRRR" - AC_SUBST(EEZE_UDEV_CFLAGS) + AC_DEFINE([OLD_UDEV_RRRRRRRRRRRRRR],[1],[compat functionality for udev < 0.23]) 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 800d6b9d13..d63a2d8530 100644 --- a/legacy/eeze/src/bin/eeze_udev_test.c +++ b/legacy/eeze/src/bin/eeze_udev_test.c @@ -94,9 +94,15 @@ int main() printf("For my first trick, I will find all of your keyboards and return their syspaths.\n"); /* find all keyboards using type EEZE_UDEV_TYPE_KEYBOARD */ type = eeze_udev_find_by_type(EEZE_UDEV_TYPE_KEYBOARD, NULL); + /* add all "link" devices that aren't explicitly found, but are still + * part of the device chain + */ + eeze_udev_find_unlisted_similar(type); EINA_LIST_FOREACH(type, l, name) - { /* add the devpath to the hash for use in the cb later */ - eina_hash_direct_add(hash, name, eeze_udev_syspath_get_devpath(name)); + { + /* 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); printf("Found keyboard: %s\n", name); } /* we save this list for later, because once a device is unplugged it can @@ -108,10 +114,13 @@ int main() printf("\nNext, I will find all of your mice and print the corresponding manufacturer.\n"); /* find all mice using type EEZE_UDEV_TYPE_MOUSE */ type = eeze_udev_find_by_type(EEZE_UDEV_TYPE_MOUSE, NULL); + eeze_udev_find_unlisted_similar(type); EINA_LIST_FOREACH(type, l, name) { /* add the devpath to the hash for use in the cb later */ - eina_hash_direct_add(hash, name, eeze_udev_syspath_get_devpath(name)); /* get a property using the device's syspath */ - printf("Found mouse %s with vendor: %s\n", name, eeze_udev_syspath_get_property(name, "ID_VENDOR")); + 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); } /* 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 @@ -122,21 +131,26 @@ int main() printf("\nNow let's try something a little more difficult. Mountable filesystems!\n"); /* find all mountable drives using type EEZE_UDEV_TYPE_DRIVE_MOUNTABLE */ type = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_MOUNTABLE, NULL); + eeze_udev_find_unlisted_similar(type); EINA_LIST_FOREACH(type, l, name) { printf("Found device: %s\n", name); /* get a property using the device's syspath */ printf("\tYou probably know it better as %s\n", eeze_udev_syspath_get_property(name, "DEVNAME")); - printf("\tIt's formatted as %s", eeze_udev_syspath_get_property(name, "ID_FS_TYPE")); - check = eeze_udev_syspath_get_property(name, "FSTAB_DIR"); - if (check) - printf(", and gets mounted at %s", check); - printf("!\n"); + if ((check = eeze_udev_syspath_get_property(name, "ID_FS_TYPE"))) + { + printf("\tIt's formatted as %s", check); + check = eeze_udev_syspath_get_property(name, "FSTAB_DIR"); + if (check) + printf(", and gets mounted at %s", check); + printf("!\n"); + } } eina_list_free(type); printf("\nInternal drives, anyone? With serial numbers?\n"); /* find all internal drives using type EEZE_UDEV_TYPE_DRIVE_INTERNAL */ type = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_INTERNAL, NULL); + eeze_udev_find_unlisted_similar(type); EINA_LIST_FOREACH(type, l, name) /* get a property using the device's syspath */ printf("%s: %s\n", name, eeze_udev_syspath_get_property(name, "ID_SERIAL")); eina_list_free(type); @@ -144,9 +158,12 @@ int main() printf("\nGot any removables? I'm gonna find em!\n"); /* find all removable media using type EEZE_UDEV_TYPE_DRIVE_REMOVABLE */ type = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_REMOVABLE, NULL); + eeze_udev_find_unlisted_similar(type); EINA_LIST_FOREACH(type, l, name) /* get a property using the device's syspath */ - printf("\tOoh, a %s attached on your %s bus!\n", eeze_udev_syspath_get_property(name, "ID_MODEL"), - eeze_udev_syspath_get_property(name, "ID_BUS")); + { + if ((check = eeze_udev_syspath_get_property(name, "ID_MODEL"))) + printf("\tOoh, a %s attached on your %s bus!\n", check, eeze_udev_syspath_get_property(name, "ID_BUS")); + } eina_list_free(type); diff --git a/legacy/eeze/src/lib/udev/Eeze_Udev.h b/legacy/eeze/src/lib/udev/Eeze_Udev.h index d6e95a221f..9305da5f7e 100644 --- a/legacy/eeze/src/lib/udev/Eeze_Udev.h +++ b/legacy/eeze/src/lib/udev/Eeze_Udev.h @@ -111,10 +111,14 @@ extern "C" { EAPI int eeze_udev_init(void); EAPI int eeze_udev_shutdown(void); + EAPI Eina_List *eeze_udev_find_similar_from_syspath(const char *syspath); + EAPI void eeze_udev_find_unlisted_similar(Eina_List *list); + EAPI Eina_List *eeze_udev_find_by_sysattr(const char *sysattr, const char *value); EAPI Eina_List *eeze_udev_find_by_type(const Eeze_Udev_Type type, const char *name); EAPI Eina_List *eeze_udev_find_by_filter(const char *subsystem, const char *type, const char *name); - EAPI const char *eeze_udev_syspath_rootdev_get(const char *syspath); + EAPI const char *eeze_udev_syspath_get_parent(const char *syspath); + EAPI Eina_List *eeze_udev_syspath_get_parents(const char *syspath); EAPI const char *eeze_udev_syspath_get_devpath(const char *syspath); EAPI const char *eeze_udev_syspath_get_subsystem(const char *syspath); EAPI const char *eeze_udev_syspath_get_property(const char *syspath, const char *property); diff --git a/legacy/eeze/src/lib/udev/Makefile.am b/legacy/eeze/src/lib/udev/Makefile.am index 5102a20d81..cc18f48284 100644 --- a/legacy/eeze/src/lib/udev/Makefile.am +++ b/legacy/eeze/src/lib/udev/Makefile.am @@ -1,6 +1,6 @@ MAINTAINERCLEANFILES = Makefile.in -AM_CPPFLAGS = @ECORE_CFLAGS@ @EEZE_UDEV_CFLAGS@ +AM_CPPFLAGS = @ECORE_CFLAGS@ if BUILD_EEZE_UDEV @@ -13,7 +13,9 @@ libeeze_udev_la_SOURCES = \ Eeze_Udev.h \ eeze_udev.c \ eeze_udev_watch.c \ -eeze_udev_main.c +eeze_udev_main.c \ +eeze_udev_find.c \ +eeze_udev_private.c libeeze_udev_la_LIBADD = @ECORE_LIBS@ @UDEV_LIBS@ libeeze_udev_la_LDFLAGS = -no-undefined -version-info @version_info@ @eeze_udev_release_info@ diff --git a/legacy/eeze/src/lib/udev/eeze_udev.c b/legacy/eeze/src/lib/udev/eeze_udev.c index bca7293942..76ff4a2adc 100644 --- a/legacy/eeze/src/lib/udev/eeze_udev.c +++ b/legacy/eeze/src/lib/udev/eeze_udev.c @@ -1,8 +1,9 @@ -#include "eeze_udev_private.h" -#include +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif -/* from watch.c */ -Eina_Bool _walk_parents_for_attr(struct udev_device *device, const char *sysattr, const char* value); +#include +#include "eeze_udev_private.h" /** * @defgroup udev udev @@ -21,7 +22,7 @@ Eina_Bool _walk_parents_for_attr(struct udev_device *device, const char *sysattr * @ingroup udev */ EAPI const char * -eeze_udev_syspath_rootdev_get(const char *syspath) +eeze_udev_syspath_get_parent(const char *syspath) { struct udev *udev; struct udev_device *device, *parent; @@ -49,167 +50,46 @@ eeze_udev_syspath_rootdev_get(const char *syspath) } /** - * Find devices using a EEZE_UDEV_TYPE_* and/or a name. + * Returns a list of all parent device syspaths for @p syspath. * - * @param type A Eeze_Udev_Type or 0 - * @param name A filter for the device name or NULL - * @return A Eina_List* of matched devices or NULL on failure - * - * Return a list of syspaths (/sys/$syspath) for matching udev devices. + * @param syspath The device to find parents of + * @return A list of the parent devices of @p syspath * * @ingroup udev */ EAPI Eina_List * -eeze_udev_find_by_type(const Eeze_Udev_Type etype, const char *name) +eeze_udev_syspath_get_parents(const char *syspath) { struct udev *udev; - struct udev_enumerate *en; - struct udev_list_entry *devs, *cur; - struct udev_device *device; - const char *devname; - Eina_List *ret = NULL; - - if ((!etype) && (!name)) return NULL; + struct udev_device *child, *parent, *device; + const char *path; + Eina_Strbuf *sbuf; + Eina_List *devlist = NULL; + if (!syspath) return NULL; udev = udev_new(); if (!udev) return NULL; - en = udev_enumerate_new(udev); - if (!en) return NULL; + + sbuf = eina_strbuf_new(); + if (!strstr(syspath, "/sys/")) + eina_strbuf_append(sbuf, "/sys/"); + eina_strbuf_append(sbuf, syspath); - switch (etype) - { - case EEZE_UDEV_TYPE_NONE: - break; - case EEZE_UDEV_TYPE_KEYBOARD: - udev_enumerate_add_match_subsystem(en, "input"); - udev_enumerate_add_match_property(en, "ID_INPUT_KEYBOARD", "1"); - break; - case EEZE_UDEV_TYPE_MOUSE: - udev_enumerate_add_match_subsystem(en, "input"); - udev_enumerate_add_match_property(en, "ID_INPUT_MOUSE", "1"); - break; - case EEZE_UDEV_TYPE_TOUCHPAD: - udev_enumerate_add_match_subsystem(en, "input"); - udev_enumerate_add_match_property(en, "ID_INPUT_TOUCHPAD", "1"); - break; - case EEZE_UDEV_TYPE_DRIVE_MOUNTABLE: - udev_enumerate_add_match_subsystem(en, "block"); - udev_enumerate_add_match_property(en, "ID_FS_USAGE", "filesystem"); - udev_enumerate_add_nomatch_sysattr(en, "capability", "52"); - break; - case EEZE_UDEV_TYPE_DRIVE_INTERNAL: - udev_enumerate_add_match_subsystem(en, "block"); - udev_enumerate_add_match_property(en, "ID_TYPE", "disk"); - udev_enumerate_add_match_property(en, "ID_BUS", "ata"); - udev_enumerate_add_match_sysattr(en, "removable", "0"); - break; - case EEZE_UDEV_TYPE_DRIVE_REMOVABLE: - udev_enumerate_add_match_subsystem(en, "block"); - udev_enumerate_add_match_property(en, "ID_TYPE", "disk"); - udev_enumerate_add_match_sysattr(en, "removable", "1"); - break; - case EEZE_UDEV_TYPE_DRIVE_CDROM: - udev_enumerate_add_match_subsystem(en, "block"); - udev_enumerate_add_match_property(en, "ID_CDROM", "1"); - break; - case EEZE_UDEV_TYPE_POWER_AC: - udev_enumerate_add_match_subsystem(en, "power_supply"); - udev_enumerate_add_match_property(en, "POWER_SUPPLY_TYPE", "Mains"); - break; - case EEZE_UDEV_TYPE_POWER_BAT: - udev_enumerate_add_match_subsystem(en, "power_supply"); - udev_enumerate_add_match_property(en, "POWER_SUPPLY_TYPE", "Battery"); - break; -/* - case EEZE_UDEV_TYPE_ANDROID: - udev_enumerate_add_match_subsystem(en, "block"); - udev_enumerate_add_match_property(en, "ID_MODEL", "Android_*"); - break; -*/ - default: - break; - } - udev_enumerate_scan_devices(en); - devs = udev_enumerate_get_list_entry(en); - - udev_list_entry_foreach(cur, devs) - { - devname = udev_list_entry_get_name(cur); - device = udev_device_new_from_syspath(udev, devname); - - if (name) - if (!strstr(devname,name)) - goto out; - - ret = eina_list_append(ret, eina_stringshare_add(udev_device_get_property_value(device, "DEVPATH"))); - -out: - udev_device_unref(device); - } - udev_enumerate_unref(en); - udev_unref(udev); - - return ret; + device = udev_device_new_from_syspath(udev, eina_strbuf_string_get(sbuf)); + if (!(parent = udev_device_get_parent(device))) + return NULL; + + for (; parent; child = parent, parent = udev_device_get_parent(child)) + { + path = udev_device_get_syspath(parent); + devlist = eina_list_append(devlist, eina_stringshare_add(path)); + } + udev_device_unref(device); + udev_unref(udev); + + return devlist; } -/** - * A more advanced find, allows finds using udev properties. - * - * @param subsystem The udev subsystem to filter by, or NULL - * @param type "ID_INPUT_KEY", "ID_INPUT_MOUSE", "ID_INPUT_TOUCHPAD", NULL, etc - * @param name A filter for the device name, or NULL - * @return A Eina_List* of matched devices or NULL on failure - * - * Return a list of syspaths (/sys/$syspath) for matching udev devices. - * Requires at least one filter. - * - * @ingroup udev - */ -EAPI Eina_List * -eeze_udev_find_by_filter(const char *subsystem, const char *type, const char *name) -{ - struct udev *udev; - struct udev_enumerate *en; - struct udev_list_entry *devs, *cur; - struct udev_device *device; - const char *devname; - Eina_List *ret = NULL; - - if ((!subsystem) && (!type) && (!name)) return NULL; - - udev = udev_new(); - if (!udev) return NULL; - en = udev_enumerate_new(udev); - if (!en) return NULL; - - if (subsystem) - udev_enumerate_add_match_subsystem(en, subsystem); - - udev_enumerate_add_match_property(en, type, "1"); - udev_enumerate_scan_devices(en); - devs = udev_enumerate_get_list_entry(en); - - udev_list_entry_foreach(cur, devs) - { - devname = udev_list_entry_get_name(cur); - device = udev_device_new_from_syspath(udev, devname); - - if (name) - if (!strstr(devname,name)) - goto out; - - ret = eina_list_append(ret, eina_stringshare_add(udev_device_get_property_value(device, "DEVPATH"))); - -out: - udev_device_unref(device); - } - udev_enumerate_unref(en); - udev_unref(udev); - - return ret; -} - - /** * Get the /dev/ path from the /sys/ path. * @@ -225,7 +105,7 @@ eeze_udev_syspath_get_devpath(const char *syspath) { struct udev *udev; struct udev_device *device; - const char *name; + const char *name = NULL; Eina_Strbuf *sbuf; if (!syspath) return NULL; @@ -238,7 +118,8 @@ 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)); - name = eina_stringshare_add(udev_device_get_property_value(device, "DEVNAME")); + if ((udev_device_get_property_value(device, "DEVNAME"))) + name = eina_stringshare_add(eina_strbuf_string_get(sbuf)); udev_device_unref(device); udev_unref(udev); @@ -302,7 +183,7 @@ eeze_udev_syspath_get_property(const char *syspath, const char *property) { struct udev *udev; struct udev_device *device; - const char *value; + const char *value = NULL, *test; Eina_Strbuf *sbuf; if (!syspath) return NULL; @@ -315,7 +196,8 @@ eeze_udev_syspath_get_property(const char *syspath, const char *property) eina_strbuf_append(sbuf, syspath); device = udev_device_new_from_syspath(udev, eina_strbuf_string_get(sbuf)); - value = eina_stringshare_add(udev_device_get_property_value(device, property)); + if ((test = udev_device_get_property_value(device, property))); + value = eina_stringshare_add(test); udev_device_unref(device); udev_unref(udev); @@ -415,7 +297,7 @@ eeze_udev_devpath_get_subsystem(const char *devpath) /** * Checks whether the device is a mouse. * - * @param syspath The /sys/ path of the device + * @param syspath The /sys/ path with or without the /sys/ * @return If true, the device is a mouse * * @ingroup udev @@ -462,7 +344,7 @@ eeze_udev_syspath_is_mouse(const char *syspath) /** * Checks whether the device is a keyboard. * - * @param syspath The /sys/ path of the device + * @param syspath The /sys/ path with or without the /sys/ * @return If true, the device is a keyboard * * @ingroup udev @@ -509,7 +391,7 @@ eeze_udev_syspath_is_kbd(const char *syspath) /** * Checks whether the device is a touchpad. * - * @param syspath The /sys/ path of the device + * @param syspath The /sys/ path with or without the /sys/ * @return If true, the device is a touchpad * * @ingroup udev @@ -546,3 +428,44 @@ 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 new file mode 100644 index 0000000000..c7a1514913 --- /dev/null +++ b/legacy/eeze/src/lib/udev/eeze_udev_find.c @@ -0,0 +1,357 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "eeze_udev_private.h" +#include + + +/** + * Returns a list of all syspaths that are (or should be) the same + * device as the device pointed at by @p syspath. + * + * @param syspath The syspath of the device to find matches for + * @return All devices which are the same as the one passed + * + * @ingroup udev + */ +EAPI Eina_List * +eeze_udev_find_similar_from_syspath(const char *syspath) +{ + struct udev *udev; + struct udev_device *device; + struct udev_list_entry *devs, *cur; + struct udev_enumerate *en; + Eina_List *l, *ret = NULL; + Eina_Strbuf *sbuf; + const char *vendor, *model, *revision, *devname, *dev; + + if (!syspath) return NULL; + udev = udev_new(); + if (!udev) return NULL; + en = udev_enumerate_new(udev); + if (!en) + { + udev_unref(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, syspath); + vendor = udev_device_get_property_value(device, "ID_VENDOR_ID"); + if (vendor) + udev_enumerate_add_match_property(en, "ID_VENDOR_ID", vendor); + model = udev_device_get_property_value(device, "ID_MODEL_ID"); + if (model) + udev_enumerate_add_match_property(en, "ID_MODEL_ID", model); + revision = udev_device_get_property_value(device, "ID_REVISION"); + if (revision) + udev_enumerate_add_match_property(en, "ID_REVISION", revision); + + udev_enumerate_scan_devices(en); + udev_device_unref(device); + + devs = udev_enumerate_get_list_entry(en); + udev_list_entry_foreach(cur, devs) + { + devname = udev_list_entry_get_name(cur); + /* verify unlisted device */ + EINA_LIST_FOREACH(ret, l, dev) + if (!strcmp(dev, devname)) + continue; + + ret = eina_list_prepend(ret, eina_stringshare_add(devname)); + device = udev_device_new_from_syspath(udev, devname); + + /* only device roots have this sysattr, + * and we only need to check parents of the roots + */ + if (udev_device_get_sysattr_value(device, "idVendor")) + _get_unlisted_parents(ret, device); + + udev_device_unref(device); + } + + udev_enumerate_unref(en); + udev_unref(udev); + eina_strbuf_free(sbuf); + + return ret; +} + +/** + * Updates a list of all syspaths that are (or should be) the same + * device. + * + * @param syspath The syspath of the device to find matches for. + * + * This function will update @p list to include all devices matching + * devices with syspaths currently stored in @p list. + * + * @ingroup udev + */ +EAPI void +eeze_udev_find_unlisted_similar(Eina_List *list) +{ + struct udev *udev; + struct udev_device *device; + struct udev_list_entry *devs, *cur; + struct udev_enumerate *en; + Eina_List *l; + const char *vendor, *model, *revision, *devname, *dev; + + if (!list) return; + udev = udev_new(); + if (!udev) return; + + EINA_LIST_FOREACH(list, l, dev) + { + en = udev_enumerate_new(udev); + if (!en) + { + udev_unref(udev); + return; + } + device = udev_device_new_from_syspath(udev, dev); + vendor = udev_device_get_property_value(device, "ID_VENDOR_ID"); + if (vendor) + udev_enumerate_add_match_property(en, "ID_VENDOR_ID", vendor); + model = udev_device_get_property_value(device, "ID_MODEL_ID"); + if (model) + udev_enumerate_add_match_property(en, "ID_MODEL_ID", model); + revision = udev_device_get_property_value(device, "ID_REVISION"); + if (revision) + udev_enumerate_add_match_property(en, "ID_REVISION", revision); + + udev_enumerate_scan_devices(en); + udev_device_unref(device); + + devs = udev_enumerate_get_list_entry(en); + udev_list_entry_foreach(cur, devs) + { + devname = udev_list_entry_get_name(cur); + device = udev_device_new_from_syspath(udev, devname); + + /* only device roots have this sysattr, + * and we only need to check parents of the roots + */ + if (udev_device_get_sysattr_value(device, "idVendor")) + _get_unlisted_parents(list, device); + + udev_device_unref(device); + } + + udev_enumerate_unref(en); + } + udev_unref(udev); + return; +} + +/** + * Find devices using a EEZE_UDEV_TYPE_* and/or a name. + * + * @param type A Eeze_Udev_Type or 0 + * @param name A filter for the device name or NULL + * @return A Eina_List* of matched devices or NULL on failure + * + * Return a list of syspaths (/sys/$syspath) for matching udev devices. + * + * @ingroup udev + */ +EAPI Eina_List * +eeze_udev_find_by_type(const Eeze_Udev_Type etype, const char *name) +{ + struct udev *udev; + struct udev_enumerate *en; + struct udev_list_entry *devs, *cur; + struct udev_device *device; + const char *devname; + Eina_List *ret = NULL; + + if ((!etype) && (!name)) return NULL; + + udev = udev_new(); + if (!udev) return NULL; + en = udev_enumerate_new(udev); + if (!en) return NULL; + + switch (etype) + { + case EEZE_UDEV_TYPE_NONE: + break; + case EEZE_UDEV_TYPE_KEYBOARD: + udev_enumerate_add_match_subsystem(en, "input"); + udev_enumerate_add_match_property(en, "ID_INPUT_KEYBOARD", "1"); + break; + case EEZE_UDEV_TYPE_MOUSE: + udev_enumerate_add_match_subsystem(en, "input"); + udev_enumerate_add_match_property(en, "ID_INPUT_MOUSE", "1"); + break; + case EEZE_UDEV_TYPE_TOUCHPAD: + udev_enumerate_add_match_subsystem(en, "input"); + udev_enumerate_add_match_property(en, "ID_INPUT_TOUCHPAD", "1"); + break; + case EEZE_UDEV_TYPE_DRIVE_MOUNTABLE: + udev_enumerate_add_match_subsystem(en, "block"); + udev_enumerate_add_match_property(en, "ID_FS_USAGE", "filesystem"); + udev_enumerate_add_nomatch_sysattr(en, "capability", "52"); + break; + case EEZE_UDEV_TYPE_DRIVE_INTERNAL: + udev_enumerate_add_match_subsystem(en, "block"); + udev_enumerate_add_match_property(en, "ID_TYPE", "disk"); + udev_enumerate_add_match_property(en, "ID_BUS", "ata"); + udev_enumerate_add_match_sysattr(en, "removable", "0"); + break; + case EEZE_UDEV_TYPE_DRIVE_REMOVABLE: + udev_enumerate_add_match_subsystem(en, "block"); + udev_enumerate_add_match_property(en, "ID_TYPE", "disk"); + udev_enumerate_add_match_sysattr(en, "removable", "1"); + break; + case EEZE_UDEV_TYPE_DRIVE_CDROM: + udev_enumerate_add_match_subsystem(en, "block"); + udev_enumerate_add_match_property(en, "ID_CDROM", "1"); + break; + case EEZE_UDEV_TYPE_POWER_AC: + udev_enumerate_add_match_subsystem(en, "power_supply"); + udev_enumerate_add_match_property(en, "POWER_SUPPLY_TYPE", "Mains"); + break; + case EEZE_UDEV_TYPE_POWER_BAT: + udev_enumerate_add_match_subsystem(en, "power_supply"); + udev_enumerate_add_match_property(en, "POWER_SUPPLY_TYPE", "Battery"); + break; +/* + case EEZE_UDEV_TYPE_ANDROID: + udev_enumerate_add_match_subsystem(en, "block"); + udev_enumerate_add_match_property(en, "ID_MODEL", "Android_*"); + break; +*/ + default: + break; + } + udev_enumerate_scan_devices(en); + devs = udev_enumerate_get_list_entry(en); + + udev_list_entry_foreach(cur, devs) + { + devname = udev_list_entry_get_name(cur); + device = udev_device_new_from_syspath(udev, devname); + + if (name) + if (!strstr(devname,name)) + goto out; + + ret = eina_list_append(ret, eina_stringshare_add(devname)); + +out: + udev_device_unref(device); + } + udev_enumerate_unref(en); + udev_unref(udev); + + return ret; +} + +/** + * A more advanced find, allows finds using udev properties. + * + * @param subsystem The udev subsystem to filter by, or NULL + * @param type "ID_INPUT_KEY", "ID_INPUT_MOUSE", "ID_INPUT_TOUCHPAD", NULL, etc + * @param name A filter for the device name, or NULL + * @return A Eina_List* of matched devices or NULL on failure + * + * Return a list of syspaths (/sys/$syspath) for matching udev devices. + * Requires at least one filter. + * + * @ingroup udev + */ +EAPI Eina_List * +eeze_udev_find_by_filter(const char *subsystem, const char *type, const char *name) +{ + struct udev *udev; + struct udev_enumerate *en; + struct udev_list_entry *devs, *cur; + struct udev_device *device; + const char *devname; + Eina_List *ret = NULL; + + if ((!subsystem) && (!type) && (!name)) return NULL; + + udev = udev_new(); + if (!udev) return NULL; + en = udev_enumerate_new(udev); + if (!en) return NULL; + + if (subsystem) + udev_enumerate_add_match_subsystem(en, subsystem); + + udev_enumerate_add_match_property(en, type, "1"); + udev_enumerate_scan_devices(en); + devs = udev_enumerate_get_list_entry(en); + + udev_list_entry_foreach(cur, devs) + { + devname = udev_list_entry_get_name(cur); + device = udev_device_new_from_syspath(udev, devname); + + if (name) + if (!strstr(devname,name)) + goto out; + + ret = eina_list_append(ret, eina_stringshare_add(devname)); + +out: + udev_device_unref(device); + } + udev_enumerate_unref(en); + udev_unref(udev); + + return ret; +} + +/** + * Find a list of devices by a sysattr (and, optionally, a value of that sysattr). + * + * @param sysattr The attribute to find + * @param value Optional: the value that the attribute should have + * + * @return A list of the devices found with the attribute + */ +EAPI Eina_List * +eeze_udev_find_by_sysattr(const char *sysattr, const char *value) +{ + struct udev *udev; + struct udev_enumerate *en; + struct udev_list_entry *devs, *cur; + struct udev_device *device; + const char *devname; + Eina_List *ret = NULL; + + if (!sysattr) return NULL; + + udev = udev_new(); + if (!udev) return NULL; + en = udev_enumerate_new(udev); + if (!en) return NULL; + + udev_enumerate_add_match_sysattr(en, sysattr, value); + udev_enumerate_scan_devices(en); + devs = udev_enumerate_get_list_entry(en); + + udev_list_entry_foreach(cur, devs) + { + devname = udev_list_entry_get_name(cur); + device = udev_device_new_from_syspath(udev, devname); + + ret = eina_list_append(ret, eina_stringshare_add(devname)); + + udev_device_unref(device); + } + udev_enumerate_unref(en); + udev_unref(udev); + + return ret; +} diff --git a/legacy/eeze/src/lib/udev/eeze_udev_private.c b/legacy/eeze/src/lib/udev/eeze_udev_private.c new file mode 100644 index 0000000000..24925d2b11 --- /dev/null +++ b/legacy/eeze/src/lib/udev/eeze_udev_private.c @@ -0,0 +1,73 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "eeze_udev_private.h" + +/** + * private function to simulate udevadm info -a + * walks up the device tree checking each node for sysattr + * with value $value + */ +Eina_Bool +_walk_parents_for_attr(struct udev_device *device, const char *sysattr, const char* value) +{ + struct udev_device *parent, *child = device; + const char *test; + + parent = udev_device_get_parent(child); + for (; parent; child = parent, parent = udev_device_get_parent(child)) + { + if (!(test = udev_device_get_sysattr_value(parent, sysattr))) + continue; + if (!value) + return 1; + else if (!strcmp(test, value)) + return 1; + } + + return 0; +} + +/** + * check a list for all parents of a device, + * stringshare adding all devices that are not in the list + */ +void +_get_unlisted_parents(Eina_List *list, struct udev_device *device) +{ + struct udev_device *parent, *child = device; + const char *test, *devname, *vendor, *vendor2, *model, *model2; + 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"); + 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)) + break; + else if ((!vendor2 && vendor) || (vendor2 && !vendor)) + break; + else if (strcmp(model, model2) || + strcmp(vendor, vendor2)) + break; + devname = udev_device_get_syspath(parent); + EINA_LIST_FOREACH(list, l, test) + { + if (!strcmp(test, devname)) + { + found = 1; + break; + } + } + if (!found) + list = eina_list_prepend(list, eina_stringshare_add(devname)); + } + return; +} diff --git a/legacy/eeze/src/lib/udev/eeze_udev_private.h b/legacy/eeze/src/lib/udev/eeze_udev_private.h index d169a52f97..cd37edfa50 100644 --- a/legacy/eeze/src/lib/udev/eeze_udev_private.h +++ b/legacy/eeze/src/lib/udev/eeze_udev_private.h @@ -1,6 +1,6 @@ #ifndef EEZE_UDEV_PRIVATE_H #define EEZE_UDEV_PRIVATE_H - +#include "Eeze_Udev.h" #ifndef E_EEZE_COLOR_DEFAULT #define E_EEZE_COLOR_DEFAULT EINA_COLOR_CYAN #endif @@ -23,4 +23,8 @@ extern int _e_eeze_udev_log_dom; #define WARN(...) EINA_LOG_DOM_WARN(_e_eeze_udev_log_dom, __VA_ARGS__) #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); +void _get_unlisted_parents(Eina_List *list, struct udev_device *device); + #endif diff --git a/legacy/eeze/src/lib/udev/eeze_udev_watch.c b/legacy/eeze/src/lib/udev/eeze_udev_watch.c index 9aafff8331..5ba4d911b7 100644 --- a/legacy/eeze/src/lib/udev/eeze_udev_watch.c +++ b/legacy/eeze/src/lib/udev/eeze_udev_watch.c @@ -1,5 +1,9 @@ -#include "eeze_udev_private.h" +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include +#include "eeze_udev_private.h" /* opaque */ struct Eeze_Udev_Watch @@ -20,31 +24,9 @@ struct _store_data }; -/* private function to simulate udevadm info -a - * walks up the device tree checking each node for sysattr - * with value value - */ -Eina_Bool -_walk_parents_for_attr(struct udev_device *device, const char *sysattr, const char* value) -{ - struct udev_device *parent, *child = device; - const char *test; - - for (parent = udev_device_get_parent(child); parent; child = parent, parent = udev_device_get_parent(child)) - { - if (!(test = udev_device_get_sysattr_value(parent, sysattr))) - continue; - if (!value) - return 1; - else if (!strcmp(test, value)) - return 1; - } - - return 0; -} - /* private function to further filter watch results based on Eeze_Udev_Type - * specified + * specified; helpful for new udev versions, but absolutely required for + * old udev, which does not implement filtering in device monitors. */ static int _get_syspath_from_watch(void *data, Ecore_Fd_Handler *fd_handler)