1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <Eeze.h>
6 #include "eeze_udev_private.h"
7
8 /*
9 * helper function to set up a new device from a syspath
10 * which may or may not include /sys at the beginning
11 */
12 _udev_device *
_new_device(const char * syspath)13 _new_device(const char *syspath)
14 {
15 _udev_device *device;
16
17 device = udev_device_new_from_syspath(udev, syspath);
18 if (!device)
19 ERR("device %s does not exist!", syspath);
20 return device;
21 }
22
23 /*
24 * copies a device
25 */
26 _udev_device *
_copy_device(_udev_device * device)27 _copy_device(_udev_device *device)
28 {
29 return udev_device_ref(device);
30 }
31
32 /*
33 * private function to simulate udevadm info -a
34 * walks up the device tree checking each node for sysattr
35 * with value $value
36 */
37 Eina_Bool
_walk_parents_test_attr(_udev_device * device,const char * sysattr,const char * value)38 _walk_parents_test_attr(_udev_device *device,
39 const char *sysattr,
40 const char *value)
41 {
42 _udev_device *parent, *child = device;
43 const char *test;
44
45 if (udev_device_get_sysattr_value(device, sysattr))
46 return EINA_TRUE;
47
48 parent = udev_device_get_parent(child);
49
50 for (; parent; child = parent, parent = udev_device_get_parent(child))
51 {
52 if (!(test = udev_device_get_sysattr_value(parent, sysattr)))
53 continue;
54
55 if (!value)
56 return EINA_TRUE;
57 else
58 if (!strcmp(test, value))
59 return EINA_TRUE;
60 }
61
62 return EINA_FALSE;
63 }
64
65 const char *
_walk_parents_get_attr(_udev_device * device,const char * sysattr,Eina_Bool property)66 _walk_parents_get_attr(_udev_device *device,
67 const char *sysattr,
68 Eina_Bool property)
69 {
70 _udev_device *parent, *child = device;
71 const char *test;
72
73 if (property)
74 test = udev_device_get_property_value(device, sysattr);
75 else
76 test = udev_device_get_sysattr_value(device, sysattr);
77 if (test) return eina_stringshare_add(test);
78
79 parent = udev_device_get_parent(child);
80
81 for (; parent; child = parent, parent = udev_device_get_parent(child))
82 {
83 if (property)
84 test = udev_device_get_property_value(parent, sysattr);
85 else
86 test = udev_device_get_sysattr_value(parent, sysattr);
87 if (test) return eina_stringshare_add(test);
88 }
89
90 return NULL;
91 }
92
93 const char *
_walk_children_get_attr(const char * syspath,const char * sysattr,const char * subsystem,Eina_Bool property)94 _walk_children_get_attr(const char *syspath,
95 const char *sysattr,
96 const char *subsystem,
97 Eina_Bool property)
98 {
99 char buf[PATH_MAX];
100 const char *path, *ret = NULL;
101 _udev_enumerate *en;
102 _udev_list_entry *devs, *cur;
103
104 en = udev_enumerate_new(udev);
105 EINA_SAFETY_ON_NULL_RETURN_VAL(en, NULL);
106 path = strrchr(syspath, '/');
107 if (path) path++;
108 else path = syspath;
109 snprintf(buf, sizeof(buf), "%s*", path);
110 udev_enumerate_add_match_sysname(en, buf);
111 if (subsystem) udev_enumerate_add_match_subsystem(en, subsystem);
112 udev_enumerate_scan_devices(en);
113 devs = udev_enumerate_get_list_entry(en);
114 udev_list_entry_foreach(cur, devs)
115 {
116 const char *devname, *test;
117 _udev_device *device;
118
119 devname = udev_list_entry_get_name(cur);
120 device = _new_device(devname);
121 if (property)
122 test = udev_device_get_property_value(device, sysattr);
123 else
124 test = udev_device_get_sysattr_value(device, sysattr);
125 if (test)
126 {
127 ret = eina_stringshare_add(test);
128 udev_device_unref(device);
129 break;
130 }
131 udev_device_unref(device);
132 }
133 udev_enumerate_unref(en);
134 return ret;
135 }
136
137 /*
138 * check a list for all parents of a device,
139 * stringshare adding all devices that are not in the list
140 */
141 Eina_List *
_get_unlisted_parents(Eina_List * list,_udev_device * device)142 _get_unlisted_parents(Eina_List *list,
143 _udev_device *device)
144 {
145 _udev_device *parent, *child = device;
146 const char *test, *devname, *vendor, *vendor2, *model, *model2;
147 Eina_List *l;
148 Eina_Bool found;
149
150 if (!(vendor = udev_device_get_property_value(child, "ID_VENDOR_ID")))
151 vendor = udev_device_get_property_value(child, "ID_VENDOR");
152 if (!vendor) vendor = udev_device_get_sysattr_value(child, "vendor");
153 if (!vendor) vendor = udev_device_get_sysattr_value(child, "manufacturer");
154
155 if (!(model = udev_device_get_property_value(child, "ID_MODEL_ID")))
156 model = udev_device_get_property_value(child, "ID_MODEL");
157 if (!model) model = udev_device_get_sysattr_value(child, "model");
158 if (!model) model = udev_device_get_sysattr_value(child, "product");
159
160 parent = udev_device_get_parent(child);
161
162 for (; parent; child = parent, parent = udev_device_get_parent(child))
163 {
164 found = EINA_FALSE;
165
166 if (!(vendor2 = udev_device_get_property_value(child, "ID_VENDOR_ID")))
167 vendor2 = udev_device_get_property_value(child, "ID_VENDOR");
168 if (!vendor2) vendor2 = udev_device_get_sysattr_value(child, "vendor");
169 if (!vendor2) vendor2 = udev_device_get_sysattr_value(child, "manufacturer");
170
171 if (!(model2 = udev_device_get_property_value(child, "ID_MODEL_ID")))
172 model2 = udev_device_get_property_value(child, "ID_MODEL");
173 if (!model2) model2 = udev_device_get_sysattr_value(child, "model");
174 if (!model2) model2 = udev_device_get_sysattr_value(child, "product");
175
176 if ((!model2 && model) || (model2 && !model) || (!vendor2 && vendor)
177 || (vendor2 && !vendor))
178 break;
179 else
180 if (((model && model2) && (strcmp(model, model2))) ||
181 ((vendor && vendor2) && (strcmp(vendor, vendor2))))
182 break;
183
184 devname = udev_device_get_syspath(parent);
185 EINA_LIST_FOREACH(list, l, test)
186 {
187 if (!strcmp(test, devname))
188 {
189 found = EINA_TRUE;
190 break;
191 }
192 }
193
194 if (!found)
195 list = eina_list_prepend(list, eina_stringshare_add(devname));
196 }
197
198 return list;
199 }
200
201