use std::mem;
use std::ops::{Deref, DerefMut};
use core_foundation::base::{kCFAllocatorDefault, kCFNull, mach_port_t, CFType, TCFType};
use core_foundation::dictionary::{CFDictionary, CFMutableDictionary, CFMutableDictionaryRef};
use core_foundation::string::CFString;
use mach::{kern_return, mach_port, port, traps};
use super::sys;
use crate::Result;
#[derive(Debug)]
pub struct IoMasterPort(mach_port_t);
impl IoMasterPort {
pub fn new() -> Result<IoMasterPort> {
let mut master_port: port::mach_port_t = port::MACH_PORT_NULL;
unsafe {
kern_try!(sys::IOMasterPort(sys::kIOMasterPortDefault, &mut master_port));
}
Ok(IoMasterPort(master_port))
}
pub fn get_services(&self) -> Result<IoIterator> {
let service = unsafe {
let ret = sys::IOServiceMatching(sys::IOPM_SERVICE_NAME);
assert_ne!(ret as *const _, kCFNull);
ret
};
let mut iterator = IoIterator::default();
unsafe {
kern_try!(sys::IOServiceGetMatchingServices(self.0, service, &mut *iterator));
}
Ok(iterator)
}
}
impl Drop for IoMasterPort {
fn drop(&mut self) {
let result = unsafe { mach_port::mach_port_deallocate(traps::mach_task_self(), self.0) };
assert_eq!(result, kern_return::KERN_SUCCESS);
}
}
#[derive(Debug)]
pub struct IoObject(sys::io_object_t);
impl IoObject {
pub fn properties(&self) -> Result<CFDictionary<CFString, CFType>> {
unsafe {
#[allow(deprecated)]
let mut props: CFMutableDictionaryRef = mem::uninitialized();
kern_try!(sys::IORegistryEntryCreateCFProperties(
self.0,
&mut props,
kCFAllocatorDefault,
0
));
Ok(CFMutableDictionary::wrap_under_create_rule(props).to_immutable())
}
}
}
impl Drop for IoObject {
fn drop(&mut self) {
let result = unsafe { sys::IOObjectRelease(self.0) };
assert_eq!(result, kern_return::KERN_SUCCESS);
}
}
#[derive(Debug)]
pub struct IoIterator(sys::io_iterator_t);
impl Deref for IoIterator {
type Target = sys::io_iterator_t;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for IoIterator {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Iterator for IoIterator {
type Item = IoObject;
fn next(&mut self) -> Option<Self::Item> {
match unsafe { sys::IOIteratorNext(self.0) } {
0 => None, io_object => Some(IoObject(io_object)),
}
}
}
impl Drop for IoIterator {
fn drop(&mut self) {
let result = unsafe { sys::IOObjectRelease(self.0) };
assert_eq!(result, kern_return::KERN_SUCCESS);
}
}
impl Default for IoIterator {
fn default() -> IoIterator {
let inner = unsafe { mem::zeroed() };
IoIterator(inner)
}
}