1 /*
2  * Copyright (c) 2019 Daniel Widdis
3  *
4  * The contents of this file is dual-licensed under 2
5  * alternative Open Source/Free licenses: LGPL 2.1 or later and
6  * Apache License 2.0. (starting with JNA version 4.0.0).
7  *
8  * You can freely decide which license you want to apply to
9  * the project.
10  *
11  * You may obtain a copy of the LGPL License at:
12  *
13  * http://www.gnu.org/licenses/licenses.html
14  *
15  * A copy is also included in the downloadable source code package
16  * containing JNA, in file "LGPL2.1".
17  *
18  * You may obtain a copy of the Apache License at:
19  *
20  * http://www.apache.org/licenses/
21  *
22  * A copy is also included in the downloadable source code package
23  * containing JNA, in file "AL2.0".
24  */
25 package com.sun.jna.platform.mac;
26 
27 import com.sun.jna.Library;
28 import com.sun.jna.Memory;
29 import com.sun.jna.Native;
30 import com.sun.jna.Pointer;
31 import com.sun.jna.PointerType;
32 import com.sun.jna.platform.mac.CoreFoundation.CFAllocatorRef;
33 import com.sun.jna.platform.mac.CoreFoundation.CFArrayRef;
34 import com.sun.jna.platform.mac.CoreFoundation.CFBooleanRef;
35 import com.sun.jna.platform.mac.CoreFoundation.CFDataRef;
36 import com.sun.jna.platform.mac.CoreFoundation.CFDictionaryRef;
37 import com.sun.jna.platform.mac.CoreFoundation.CFMutableDictionaryRef;
38 import com.sun.jna.platform.mac.CoreFoundation.CFNumberRef;
39 import com.sun.jna.platform.mac.CoreFoundation.CFStringRef;
40 import com.sun.jna.platform.mac.CoreFoundation.CFTypeRef;
41 import com.sun.jna.ptr.IntByReference;
42 import com.sun.jna.ptr.LongByReference;
43 import com.sun.jna.ptr.PointerByReference;
44 
45 /**
46  * The I/O Kit framework implements non-kernel access to I/O Kit objects
47  * (drivers and nubs) through the device-interface mechanism.
48  */
49 public interface IOKit extends Library {
50 
51     IOKit INSTANCE = Native.load("IOKit", IOKit.class);
52 
53     int kIORegistryIterateRecursively = 0x00000001;
54     int kIORegistryIterateParents = 0x00000002;
55 
56     /**
57      * Return value when attempting parent or child in registry and they do not
58      * exist
59      */
60     int kIOReturnNoDevice = 0xe00002c0;
61 
62     double kIOPSTimeRemainingUnlimited = -2.0;
63     double kIOPSTimeRemainingUnknown = -1.0;
64 
65     /**
66      * IOKitLib implements non-kernel task access to common IOKit object types -
67      * IORegistryEntry, IOService, IOIterator etc. These functions are generic -
68      * families may provide API that is more specific.
69      * <p>
70      * IOKitLib represents IOKit objects outside the kernel with the types
71      * io_object_t, io_registry_entry_t, io_service_t, and io_connect_t. Function
72      * names usually begin with the type of object they are compatible with - e.g.,
73      * IOObjectRelease can be used with any io_object_t. Inside the kernel, the c++
74      * class hierarchy allows the subclasses of each object type to receive the same
75      * requests from user level clients, for example in the kernel, IOService is a
76      * subclass of IORegistryEntry, which means any of the IORegistryEntryXXX
77      * functions in IOKitLib may be used with io_service_t's as well as
78      * io_registry_t's. There are functions available to introspect the class of the
79      * kernel object which any io_object_t et al. represents. IOKit objects returned
80      * by all functions should be released with {@link IOKit#IOObjectRelease}.
81      */
82     class IOObject extends PointerType {
IOObject()83         public IOObject() {
84             super();
85         }
86 
IOObject(Pointer p)87         public IOObject(Pointer p) {
88             super(p);
89         }
90 
91         /**
92          * Convenience method for {@link IOKit#IOObjectConformsTo} on this object.
93          *
94          * @param className
95          *            The name of the class.
96          * @return If the object handle is valid, and represents an object in the kernel
97          *         that dynamic casts to the class true is returned, otherwise false.
98          */
conformsTo(String className)99         public boolean conformsTo(String className) {
100             return INSTANCE.IOObjectConformsTo(this, className);
101         }
102 
103         /**
104          * Convenience method for {@link IOKit#IOObjectRelease} on this object.
105          *
106          * @return 0 if successful, otherwise a {@code kern_return_t} error code.
107          */
release()108         public int release() {
109             return INSTANCE.IOObjectRelease(this);
110         }
111     }
112 
113     /**
114      * An IOKit iterator handle.
115      */
116     class IOIterator extends IOObject {
IOIterator()117         public IOIterator() {
118             super();
119         }
120 
IOIterator(Pointer p)121         public IOIterator(Pointer p) {
122             super(p);
123         }
124 
125         /**
126          * Convenience method for {@link IOKit#IOIteratorNext} on this object.
127          *
128          * @return If the iterator handle is valid, the next element in the iteration is
129          *         returned, otherwise {@code null} is returned. The element should be
130          *         released by the caller when it is finished.
131          */
next()132         public IORegistryEntry next() {
133             return INSTANCE.IOIteratorNext(this);
134         }
135     }
136 
137     /**
138      * The base class for all objects in the registry.
139      */
140     class IORegistryEntry extends IOObject {
IORegistryEntry()141         public IORegistryEntry() {
142             super();
143         }
144 
IORegistryEntry(Pointer p)145         public IORegistryEntry(Pointer p) {
146             super(p);
147         }
148 
149         /**
150          * Convenience method for {@link #IORegistryEntryGetRegistryEntryID} to
151          * return an ID for this registry entry that is global to all tasks.
152          *
153          * @return the ID.
154          * @throws IOReturnException
155          *             if the ID could not be retrieved.
156          */
getRegistryEntryID()157         public long getRegistryEntryID() {
158             LongByReference id = new LongByReference();
159             int kr = INSTANCE.IORegistryEntryGetRegistryEntryID(this, id);
160             if (kr != 0) {
161                 throw new IOReturnException(kr);
162             }
163             return id.getValue();
164         }
165 
166         /**
167          * Convenience method for {@link #IORegistryEntryGetName} to return a
168          * name assigned to this registry entry.
169          *
170          * @return The name
171          * @throws IOReturnException
172          *             if the name could not be retrieved.
173          */
getName()174         public String getName() {
175             Memory name = new Memory(128);
176             int kr = INSTANCE.IORegistryEntryGetName(this, name);
177             if (kr != 0) {
178                 throw new IOReturnException(kr);
179             }
180             return name.getString(0);
181         }
182 
183         /**
184          * Convenience method for {@link #IORegistryEntryGetChildIterator} to
185          * return an iterator over this registry entry’s child entries in a
186          * plane.
187          *
188          * @param plane
189          *            The name of an existing registry plane. Plane names are
190          *            defined in {@code IOKitKeys.h}, for example,
191          *            {@code kIOServicePlane}.
192          * @return The iterator
193          * @throws IOReturnException
194          *             if the iterator could not be retrieved.
195          */
getChildIterator(String plane)196         public IOIterator getChildIterator(String plane) {
197             PointerByReference iter = new PointerByReference();
198             int kr = INSTANCE.IORegistryEntryGetChildIterator(this, plane, iter);
199             if (kr != 0) {
200                 throw new IOReturnException(kr);
201             }
202             return new IOIterator(iter.getValue());
203         }
204 
205         /**
206          * Convenience method for {@link #IORegistryEntryGetChildEntry} to
207          * return the first child of this registry entry in a plane.
208          *
209          * @param plane
210          *            The name of an existing registry plane.
211          * @return The child registry entry, if a child exists, null otherwise
212          * @throws IOReturnException
213          *             if the entry exists but could not be retrieved.
214          */
getChildEntry(String plane)215         public IORegistryEntry getChildEntry(String plane) {
216             PointerByReference child = new PointerByReference();
217             int kr = INSTANCE.IORegistryEntryGetChildEntry(this, plane, child);
218             if (kr == kIOReturnNoDevice) {
219                 return null;
220             } else if (kr != 0) {
221                 throw new IOReturnException(kr);
222             }
223             return new IORegistryEntry(child.getValue());
224         }
225 
226         /**
227          * Convenience method for {@link #IORegistryEntryGetParentEntry} to
228          * return the first parent of this registry entry in a plane.
229          *
230          * @param plane
231          *            The name of an existing registry plane.
232          * @return The parent registry entry, if a parent exists, null otherwise
233          * @throws IOReturnException
234          *             if the entry exists but could not be retrieved.
235          */
getParentEntry(String plane)236         public IORegistryEntry getParentEntry(String plane) {
237             PointerByReference parent = new PointerByReference();
238             int kr = INSTANCE.IORegistryEntryGetParentEntry(this, plane, parent);
239             if (kr == kIOReturnNoDevice) {
240                 return null;
241             } else if (kr != 0) {
242                 throw new IOReturnException(kr);
243             }
244             return new IORegistryEntry(parent.getValue());
245         }
246 
247         /**
248          * Convenience method for {@link #IORegistryEntryCreateCFProperty} to create a
249          * CF representation of this registry entry's property.
250          *
251          * @param key
252          *            A {@code CFString} specifying the property name.
253          * @return A CF container is created and returned the caller on success.
254          *         <p>
255          *         The caller should release with {@link CoreFoundation#CFRelease}.
256          */
createCFProperty(CFStringRef key)257         public CFTypeRef createCFProperty(CFStringRef key) {
258             return INSTANCE.IORegistryEntryCreateCFProperty(this, key, CoreFoundation.INSTANCE.CFAllocatorGetDefault(),
259                     0);
260         }
261 
262         /**
263          * Convenience method for {@link #IORegistryEntryCreateCFProperties} to
264          * create a CF dictionary representation of this registry entry's
265          * property table.
266          *
267          * @return The property table.
268          *         <p>
269          *         The caller should release with
270          *         {@link CoreFoundation#CFRelease}.
271          * @throws IOReturnException
272          *             if the entry could not be retrieved.
273          */
createCFProperties()274         public CFMutableDictionaryRef createCFProperties() {
275             PointerByReference properties = new PointerByReference();
276             int kr = INSTANCE.IORegistryEntryCreateCFProperties(this, properties,
277                     CoreFoundation.INSTANCE.CFAllocatorGetDefault(), 0);
278             if (kr != 0) {
279                 throw new IOReturnException(kr);
280             }
281             return new CFMutableDictionaryRef(properties.getValue());
282         }
283 
284         /**
285          * Convenience method for {@link #IORegistryEntrySearchCFProperty} to create a
286          * CF representation of a registry entry's property searched from this object.
287          *
288          * @param plane
289          *            The name of an existing registry plane. Plane names are defined in
290          *            {@code IOKitKeys.h}, for example, {@code kIOServicePlane}.
291          * @param key
292          *            A {@code CFString} specifying the property name.
293          * @param options
294          *            {@link #kIORegistryIterateRecursively} may be set to recurse
295          *            automatically into the registry hierarchy. Without this option,
296          *            this method degenerates into the standard
297          *            {@link #IORegistryEntryCreateCFProperty} call.
298          *            {@link #kIORegistryIterateParents} may be set to iterate the
299          *            parents of the entry, in place of the children.
300          * @return A CF container is created and returned the caller on success. The
301          *         caller should release with CFRelease.
302          */
searchCFProperty(String plane, CFStringRef key, int options)303         CFTypeRef searchCFProperty(String plane, CFStringRef key, int options) {
304             return INSTANCE.IORegistryEntrySearchCFProperty(this, plane, key,
305                     CoreFoundation.INSTANCE.CFAllocatorGetDefault(), options);
306         }
307 
308         /**
309          * Convenience method to get a {@link java.lang.String} value from this IO
310          * Registry Entry.
311          *
312          * @param key
313          *            The string name of the key to retrieve
314          * @return The value of the registry entry if it exists; {@code null} otherwise
315          */
getStringProperty(String key)316         public String getStringProperty(String key) {
317             String value = null;
318             CFStringRef keyAsCFString = CFStringRef.createCFString(key);
319             CFTypeRef valueAsCFType = this.createCFProperty(keyAsCFString);
320             keyAsCFString.release();
321             if (valueAsCFType != null) {
322                 CFStringRef valueAsCFString = new CFStringRef(valueAsCFType.getPointer());
323                 value = valueAsCFString.stringValue();
324                 valueAsCFType.release();
325             }
326             return value;
327         }
328 
329         /**
330          * Convenience method to get a {@link java.lang.Long} value from this IO
331          * Registry Entry.
332          *
333          * @param key
334          *            The string name of the key to retrieve
335          * @return The value of the registry entry if it exists; {@code null} otherwise
336          *         <p>
337          *         This method assumes a 64-bit integer is stored and does not do type
338          *         checking. If this object's type differs from the return type, and the
339          *         conversion is lossy or the return value is out of range, then this
340          *         method returns an approximate value.
341          */
getLongProperty(String key)342         public Long getLongProperty(String key) {
343             Long value = null;
344             CFStringRef keyAsCFString = CFStringRef.createCFString(key);
345             CFTypeRef valueAsCFType = this.createCFProperty(keyAsCFString);
346             keyAsCFString.release();
347             if (valueAsCFType != null) {
348                 CFNumberRef valueAsCFNumber = new CFNumberRef(valueAsCFType.getPointer());
349                 value = valueAsCFNumber.longValue();
350                 valueAsCFType.release();
351             }
352             return value;
353         }
354 
355         /**
356          * Convenience method to get an {@link java.lang.Integer} value from this IO
357          * Registry Entry.
358          *
359          * @param key
360          *            The string name of the key to retrieve
361          * @return The value of the registry entry if it exists; {@code null} otherwise
362          *         <p>
363          *         This method assumes a 32-bit integer is stored and does not do type
364          *         checking. If this object's type differs from the return type, and the
365          *         conversion is lossy or the return value is out of range, then this
366          *         method returns an approximate value.
367          */
getIntegerProperty(String key)368         public Integer getIntegerProperty(String key) {
369             Integer value = null;
370             CFStringRef keyAsCFString = CFStringRef.createCFString(key);
371             CFTypeRef valueAsCFType = this.createCFProperty(keyAsCFString);
372             keyAsCFString.release();
373             if (valueAsCFType != null) {
374                 CFNumberRef valueAsCFNumber = new CFNumberRef(valueAsCFType.getPointer());
375                 value = valueAsCFNumber.intValue();
376                 valueAsCFType.release();
377             }
378             return value;
379         }
380 
381         /**
382          * Convenience method to get a {@link java.lang.Double} value from this IO
383          * Registry Entry.
384          *
385          * @param key
386          *            The string name of the key to retrieve
387          * @return The value of the registry entry if it exists; {@code null} otherwise
388          *         <p>
389          *         This method assumes a floating point value is stored and does not do
390          *         type checking. If this object's type differs from the return type,
391          *         and the conversion is lossy or the return value is out of range, then
392          *         this method returns an approximate value.
393          */
getDoubleProperty(String key)394         public Double getDoubleProperty(String key) {
395             Double value = null;
396             CFStringRef keyAsCFString = CFStringRef.createCFString(key);
397             CFTypeRef valueAsCFType = this.createCFProperty(keyAsCFString);
398             keyAsCFString.release();
399             if (valueAsCFType != null) {
400                 CFNumberRef valueAsCFNumber = new CFNumberRef(valueAsCFType.getPointer());
401                 value = valueAsCFNumber.doubleValue();
402                 valueAsCFType.release();
403             }
404             return value;
405         }
406 
407         /**
408          * Convenience method to get a {@link java.lang.Boolean} value from this IO
409          * Registry Entry.
410          *
411          * @param key
412          *            The string name of the key to retrieve
413          * @return The value of the registry entry if it exists; {@code null} otherwise
414          */
getBooleanProperty(String key)415         public Boolean getBooleanProperty(String key) {
416             Boolean value = null;
417             CFStringRef keyAsCFString = CFStringRef.createCFString(key);
418             CFTypeRef valueAsCFType = this.createCFProperty(keyAsCFString);
419             keyAsCFString.release();
420             if (valueAsCFType != null) {
421                 CFBooleanRef valueAsCFBoolean = new CFBooleanRef(valueAsCFType.getPointer());
422                 value = valueAsCFBoolean.booleanValue();
423                 valueAsCFType.release();
424             }
425             return value;
426         }
427 
428         /**
429          * Convenience method to get a {@code byte} array value from this IO Registry
430          * Entry.
431          *
432          * @param key
433          *            The string name of the key to retrieve
434          * @return The value of the registry entry if it exists; {@code null} otherwise
435          */
getByteArrayProperty(String key)436         public byte[] getByteArrayProperty(String key) {
437             byte[] value = null;
438             CFStringRef keyAsCFString = CFStringRef.createCFString(key);
439             CFTypeRef valueAsCFType = this.createCFProperty(keyAsCFString);
440             keyAsCFString.release();
441             if (valueAsCFType != null) {
442                 CFDataRef valueAsCFData = new CFDataRef(valueAsCFType.getPointer());
443                 int length = valueAsCFData.getLength();
444                 Pointer p = valueAsCFData.getBytePtr();
445                 value = p.getByteArray(0, length);
446                 valueAsCFType.release();
447             }
448             return value;
449         }
450     }
451 
452     /**
453      * The base class for most I/O Kit families, devices, and drivers.
454      */
455     class IOService extends IORegistryEntry {
IOService()456         public IOService() {
457             super();
458         }
459 
IOService(Pointer p)460         public IOService(Pointer p) {
461             super(p);
462         }
463     }
464 
465     /**
466      * For an application to communicate with a device, the first thing it must do
467      * is create a connection between itself and the in-kernel object representing
468      * the device. To do this, it creates a user client object.
469      */
470     class IOConnect extends IOService {
IOConnect()471         public IOConnect() {
472             super();
473         }
474 
IOConnect(Pointer p)475         public IOConnect(Pointer p) {
476             super(p);
477         }
478     }
479 
480     /**
481      * Returns the mach port used to initiate communication with IOKit.
482      *
483      * @param bootstrapPort
484      *            Pass 0 for the default.
485      * @param port
486      *            A pointer to the master port is returned. Multiple calls to
487      *            IOMasterPort will not result in leaking ports (each call to
488      *            IOMasterPort adds another send right to the port) but it is
489      *            considered good programming practice to deallocate the port when
490      *            you are finished with it using
491      *            {@link SystemB#mach_port_deallocate}.
492      * @return 0 if successful, otherwise a {@code kern_return_t} error code.
493      */
IOMasterPort(int bootstrapPort, IntByReference port)494     int IOMasterPort(int bootstrapPort, IntByReference port);
495 
496     /**
497      * Create a matching dictionary that specifies an {@code IOService} class match.
498      *
499      * @param name
500      *            The class name. Class matching is successful on {@code IOService}s
501      *            of this class or any subclass.
502      * @return The matching dictionary created, is returned on success, or
503      *         {@code null} on failure.
504      *         <p>
505      *         The dictionary is commonly passed to
506      *         {@link #IOServiceGetMatchingServices} which will consume a reference,
507      *         otherwise it should be released with {@link CoreFoundation#CFRelease}
508      *         by the caller.
509      */
IOServiceMatching(String name)510     CFMutableDictionaryRef IOServiceMatching(String name);
511 
512     /**
513      * Create a matching dictionary that specifies an {@code IOService} name match.
514      *
515      * @param name
516      *            The {@code IOService} name.
517      * @return The matching dictionary created, is returned on success, or
518      *         {@code null} on failure.
519      *         <p>
520      *         The dictionary is commonly passed to
521      *         {@link #IOServiceGetMatchingServices} which will consume a reference,
522      *         otherwise it should be released with {@link CoreFoundation#CFRelease}
523      *         by the caller.
524      */
IOServiceNameMatching(String name)525     CFMutableDictionaryRef IOServiceNameMatching(String name);
526 
527     /**
528      * Create a matching dictionary that specifies an {@code IOService} match based
529      * on BSD device name.
530      *
531      * @param masterPort
532      *            The master port obtained from {@link #IOMasterPort}.
533      * @param options
534      *            No options are currently defined.
535      * @param bsdName
536      *            The BSD name.
537      * @return The matching dictionary created, is returned on success, or
538      *         {@code null} on failure.
539      *         <p>
540      *         The dictionary is commonly passed to
541      *         {@link #IOServiceGetMatchingServices} which will consume a reference,
542      *         otherwise it should be released with {@link CoreFoundation#CFRelease}
543      *         by the caller.
544      */
IOBSDNameMatching(int masterPort, int options, String bsdName)545     CFMutableDictionaryRef IOBSDNameMatching(int masterPort, int options, String bsdName);
546 
547     /**
548      * Look up a registered IOService object that matches a matching dictionary.
549      *
550      * @param masterPort
551      *            The master port obtained from {@link #IOMasterPort}.
552      * @param matchingDictionary
553      *            A CF dictionary containing matching information, of which one
554      *            reference is always consumed by this function. IOKitLib can
555      *            construct matching dictionaries for common criteria with helper
556      *            functions such as {@link #IOServiceMatching},
557      *            {@link #IOServiceNameMatching}, and {@link #IOBSDNameMatching}.
558      * @return The first service matched is returned on success.
559      *         <p>
560      *         The service must be released by the caller.
561      */
IOServiceGetMatchingService(int masterPort, CFDictionaryRef matchingDictionary)562     IOService IOServiceGetMatchingService(int masterPort, CFDictionaryRef matchingDictionary);
563 
564     /**
565      * Look up registered IOService objects that match a matching dictionary.
566      *
567      * @param masterPort
568      *            The master port obtained from {@link #IOMasterPort}.
569      * @param matchingDictionary
570      *            A CF dictionary containing matching information, of which one
571      *            reference is always consumed by this function. IOKitLib can
572      *            construct matching dictionaries for common criteria with helper
573      *            functions such as {@link #IOServiceMatching},
574      *            {@link #IOServiceNameMatching}, and {@link #IOBSDNameMatching}.
575      * @param iterator
576      *            An iterator handle is returned on success, and should be released
577      *            by the caller when the iteration is finished.
578      * @return 0 if successful, otherwise a {@code kern_return_t} error code.
579      */
IOServiceGetMatchingServices(int masterPort, CFDictionaryRef matchingDictionary, PointerByReference iterator)580     int IOServiceGetMatchingServices(int masterPort, CFDictionaryRef matchingDictionary, PointerByReference iterator);
581 
582     /**
583      * Returns the next object in an iteration.
584      *
585      * @param iterator
586      *            An IOKit iterator handle.
587      * @return If the iterator handle is valid, the next element in the iteration is
588      *         returned, otherwise zero is returned. The element should be released
589      *         by the caller when it is finished.
590      */
IOIteratorNext(IOIterator iterator)591     IORegistryEntry IOIteratorNext(IOIterator iterator);
592 
593     /**
594      * Create a CF representation of a registry entry's property.
595      *
596      * @param entry
597      *            The registry entry handle whose property to copy.
598      * @param key
599      *            A {@code CFString} specifying the property name.
600      * @param allocator
601      *            The CF allocator to use when creating the CF container.
602      * @param options
603      *            No options are currently defined.
604      * @return A CF container is created and returned the caller on success.
605      *         <p>
606      *         The caller should release with {@link CoreFoundation#CFRelease}.
607      */
IORegistryEntryCreateCFProperty(IORegistryEntry entry, CFStringRef key, CFAllocatorRef allocator, int options)608     CFTypeRef IORegistryEntryCreateCFProperty(IORegistryEntry entry, CFStringRef key, CFAllocatorRef allocator,
609             int options);
610 
611     /**
612      * Create a CF dictionary representation of a registry entry's property table.
613      *
614      * @param entry
615      *            The registry entry handle whose property table to copy.
616      * @param properties
617      *            A CFDictionary is created and returned the caller on success. The
618      *            caller should release with CFRelease.
619      * @param allocator
620      *            The CF allocator to use when creating the CF containers.
621      * @param options
622      *            No options are currently defined.
623      * @return 0 if successful, otherwise a {@code kern_return_t} error code.
624      */
IORegistryEntryCreateCFProperties(IORegistryEntry entry, PointerByReference properties, CFAllocatorRef allocator, int options)625     int IORegistryEntryCreateCFProperties(IORegistryEntry entry, PointerByReference properties,
626             CFAllocatorRef allocator, int options);
627 
628     /**
629      * Create a CF representation of a registry entry's property.
630      *
631      * @param entry
632      *            The registry entry at which to start the search.
633      * @param plane
634      *            The name of an existing registry plane. Plane names are defined in
635      *            {@code IOKitKeys.h}, for example, {@code kIOServicePlane}.
636      * @param key
637      *            A {@code CFString} specifying the property name.
638      * @param allocator
639      *            The CF allocator to use when creating the CF container.
640      * @param options
641      *            {@link #kIORegistryIterateRecursively} may be set to recurse
642      *            automatically into the registry hierarchy. Without this option,
643      *            this method degenerates into the standard
644      *            {@link #IORegistryEntryCreateCFProperty} call.
645      *            {@link #kIORegistryIterateParents} may be set to iterate the
646      *            parents of the entry, in place of the children.
647      * @return A CF container is created and returned the caller on success. The
648      *         caller should release with CFRelease.
649      */
IORegistryEntrySearchCFProperty(IORegistryEntry entry, String plane, CFStringRef key, CFAllocatorRef allocator, int options)650     CFTypeRef IORegistryEntrySearchCFProperty(IORegistryEntry entry, String plane, CFStringRef key,
651             CFAllocatorRef allocator, int options);
652 
653     /**
654      * Returns an ID for the registry entry that is global to all tasks.
655      *
656      * @param entry
657      *            The registry entry handle whose ID to look up.
658      * @param id
659      *            The resulting ID.
660      * @return 0 if successful, otherwise a {@code kern_return_t} error code.
661      */
IORegistryEntryGetRegistryEntryID(IORegistryEntry entry, LongByReference id)662     int IORegistryEntryGetRegistryEntryID(IORegistryEntry entry, LongByReference id);
663 
664     /**
665      * Returns a name assigned to a registry entry.
666      *
667      * @param entry
668      *            The registry entry handle whose name to look up.
669      * @param name
670      *            The caller's buffer to receive the name. This must be a 128-byte
671      *            buffer.
672      * @return 0 if successful, otherwise a {@code kern_return_t} error code.
673      */
IORegistryEntryGetName(IORegistryEntry entry, Pointer name)674     int IORegistryEntryGetName(IORegistryEntry entry, Pointer name);
675 
676     /**
677      * Returns an iterator over a registry entry’s child entries in a plane.
678      *
679      * @param entry
680      *            The registry entry whose children to iterate over.
681      * @param plane
682      *            The name of an existing registry plane. Plane names are defined in
683      *            {@code IOKitKeys.h}, for example, {@code kIOServicePlane}.
684      * @param iter
685      *            The created iterator over the children of the entry, on success.
686      *            The iterator must be released when the iteration is finished.
687      * @return 0 if successful, otherwise a {@code kern_return_t} error code.
688      */
IORegistryEntryGetChildIterator(IORegistryEntry entry, String plane, PointerByReference iter)689     int IORegistryEntryGetChildIterator(IORegistryEntry entry, String plane, PointerByReference iter);
690 
691     /**
692      * Returns the first child of a registry entry in a plane.
693      *
694      * @param entry
695      *            The registry entry whose child to look up.
696      * @param plane
697      *            The name of an existing registry plane. Plane names are defined in
698      *            {@code IOKitKeys.h}, for example, {@code kIOServicePlane}.
699      * @param child
700      *            The first child of the registry entry, on success. The child must
701      *            be released by the caller.
702      * @return 0 if successful, otherwise a {@code kern_return_t} error code.
703      */
IORegistryEntryGetChildEntry(IORegistryEntry entry, String plane, PointerByReference child)704     int IORegistryEntryGetChildEntry(IORegistryEntry entry, String plane, PointerByReference child);
705 
706     /**
707      * Returns the first parent of a registry entry in a plane.
708      *
709      * @param entry
710      *            The registry entry whose parent to look up.
711      * @param plane
712      *            The name of an existing registry plane. Plane names are defined in
713      *            {@code IOKitKeys.h}, for example, {@code kIOServicePlane}.
714      * @param parent
715      *            The first parent of the registry entry, on success. The parent
716      *            must be released by the caller.
717      * @return 0 if successful, otherwise a {@code kern_return_t} error code.
718      */
IORegistryEntryGetParentEntry(IORegistryEntry entry, String plane, PointerByReference parent)719     int IORegistryEntryGetParentEntry(IORegistryEntry entry, String plane, PointerByReference parent);
720 
721     /**
722      * Return a handle to the registry root.
723      *
724      * @param masterPort
725      *            The master port obtained from {@link #IOMasterPort}.
726      * @return A handle to the IORegistryEntry root instance, to be released with
727      *         {@link #IOObjectRelease} by the caller, or 0 on failure.
728      */
IORegistryGetRootEntry(int masterPort)729     IORegistryEntry IORegistryGetRootEntry(int masterPort);
730 
731     /**
732      * Performs an OSDynamicCast operation on an IOKit object.
733      *
734      * @param object
735      *            An IOKit object.
736      * @param className
737      *            The name of the class.
738      * @return If the object handle is valid, and represents an object in the kernel
739      *         that dynamic casts to the class true is returned, otherwise false.
740      */
IOObjectConformsTo(IOObject object, String className)741     boolean IOObjectConformsTo(IOObject object, String className);
742 
743     /**
744      * Releases an object handle previously returned by {@code IOKitLib}.
745      *
746      * @param object
747      *            The IOKit object to release.
748      * @return 0 if successful, otherwise a {@code kern_return_t} error code.
749      */
IOObjectRelease(IOObject object)750     int IOObjectRelease(IOObject object);
751 
752     /**
753      * A request to create a connection to an IOService.
754      *
755      * @param service
756      *            The IOService object to open a connection to, usually obtained via
757      *            the {@link #IOServiceGetMatchingServices} API.
758      * @param owningTask
759      *            The mach task requesting the connection.
760      * @param type
761      *            A constant specifying the type of connection to be created,
762      *            interpreted only by the IOService's family.
763      * @param connect
764      *            An {@code io_connect_t} handle is returned on success, to be used
765      *            with the IOConnectXXX APIs. It should be destroyed with
766      *            {@link IOServiceClose}.
767      * @return A return code generated by {@code IOService::newUserClient}.
768      */
IOServiceOpen(IOService service, int owningTask, int type, PointerByReference connect)769     int IOServiceOpen(IOService service, int owningTask, int type, PointerByReference connect);
770 
771     /**
772      * Returns the busyState of an IOService.
773      *
774      * @param service
775      *            The IOService whose busyState to return.
776      * @param busyState
777      *            The busyState count is returned.
778      * @return 0 if successful, otherwise a {@code kern_return_t} error code.
779      */
IOServiceGetBusyState(IOService service, IntByReference busyState)780     int IOServiceGetBusyState(IOService service, IntByReference busyState);
781 
782     /**
783      * Close a connection to an IOService and destroy the connect handle.
784      *
785      * @param connect
786      *            The connect handle created by IOServiceOpen. It will be destroyed
787      *            by this function, and should not be released with IOObjectRelease.
788      * @return 0 if successful, otherwise a {@code kern_return_t} error code.
789      */
IOServiceClose(IOConnect connect)790     int IOServiceClose(IOConnect connect);
791 
792     /**
793      * Returns a blob of Power Source information in an opaque CFTypeRef.
794      *
795      * @return {@code null} if errors were encountered, a {@link CFTypeRef}
796      *         otherwise.
797      *         <p>
798      *         Caller must {@link CoreFoundation#CFRelease} the return value when
799      *         done accessing it.
800      */
IOPSCopyPowerSourcesInfo()801     CFTypeRef IOPSCopyPowerSourcesInfo();
802 
803     /**
804      * Returns a CFArray of Power Source handles, each of type CFTypeRef.
805      *
806      * @param blob
807      *            Takes the {@link CFTypeRef} returned by
808      *            {@link #IOPSCopyPowerSourcesInfo}
809      * @return {@code null} if errors were encountered, otherwise a CFArray of
810      *         {@link CFTypeRef}s.
811      *         <p>
812      *         Caller must {@link CoreFoundation#CFRelease} the returned
813      *         {@link CFArrayRef}.
814      */
IOPSCopyPowerSourcesList(CFTypeRef blob)815     CFArrayRef IOPSCopyPowerSourcesList(CFTypeRef blob);
816 
817     /**
818      * Returns a CFDictionary with readable information about the specific power
819      * source.
820      *
821      * @param blob
822      *            the {@link CFTypeRef} returned by
823      *            {@link #IOPSCopyPowerSourcesInfo}
824      * @param ps
825      *            One of the {@link CFTypeRef}s in the CFArray returned by
826      *            {@link #IOPSCopyPowerSourcesList}.
827      * @return {@code null} if an error was encountered, otherwise a CFDictionary.
828      *         <p>
829      *         Caller should NOT release the returned CFDictionary - it will be
830      *         released as part of the {@link CFTypeRef} returned by
831      *         {@link IOPSCopyPowerSourcesInfo}.
832      */
IOPSGetPowerSourceDescription(CFTypeRef blob, CFTypeRef ps)833     CFDictionaryRef IOPSGetPowerSourceDescription(CFTypeRef blob, CFTypeRef ps);
834 
835     /**
836      * Returns the estimated seconds remaining until all power sources (battery
837      * and/or UPS's) are empty.
838      *
839      * @return Returns {@link #kIOPSTimeRemainingUnknown} if the OS cannot determine
840      *         the time remaining.
841      *         <p>
842      *         Returns {@link #kIOPSTimeRemainingUnlimited} if the system has an
843      *         unlimited power source.
844      *         <p>
845      *         Otherwise returns a positive number indicating the time remaining in
846      *         seconds until all power sources are depleted.
847      */
IOPSGetTimeRemainingEstimate()848     double IOPSGetTimeRemainingEstimate();
849 }
850