1 /* Copyright (c) 2020 Daniel Widdis, All Rights Reserved
2  *
3  * The contents of this file is dual-licensed under 2
4  * alternative Open Source/Free licenses: LGPL 2.1 or later and
5  * Apache License 2.0. (starting with JNA version 4.0.0).
6  *
7  * You can freely decide which license you want to apply to
8  * the project.
9  *
10  * You may obtain a copy of the LGPL License at:
11  *
12  * http://www.gnu.org/licenses/licenses.html
13  *
14  * A copy is also included in the downloadable source code package
15  * containing JNA, in file "LGPL2.1".
16  *
17  * You may obtain a copy of the Apache License at:
18  *
19  * http://www.apache.org/licenses/
20  *
21  * A copy is also included in the downloadable source code package
22  * containing JNA, in file "AL2.0".
23  */
24 package com.sun.jna.platform.linux;
25 
26 import com.sun.jna.Library;
27 import com.sun.jna.Native;
28 import com.sun.jna.PointerType;
29 
30 /**
31  * libudev.h provides APIs to introspect and enumerate devices on the local
32  * system. Udev objects are opaque and must not be accessed by the caller via
33  * different means than functions provided by libudev.
34  */
35 public interface Udev extends Library {
36 
37     Udev INSTANCE = Native.load("udev", Udev.class);
38 
39     /**
40      * All functions require a libudev context to operate. This context can be
41      * created via {@link #udev_new}. It is used to track library state and link
42      * objects together. No global state is used by libudev, everything is always
43      * linked to a udev context. Furthermore, multiple different udev contexts can
44      * be used in parallel by multiple threads. However, a single context must not
45      * be accessed by multiple threads in parallel. The caller is responsible for
46      * providing suitable locking if they intend to use it from multiple threads.
47      */
48     class UdevContext extends PointerType {
49         /**
50          * Acquire a further reference to this object.
51          *
52          * @return this object, unmodified.
53          */
ref()54         UdevContext ref() {
55             return INSTANCE.udev_ref(this);
56         }
57 
58         /**
59          * Drop a reference to this object. Once the reference count hits 0, the context
60          * object is destroyed and freed.
61          */
unref()62         public void unref() {
63             INSTANCE.udev_unref(this);
64         }
65 
66         /**
67          * Create a udev enumerate object. Initially, the reference count of the
68          * enumerate object is 1.
69          *
70          * @return On success, returns the allocated enumerator. On failure, NULL is
71          *         returned.
72          */
enumerateNew()73         public UdevEnumerate enumerateNew() {
74             return INSTANCE.udev_enumerate_new(this);
75         }
76 
77         /**
78          * Creates a udev device object based on information found in {@code /sys},
79          * annotated with properties from the udev-internal device database. Initially,
80          * the reference count of the device is 1.
81          *
82          * @param syspath
83          *            The path of the device in {@code /sys}.
84          * @return the allocated udev device. On failure, NULL is returned, and
85          *         {@code errno} is set appropriately.
86          */
deviceNewFromSyspath(String syspath)87         public UdevDevice deviceNewFromSyspath(String syspath) {
88             return INSTANCE.udev_device_new_from_syspath(this, syspath);
89         }
90     }
91 
92     /**
93      * To enumerate local devices on the system, an enumeration object can be
94      * created via {@link UdevContext#enumerateNew()}.
95      */
96     class UdevEnumerate extends PointerType {
97         /**
98          * Acquire a further reference to this object.
99          *
100          * @return this object, unmodified.
101          */
ref()102         public UdevEnumerate ref() {
103             return INSTANCE.udev_enumerate_ref(this);
104         }
105 
106         /**
107          * Drop a reference to this object. Once the reference count hits 0, the context
108          * object is destroyed and freed.
109          */
unref()110         public void unref() {
111             INSTANCE.udev_enumerate_unref(this);
112         }
113 
114         /**
115          * Modify filters of this object to match a subsystem.
116          *
117          * @param subsystem
118          *            The subsystem to match
119          * @return an integer greater than, or equal to, 0 on success.
120          */
addMatchSubsystem(String subsystem)121         public int addMatchSubsystem(String subsystem) {
122             return INSTANCE.udev_enumerate_add_match_subsystem(this, subsystem);
123         }
124 
125         /**
126          * Query this object. Scans {@code /sys} for all devices which match the given
127          * filters. No filters will return all currently available devices.
128          *
129          * @return an integer greater than, or equal to, 0 on success.
130          */
scanDevices()131         public int scanDevices() {
132             return INSTANCE.udev_enumerate_scan_devices(this);
133         }
134 
135         /**
136          * Get the first list entry from this object.
137          *
138          * @return On success, returns the first entry in the list of found devices. If
139          *         the list is empty, or on failure, NULL is returned.
140          */
getListEntry()141         public UdevListEntry getListEntry() {
142             return INSTANCE.udev_enumerate_get_list_entry(this);
143         }
144     }
145 
146     /**
147      * Whenever libudev returns a list of objects, the {@code udev_list_entry} API
148      * should be used to iterate, access and modify those lists.
149      */
150     class UdevListEntry extends PointerType {
151         /**
152          * Gets the next entry in the enumeration.
153          *
154          * @return On success, returns the next list entry. If no such entry can be
155          *         found, or on failure, NULL is returned.
156          */
getNext()157         public UdevListEntry getNext() {
158             return INSTANCE.udev_list_entry_get_next(this);
159         }
160 
161         /**
162          * Get the name of this entry, which is the path of the device in {@code /sys}.
163          *
164          * @return A string representing the syspath. On failure, NULL is returned.
165          */
getName()166         public String getName() {
167             return INSTANCE.udev_list_entry_get_name(this);
168         }
169     }
170 
171     /**
172      * To introspect a local device on a system, a udev device object can be created
173      * via {@link UdevContext#deviceNewFromSyspath(String)} and friends. The device
174      * object allows one to query current state, read and write attributes and
175      * lookup properties of the device in question.
176      */
177     class UdevDevice extends PointerType {
178         /**
179          * Acquire a further reference to this object.
180          *
181          * @return this object, unmodified.
182          */
ref()183         public UdevDevice ref() {
184             return INSTANCE.udev_device_ref(this);
185         }
186 
187         /**
188          * Drop a reference to this object. Once the reference count hits 0, the context
189          * object is destroyed and freed.
190          */
unref()191         public void unref() {
192             INSTANCE.udev_device_unref(this);
193         }
194 
195         /**
196          * Gets the parent of this device
197          *
198          * @return the parent device. No additional reference to this device is
199          *         acquired, but the child device owns a reference to the parent device.
200          *         On failure, NULL is returned.
201          */
getParent()202         public UdevDevice getParent() {
203             return INSTANCE.udev_device_get_parent(this);
204         }
205 
206         /**
207          * Gets the parent of this device matching a subsystem and devtype
208          *
209          * @param subsystem
210          *            The subsystem to match
211          * @param devtype
212          *            The device type to match
213          * @return the parent device. No additional reference to this device is
214          *         acquired, but the child device owns a reference to the parent device.
215          *         On failure, NULL is returned.
216          */
getParentWithSubsystemDevtype(String subsystem, String devtype)217         public UdevDevice getParentWithSubsystemDevtype(String subsystem, String devtype) {
218             return INSTANCE.udev_device_get_parent_with_subsystem_devtype(this, subsystem, devtype);
219         }
220 
221         /**
222          * Gets the syspath of this device
223          *
224          * @return a string that describes the syspath. On failure, may return NULL.
225          */
getSyspath()226         public String getSyspath() {
227             return INSTANCE.udev_device_get_syspath(this);
228         }
229 
230         /**
231          * Gets the sysname of this device
232          *
233          * @return a string that describes the sysname. On failure, may return NULL.
234          */
getSysname()235         public String getSysname() {
236             return INSTANCE.udev_device_get_syspath(this);
237         }
238 
239         /**
240          * Gets the devnode of this device
241          *
242          * @return a string that describes the devnode. On failure, may return NULL.
243          */
getDevnode()244         public String getDevnode() {
245             return INSTANCE.udev_device_get_devnode(this);
246         }
247 
248         /**
249          * Gets the devtype of this device
250          *
251          * @return a string that describes the devtype. On failure, may return NULL.
252          */
getDevtype()253         public String getDevtype() {
254             return INSTANCE.udev_device_get_devtype(this);
255         }
256 
257         /**
258          * Gets the subsystem of this device
259          *
260          * @return a string that describes the subsystem. On failure, may return NULL.
261          */
getSubsystem()262         public String getSubsystem() {
263             return INSTANCE.udev_device_get_subsystem(this);
264         }
265 
266         /**
267          * Retrieves a device attribute from this device
268          *
269          * @param sysattr
270          *            The attribute to retrieve.
271          * @return a string of the requested value. On error, NULL is returned.
272          *         Attributes that may contain NUL bytes should not be retrieved with
273          *         udev_device_get_sysattr_value(); instead, read them directly from the
274          *         files within the device's syspath.
275          */
getSysattrValue(String sysattr)276         public String getSysattrValue(String sysattr) {
277             return INSTANCE.udev_device_get_sysattr_value(this, sysattr);
278         }
279 
280         /**
281          * Retrieves a device property from this device
282          *
283          * @param key
284          *            The property to retrieve.
285          * @return a string of the requested value. On error, NULL is returned.
286          */
getPropertyValue(String key)287         public String getPropertyValue(String key) {
288             return INSTANCE.udev_device_get_property_value(this, key);
289         }
290     }
291 
292     /**
293      * Allocates a new udev context object and returns a pointer to it. This object
294      * is opaque and must not be accessed by the caller via different means than
295      * functions provided by libudev. Initially, the reference count of the context
296      * is 1.
297      *
298      * @return On success, returns a pointer to the allocated udev context. On
299      *         failure, NULL is returned.
300      */
udev_new()301     UdevContext udev_new();
302 
303     /**
304      * Acquire further references to a udev context object.
305      *
306      * @param udev
307      *            A udev context object.
308      * @return the argument that was passed, unmodified.
309      */
udev_ref(UdevContext udev)310     UdevContext udev_ref(UdevContext udev);
311 
312     /**
313      * Drop a reference to a udev context object. Once the reference count hits 0,
314      * the context object is destroyed and freed.
315      *
316      * @param udev
317      *            A udev context object.
318      * @return always returns NULL.
319      */
udev_unref(UdevContext udev)320     UdevContext udev_unref(UdevContext udev);
321 
322     /**
323      * Allocates a new udev device object and returns a pointer to it. This object
324      * is opaque and must not be accessed by the caller via different means than
325      * functions provided by libudev. Initially, the reference count of the device
326      * is 1.
327      * <p>
328      * Creates the device object based on information found in {@code /sys},
329      * annotated with properties from the udev-internal device database. A syspath
330      * is any subdirectory of {@code /sys}, with the restriction that a subdirectory
331      * of {@code /sys/devices} (or a symlink to one) represents a real device and as
332      * such must contain a uevent file.
333      *
334      * @param udev
335      *            A udev context object.
336      * @param syspath
337      *            The path of the device in {@code /sys}.
338      * @return a pointer to the allocated udev device. On failure, NULL is returned,
339      *         and {@code errno} is set appropriately.
340      */
udev_device_new_from_syspath(UdevContext udev, String syspath)341     UdevDevice udev_device_new_from_syspath(UdevContext udev, String syspath);
342 
343     /**
344      * Create a udev enumerate object. Initially, the reference count of the
345      * enumerate object is 1.
346      *
347      * @param udev
348      *            A udev context object.
349      * @return On success, returns a pointer to the allocated udev monitor. On
350      *         failure, NULL is returned.
351      */
udev_enumerate_new(UdevContext udev)352     UdevEnumerate udev_enumerate_new(UdevContext udev);
353 
354     /**
355      * Acquire further references to a udev enumerate object.
356      *
357      * @param udev_enumerate
358      *            A udev enumerate object.
359      * @return the argument that was passed, unmodified.
360      */
udev_enumerate_ref(UdevEnumerate udev_enumerate)361     UdevEnumerate udev_enumerate_ref(UdevEnumerate udev_enumerate);
362 
363     /**
364      * Drop a reference to a udev enumerate object. Once the reference count hits 0,
365      * the enumerate object is destroyed and freed.
366      *
367      * @param udev_enumerate
368      *            A udev enumerate object.
369      * @return always returns NULL.
370      */
udev_enumerate_unref(UdevEnumerate udev_enumerate)371     UdevEnumerate udev_enumerate_unref(UdevEnumerate udev_enumerate);
372 
373     /**
374      * Modify filters of a udev enumerate object to match a subsystem.
375      *
376      * @param udev_enumerate
377      *            The udev enumerate object to modify.
378      * @param subsystem
379      *            The subsystem to match
380      * @return an integer greater than, or equal to, 0 on success.
381      */
udev_enumerate_add_match_subsystem(UdevEnumerate udev_enumerate, String subsystem)382     int udev_enumerate_add_match_subsystem(UdevEnumerate udev_enumerate, String subsystem);
383 
384     /**
385      * Query a udev enumerate object. Scans {@code /sys} for all devices which match
386      * the given filters. No matches will return all currently available devices.
387      *
388      * @param udev_enumerate
389      *            The udev enumerate object, with optional filters.
390      * @return an integer greater than, or equal to, 0 on success.
391      */
udev_enumerate_scan_devices(UdevEnumerate udev_enumerate)392     int udev_enumerate_scan_devices(UdevEnumerate udev_enumerate);
393 
394     /**
395      * Get the first list entry from a udev enumerate object.
396      *
397      * @param udev_enumerate
398      *            The udev enumerate object.
399      * @return On success, returns a pointer to the first entry in the list of found
400      *         devices. If the list is empty, or on failure, NULL is returned.
401      */
udev_enumerate_get_list_entry(UdevEnumerate udev_enumerate)402     UdevListEntry udev_enumerate_get_list_entry(UdevEnumerate udev_enumerate);
403 
404     /**
405      * Gets the next entry in the enumeration.
406      *
407      * @param list_entry
408      *            the current list entry
409      * @return On success, returns a pointer to the next list entry. If no such
410      *         entry can be found, or on failure, NULL is returned.
411      */
udev_list_entry_get_next(UdevListEntry list_entry)412     UdevListEntry udev_list_entry_get_next(UdevListEntry list_entry);
413 
414     /**
415      * Get the name of the udev list entry
416      *
417      * @param list_entry
418      *            A udev list entry
419      * @return a pointer to a constant string representing the requested value. The
420      *         string is bound to the lifetime of the list entry itself. On failure,
421      *         NULL is returned.
422      */
udev_list_entry_get_name(UdevListEntry list_entry)423     String udev_list_entry_get_name(UdevListEntry list_entry);
424 
425     /**
426      * Acquire further references to a udev device object.
427      *
428      * @param udev_device
429      *            A udev device object.
430      * @return the argument that was passed, unmodified.
431      */
udev_device_ref(UdevDevice udev_device)432     UdevDevice udev_device_ref(UdevDevice udev_device);
433 
434     /**
435      * Drop a reference to a udev device object. Once the reference count hits 0,
436      * the device object is destroyed and freed.
437      *
438      * @param udev_device
439      *            A udev device object.
440      * @return always returns NULL.
441      */
udev_device_unref(UdevDevice udev_device)442     UdevDevice udev_device_unref(UdevDevice udev_device);
443 
444     /**
445      * Gets the parent of a udev device
446      *
447      * @param udev_device
448      *            A udev device object.
449      * @return a pointer to the parent device. No additional reference to this
450      *         device is acquired, but the child device owns a reference to such a
451      *         parent device. On failure, NULL is returned.
452      */
udev_device_get_parent(UdevDevice udev_device)453     UdevDevice udev_device_get_parent(UdevDevice udev_device);
454 
455     /**
456      * Gets the parent of a udev device matching a subsystem and devtype
457      *
458      * @param udev_device
459      *            A udev device object.
460      * @param subsystem
461      *            The subsystem to match
462      * @param devtype
463      *            The device type to match
464      * @return a pointer to the parent device. No additional reference to this
465      *         device is acquired, but the child device owns a reference to such a
466      *         parent device. On failure, NULL is returned.
467      */
udev_device_get_parent_with_subsystem_devtype(UdevDevice udev_device, String subsystem, String devtype)468     UdevDevice udev_device_get_parent_with_subsystem_devtype(UdevDevice udev_device, String subsystem, String devtype);
469 
470     /**
471      * Gets the syspath of a udev device
472      *
473      * @param udev_device
474      *            A udev device object.
475      * @return a pointer to a constant string that describes the syspath. The
476      *         lifetime of this string is bound to the device it was requested on.
477      *         On failure, may return NULL.
478      */
udev_device_get_syspath(UdevDevice udev_device)479     String udev_device_get_syspath(UdevDevice udev_device);
480 
481     /**
482      * Gets the sysname of a udev device
483      *
484      * @param udev_device
485      *            A udev device object.
486      * @return a pointer to a constant string that describes the sysname. The
487      *         lifetime of this string is bound to the device it was requested on.
488      *         On failure, may return NULL.
489      */
udev_device_get_sysname(UdevDevice udev_device)490     String udev_device_get_sysname(UdevDevice udev_device);
491 
492     /**
493      * Gets the devnode of a udev device
494      *
495      * @param udev_device
496      *            A udev device object.
497      * @return a pointer to a constant string that describes the devnode. The
498      *         lifetime of this string is bound to the device it was requested on.
499      *         On failure, may return NULL.
500      */
udev_device_get_devnode(UdevDevice udev_device)501     String udev_device_get_devnode(UdevDevice udev_device);
502 
503     /**
504      * Gets the devtype of a udev device
505      *
506      * @param udev_device
507      *            A udev device object.
508      * @return a pointer to a constant string that describes the devtype. The
509      *         lifetime of this string is bound to the device it was requested on.
510      *         On failure, may return NULL.
511      */
udev_device_get_devtype(UdevDevice udev_device)512     String udev_device_get_devtype(UdevDevice udev_device);
513 
514     /**
515      * Gets the subsystem of a udev device
516      *
517      * @param udev_device
518      *            A udev device object.
519      * @return a pointer to a constant string that describes the subsystem. The
520      *         lifetime of this string is bound to the device it was requested on.
521      *         On failure, may return NULL.
522      */
udev_device_get_subsystem(UdevDevice udev_device)523     String udev_device_get_subsystem(UdevDevice udev_device);
524 
525     /**
526      * Retrieves a device attributesfrom a udev device.
527      *
528      * @param udev_device
529      *            A udev device object.
530      * @param sysattr
531      *            The attribute to retrieve.
532      * @return a pointer to a constant string of the requested value. On error, NULL
533      *         is returned. Attributes that may contain NUL bytes should not be
534      *         retrieved with udev_device_get_sysattr_value(); instead, read them
535      *         directly from the files within the device's syspath.
536      */
udev_device_get_sysattr_value(UdevDevice udev_device, String sysattr)537     String udev_device_get_sysattr_value(UdevDevice udev_device, String sysattr);
538 
539     /**
540      * Retrieves a device property from a udev device.
541      *
542      * @param udev_device
543      *            A udev device object.
544      * @param key
545      *            The property to retrieve.
546      * @return a pointer to a constant string of the requested value. On error, NULL
547      *         is returned.
548      */
udev_device_get_property_value(UdevDevice udev_device, String key)549     String udev_device_get_property_value(UdevDevice udev_device, String key);
550 }