Source code for rpcclient.darwin.ioregistry

from typing import Mapping

from rpcclient.allocated import Allocated
from rpcclient.darwin.consts import MACH_PORT_NULL, kCFAllocatorDefault, kIOServicePlane
from rpcclient.darwin.structs import io_name_t, io_object_t, mach_port_t
from rpcclient.exceptions import BadReturnValueError, RpcClientException


[docs] class IOService(Allocated): """ representation of a remote IOService """ def __init__(self, client, service): super().__init__() self._client = client self._service = service @property def name(self) -> str: with self._client.safe_malloc(io_name_t.sizeof()) as name: if self._client.symbols.IORegistryEntryGetName(self._service, name): raise BadReturnValueError('IORegistryEntryGetName failed') return name.peek_str() @property def properties(self) -> Mapping: with self._client.safe_malloc(8) as p_properties: if self._client.symbols.IORegistryEntryCreateCFProperties(self._service, p_properties, kCFAllocatorDefault, 0): raise BadReturnValueError('IORegistryEntryCreateCFProperties failed') return p_properties[0].py() def __iter__(self): with self._client.safe_malloc(io_object_t.sizeof()) as p_child_iter: if self._client.symbols.IORegistryEntryGetChildIterator(self._service, kIOServicePlane, p_child_iter): raise BadReturnValueError('IORegistryEntryGetChildIterator failed') child_iter = p_child_iter[0] while True: child = self._client.symbols.IOIteratorNext(child_iter) if not child: break s = IOService(self._client, child) yield s
[docs] def set(self, properties: Mapping): self._client.symbols.IORegistryEntrySetCFProperties(self._service, self._client.cf(properties))
[docs] def get(self, key: str): return self._client.symbols.IORegistryEntryCreateCFProperty(self._service, self._client.cf(key), kCFAllocatorDefault, 0).py()
def _deallocate(self): self._client.symbols.IOObjectRelease(self._service) def __repr__(self): return f'<{self.__class__.__name__} NAME:{self.name}>'
[docs] class BacklightControlService(IOService): @property def display_parameters(self) -> Mapping: return self.get('IODisplayParameters') @property def brightness(self) -> int: return self.display_parameters['brightness']['value'] @brightness.setter def brightness(self, value: int): self.set({'EnableBacklight': bool(value)}) self.set({'brightness': value})
[docs] class PowerSourceService(IOService): @property def battery_voltage(self) -> int: return self.get('AppleRawBatteryVoltage') @property def charging(self) -> bool: return self.get('IsCharging') @charging.setter def charging(self, value: bool): self.set({'IsCharging': value, 'ExternalConnected': value}) @property def external_connected(self) -> bool: return self.get('ExternalConnected') @external_connected.setter def external_connected(self, value: bool): self.set({'ExternalConnected': value}) @property def current_capacity(self) -> int: return self.get('CurrentCapacity') @current_capacity.setter def current_capacity(self, value: int): self.set({'CurrentCapacity': value}) @property def at_warn_level(self) -> bool: return self.get('AtWarnLevel') @at_warn_level.setter def at_warn_level(self, value: bool): self.set({'AtWarnLevel': value}) @property def time_remaining(self) -> int: return self.get('TimeRemaining') @property def temperature(self) -> int: return self.get('Temperature') @temperature.setter def temperature(self, value: int): self.set({'Temperature': value})
[docs] class IORegistry: """ IORegistry utils https://developer.apple.com/library/archive/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/TheRegistry/TheRegistry.html """ def __init__(self, client): """ :param rpcclient.darwin.client.DarwinClient client: """ self._client = client @property def backlight_control(self) -> BacklightControlService: service = self._client.symbols.IOServiceGetMatchingService( 0, self._client.cf({'IOPropertyMatch': {'backlight-control': True}})) if not service: raise RpcClientException('IOServiceGetMatchingService failed') return BacklightControlService(self._client, service) @property def power_source(self) -> PowerSourceService: service = self._client.symbols.IOServiceGetMatchingService( 0, self._client.symbols.IOServiceMatching('IOPMPowerSource')) if not service: raise RpcClientException('IOServiceGetMatchingService failed') return PowerSourceService(self._client, service) @property def root(self) -> IOService: with self._client.safe_malloc(mach_port_t.sizeof()) as p_master_port: self._client.symbols.IOMasterPort(MACH_PORT_NULL, p_master_port) return IOService(self._client, self._client.symbols.IORegistryGetRootEntry(p_master_port[0]))