1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 
10 #include <Eeze.h>
11 #include "eeze_udev_private.h"
12 
13 EAPI Eina_List *
eeze_udev_find_similar_from_syspath(const char * syspath)14 eeze_udev_find_similar_from_syspath(const char *syspath)
15 {
16    _udev_device *device;
17    _udev_list_entry *devs, *cur;
18    _udev_enumerate *en;
19    Eina_List *l, *ret = NULL;
20    const char *vendor, *model, *revision, *devname, *dev;
21 
22    if (!syspath)
23      return NULL;
24 
25    en = udev_enumerate_new(udev);
26 
27    if (!en)
28      return NULL;
29 
30    if (!(device = _new_device(syspath)))
31      {
32         udev_enumerate_unref(en);
33         return NULL;
34      }
35 
36    vendor = udev_device_get_property_value(device, "ID_VENDOR_ID");
37 
38    if (vendor)
39      udev_enumerate_add_match_property(en, "ID_VENDOR_ID", vendor);
40 
41    model = udev_device_get_property_value(device, "ID_MODEL_ID");
42 
43    if (model)
44      udev_enumerate_add_match_property(en, "ID_MODEL_ID", model);
45 
46    revision = udev_device_get_property_value(device, "ID_REVISION");
47 
48    if (revision)
49      udev_enumerate_add_match_property(en, "ID_REVISION", revision);
50 
51    udev_enumerate_scan_devices(en);
52    udev_device_unref(device);
53    devs = udev_enumerate_get_list_entry(en);
54    udev_list_entry_foreach(cur, devs)
55      {
56         devname = udev_list_entry_get_name(cur);
57         /* verify unlisted device */
58 
59         EINA_LIST_FOREACH(ret, l, dev)
60           if (!strcmp(dev, devname))
61             continue;
62 
63         ret = eina_list_prepend(ret, eina_stringshare_add(devname));
64         device = udev_device_new_from_syspath(udev, devname);
65 
66         /* only device roots have this sysattr,
67          * and we only need to check parents of the roots
68          */
69         if (udev_device_get_sysattr_value(device, "idVendor"))
70           ret = _get_unlisted_parents(ret, device);
71 
72         udev_device_unref(device);
73      }
74    udev_enumerate_unref(en);
75    return ret;
76 }
77 
78 EAPI Eina_List *
eeze_udev_find_unlisted_similar(Eina_List * list)79 eeze_udev_find_unlisted_similar(Eina_List *list)
80 {
81    _udev_device *device;
82    _udev_list_entry *devs, *cur;
83    _udev_enumerate *en;
84    Eina_List *l;
85    const char *vendor, *model, *revision, *devname, *dev;
86 
87    if (!list)
88      return NULL;
89 
90    EINA_LIST_FOREACH(list, l, dev)
91      {
92         en = udev_enumerate_new(udev);
93 
94         if (!en)
95           return NULL;
96 
97         device = _new_device(dev);
98         if (!device) continue;
99 
100         if ((vendor = udev_device_get_property_value(device, "ID_VENDOR_ID")))
101           udev_enumerate_add_match_property(en, "ID_VENDOR_ID", vendor);
102         else if ((vendor = udev_device_get_property_value(device, "ID_VENDOR")))
103           udev_enumerate_add_match_property(en, "ID_VENDOR", vendor);
104         else if ((vendor = udev_device_get_sysattr_value(device, "vendor")))
105           udev_enumerate_add_match_sysattr(en, "vendor", vendor);
106         else if ((vendor = udev_device_get_sysattr_value(device, "manufacturer")))
107           udev_enumerate_add_match_sysattr(en, "manufacturer", vendor);
108 
109         if ((model = udev_device_get_property_value(device, "ID_MODEL_ID")))
110           udev_enumerate_add_match_property(en, "ID_MODEL_ID", model);
111         else if ((model = udev_device_get_property_value(device, "ID_MODEL")))
112           udev_enumerate_add_match_property(en, "ID_MODEL", model);
113         else if ((model = udev_device_get_sysattr_value(device, "model")))
114           udev_enumerate_add_match_sysattr(en, "model", model);
115         else if ((model = udev_device_get_sysattr_value(device, "product")))
116           udev_enumerate_add_match_sysattr(en, "product", model);
117 
118         if ((revision = udev_device_get_property_value(device, "ID_REVISION")))
119           udev_enumerate_add_match_property(en, "ID_REVISION", revision);
120         else if ((revision = udev_device_get_sysattr_value(device, "revision")))
121           udev_enumerate_add_match_sysattr(en, "revision", revision);
122 
123         udev_enumerate_add_match_subsystem(en, udev_device_get_subsystem(device));
124 
125         udev_enumerate_scan_devices(en);
126         udev_device_unref(device);
127         devs = udev_enumerate_get_list_entry(en);
128         udev_list_entry_foreach(cur, devs)
129           {
130              devname = udev_list_entry_get_name(cur);
131              device = udev_device_new_from_syspath(udev, devname);
132 
133              /* only device roots have this sysattr,
134               * and we only need to check parents of the roots
135               */
136              if (udev_device_get_sysattr_value(device, "idVendor"))
137                list = _get_unlisted_parents(list, device);
138 
139              udev_device_unref(device);
140           }
141         udev_enumerate_unref(en);
142      }
143    return list;
144 }
145 
146 EAPI Eina_List *
eeze_udev_find_by_type(Eeze_Udev_Type etype,const char * name)147 eeze_udev_find_by_type(Eeze_Udev_Type etype,
148                        const char    *name)
149 {
150    _udev_enumerate *en;
151    _udev_list_entry *devs, *cur;
152    _udev_device *device, *parent;
153    const char *devname;
154    Eina_List *ret = NULL;
155 
156    en = udev_enumerate_new(udev);
157 
158    if (!en)
159      return NULL;
160 
161    switch (etype)
162      {
163       case EEZE_UDEV_TYPE_NONE:
164         break;
165 
166       case EEZE_UDEV_TYPE_KEYBOARD:
167         udev_enumerate_add_match_subsystem(en, "input");
168         udev_enumerate_add_match_property(en, "ID_INPUT_KEYBOARD", "1");
169         break;
170 
171       case EEZE_UDEV_TYPE_MOUSE:
172         udev_enumerate_add_match_subsystem(en, "input");
173         udev_enumerate_add_match_property(en, "ID_INPUT_MOUSE", "1");
174         break;
175 
176       case EEZE_UDEV_TYPE_TOUCHPAD:
177         udev_enumerate_add_match_subsystem(en, "input");
178         udev_enumerate_add_match_property(en, "ID_INPUT_TOUCHPAD", "1");
179         break;
180 
181       case EEZE_UDEV_TYPE_JOYSTICK:
182         udev_enumerate_add_match_subsystem(en, "input");
183         udev_enumerate_add_match_property(en, "ID_INPUT_JOYSTICK", "1");
184         break;
185 
186       case EEZE_UDEV_TYPE_DRIVE_MOUNTABLE:
187         udev_enumerate_add_match_subsystem(en, "block");
188         udev_enumerate_add_match_property(en, "ID_FS_USAGE", "filesystem");
189         break;
190 
191       case EEZE_UDEV_TYPE_DRIVE_INTERNAL:
192         udev_enumerate_add_match_subsystem(en, "block");
193         udev_enumerate_add_match_property(en, "ID_TYPE", "disk");
194         udev_enumerate_add_match_property(en, "ID_BUS", "ata");
195         udev_enumerate_add_match_sysattr(en, "removable", "0");
196         break;
197 
198       case EEZE_UDEV_TYPE_DRIVE_REMOVABLE:
199         udev_enumerate_add_match_sysattr(en, "removable", "1");
200         udev_enumerate_add_match_property(en, "ID_TYPE", "disk");
201         break;
202 
203       case EEZE_UDEV_TYPE_DRIVE_CDROM:
204         udev_enumerate_add_match_property(en, "ID_CDROM", "1");
205         break;
206 
207       case EEZE_UDEV_TYPE_POWER_AC:
208         udev_enumerate_add_match_subsystem(en, "power_supply");
209         udev_enumerate_add_match_sysattr(en, "type", "Mains");
210         break;
211 
212       case EEZE_UDEV_TYPE_POWER_BAT:
213         udev_enumerate_add_match_subsystem(en, "power_supply");
214         udev_enumerate_add_match_sysattr(en, "type", "Battery");
215         udev_enumerate_add_match_sysattr(en, "present", "1");
216         break;
217 
218       case EEZE_UDEV_TYPE_NET:
219         udev_enumerate_add_match_subsystem(en, "net");
220         break;
221 
222       case EEZE_UDEV_TYPE_IS_IT_HOT_OR_IS_IT_COLD_SENSOR:
223         udev_enumerate_add_match_subsystem(en, "hwmon");
224         break;
225 
226       /*
227               case EEZE_UDEV_TYPE_ANDROID:
228                 udev_enumerate_add_match_subsystem(en, "block");
229                 udev_enumerate_add_match_property(en, "ID_MODEL", "Android_*");
230                 break;
231        */
232       case EEZE_UDEV_TYPE_V4L:
233         udev_enumerate_add_match_subsystem(en, "video4linux");
234         break;
235 
236       case EEZE_UDEV_TYPE_BLUETOOTH:
237         udev_enumerate_add_match_subsystem(en, "bluetooth");
238         break;
239 
240       case EEZE_UDEV_TYPE_DRM:
241         udev_enumerate_add_match_subsystem(en, "drm");
242         udev_enumerate_add_match_subsystem(en, "card[0-9]*");
243         break;
244 
245       case EEZE_UDEV_TYPE_BACKLIGHT:
246         udev_enumerate_add_match_subsystem(en, "backlight");
247         break;
248 
249       case EEZE_UDEV_TYPE_LEDS:
250         udev_enumerate_add_match_subsystem(en, "leds");
251         break;
252 
253       case EEZE_UDEV_TYPE_GRAPHICS:
254         udev_enumerate_add_match_subsystem(en, "graphics");
255         break;
256 
257       case EEZE_UDEV_TYPE_GPIO:
258         udev_enumerate_add_match_subsystem(en, "gpio");
259         break;
260 
261       default:
262         break;
263      }
264 
265    udev_enumerate_scan_devices(en);
266    devs = udev_enumerate_get_list_entry(en);
267    udev_list_entry_foreach(cur, devs)
268      {
269         devname = udev_list_entry_get_name(cur);
270         device = udev_device_new_from_syspath(udev, devname);
271 
272 
273         if (etype == EEZE_UDEV_TYPE_IS_IT_HOT_OR_IS_IT_COLD_SENSOR) /* ensure that temp input exists somewhere in this device chain */
274           {
275              Eina_Bool one, two;
276              const char *t;
277 
278              one = _walk_parents_test_attr(device, "temp1_input", NULL);
279              two = _walk_parents_test_attr(device, "temp2_input", NULL);
280              if ((!one) && (!two)) goto out;
281 
282              t = one ? "temp1_input" : "temp2_input";
283              /* if device is not the one which has the temp input, we must go up the chain */
284              if (!udev_device_get_sysattr_value(device, t))
285                {
286                   devname = NULL;
287 
288                   for (parent = udev_device_get_parent(device); parent; parent = udev_device_get_parent(parent)) /*check for parent */
289                     if ((udev_device_get_sysattr_value(parent, t)))
290                       {
291                          devname = udev_device_get_syspath(parent);
292                          break;
293                       }
294 
295                   if (!devname)
296                     goto out;
297                }
298           }
299         else if (etype == EEZE_UDEV_TYPE_DRIVE_REMOVABLE)
300           {
301              /* this yields the actual hw device, not to be confused with the filesystem */
302              devname = udev_device_get_syspath(udev_device_get_parent(device));
303           }
304         else if (etype == EEZE_UDEV_TYPE_DRIVE_MOUNTABLE)
305           {
306              int devcheck;
307 
308              devcheck = open(udev_device_get_devnode(device), O_RDONLY);
309              if (devcheck < 0) goto out;
310              close(devcheck);
311           }
312 
313         if (name && (!strstr(devname, name)))
314           goto out;
315 
316         ret = eina_list_append(ret, eina_stringshare_add(devname));
317 out:
318         udev_device_unref(device);
319      }
320    udev_enumerate_unref(en);
321    return ret;
322 }
323 
324 EAPI Eina_List *
eeze_udev_find_by_filter(const char * subsystem,const char * type,const char * name)325 eeze_udev_find_by_filter(const char *subsystem,
326                          const char *type,
327                          const char *name)
328 {
329    _udev_enumerate *en;
330    _udev_list_entry *devs, *cur;
331    const char *devname;
332    Eina_List *ret = NULL;
333 
334    if ((!subsystem) && (!type) && (!name))
335      return NULL;
336 
337    en = udev_enumerate_new(udev);
338 
339    if (!en)
340      return NULL;
341 
342    if (subsystem)
343      udev_enumerate_add_match_subsystem(en, subsystem);
344 
345    if (type)
346      udev_enumerate_add_match_property(en, type, "1");
347    udev_enumerate_scan_devices(en);
348    devs = udev_enumerate_get_list_entry(en);
349    udev_list_entry_foreach(cur, devs)
350      {
351         devname = udev_list_entry_get_name(cur);
352 
353         if (name && (!strstr(devname, name)))
354           continue;
355 
356         ret = eina_list_append(ret, eina_stringshare_add(devname));
357      }
358    udev_enumerate_unref(en);
359    return ret;
360 }
361 
362 EAPI Eina_List *
eeze_udev_find_by_sysattr(const char * sysattr,const char * value)363 eeze_udev_find_by_sysattr(const char *sysattr,
364                           const char *value)
365 {
366    _udev_enumerate *en;
367    _udev_list_entry *devs, *cur;
368    const char *devname;
369    Eina_List *ret = NULL;
370 
371    if (!sysattr)
372      return NULL;
373 
374    en = udev_enumerate_new(udev);
375 
376    if (!en)
377      return NULL;
378 
379    udev_enumerate_add_match_sysattr(en, sysattr, value);
380    udev_enumerate_scan_devices(en);
381    devs = udev_enumerate_get_list_entry(en);
382    udev_list_entry_foreach(cur, devs)
383      {
384         devname = udev_list_entry_get_name(cur);
385         ret = eina_list_append(ret, eina_stringshare_add(devname));
386      }
387    udev_enumerate_unref(en);
388    return ret;
389 }
390 
391 EAPI Eina_List *
eeze_udev_find_by_subsystem_sysname(const char * subsystem,const char * sysname)392 eeze_udev_find_by_subsystem_sysname(const char *subsystem, const char *sysname)
393 {
394    _udev_enumerate *en;
395    _udev_list_entry *devs, *cur;
396    const char *devname;
397    Eina_List *ret = NULL;
398 
399    en = udev_enumerate_new(udev);
400    if (!en) return NULL;
401 
402    if (subsystem) udev_enumerate_add_match_subsystem(en, subsystem);
403    if (sysname) udev_enumerate_add_match_sysname(en, sysname);
404 
405    udev_enumerate_scan_devices(en);
406    devs = udev_enumerate_get_list_entry(en);
407    udev_list_entry_foreach(cur, devs)
408      {
409         devname = udev_list_entry_get_name(cur);
410         ret = eina_list_append(ret, eina_stringshare_add(devname));
411      }
412    udev_enumerate_unref(en);
413    return ret;
414 }
415