mirror of
https://github.com/darlinghq/darling-iokitd.git
synced 2024-11-23 04:29:40 +00:00
Introduce IORegistryEntry, work on supporting a plane-based hierarchy
This commit is contained in:
parent
31fe24a002
commit
cf97f7a4ba
@ -24,14 +24,17 @@ include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/libcxx/include ${CMA
|
||||
|
||||
mig(iokitmig.defs)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
|
||||
|
||||
set(iokitd_sources
|
||||
src/main.mm
|
||||
src/stubs.c
|
||||
src/iokitd.cpp
|
||||
src/Registry.mm
|
||||
src/ServiceRegistry.mm
|
||||
src/IOObject.cpp
|
||||
src/IOIterator.cpp
|
||||
src/IOService.mm
|
||||
src/IORegistryEntry.mm
|
||||
src/IODisplayConnect.mm
|
||||
src/IODisplayConnectX11.mm
|
||||
${CMAKE_CURRENT_BINARY_DIR}/iokitmigServer.c
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef IOKITD_IODISPLAYCONNECTX11_H
|
||||
#define IOKITD_IODISPLAYCONNECTX11_H
|
||||
#include "IODisplayConnect.h"
|
||||
#include "Registry.h"
|
||||
#include "ServiceRegistry.h"
|
||||
#include <vector>
|
||||
#include <X11/Xlib.h>
|
||||
#import <Foundation/NSData.h>
|
||||
@ -13,13 +13,15 @@ private:
|
||||
IODisplayConnectX11(int index, NSDictionary* props);
|
||||
public:
|
||||
~IODisplayConnectX11();
|
||||
static void discoverDevices(Registry* targetRegistry);
|
||||
static void discoverDevices(ServiceRegistry* targetRegistry);
|
||||
NSDictionary* getProperties() override;
|
||||
private:
|
||||
static Display* m_display;
|
||||
// Index of the corresponding XrandR output
|
||||
int m_index;
|
||||
|
||||
NSDictionary* m_props;
|
||||
static IORegistryEntry* m_root;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -3,9 +3,11 @@
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <IOKit/graphics/IOGraphicsTypes.h>
|
||||
#include <CoreFoundation/CFByteOrder.h>
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <cstdio>
|
||||
|
||||
Display* IODisplayConnectX11::m_display;
|
||||
IORegistryEntry* IODisplayConnectX11::m_root;
|
||||
|
||||
IODisplayConnectX11::IODisplayConnectX11(int index, NSDictionary* props)
|
||||
: m_index(index)
|
||||
@ -18,8 +20,20 @@ IODisplayConnectX11::~IODisplayConnectX11()
|
||||
[m_props release];
|
||||
}
|
||||
|
||||
void IODisplayConnectX11::discoverDevices(Registry* targetRegistry)
|
||||
NSDictionary* IODisplayConnectX11::getProperties()
|
||||
{
|
||||
return m_props;
|
||||
}
|
||||
|
||||
void IODisplayConnectX11::discoverDevices(ServiceRegistry* targetServiceRegistry)
|
||||
{
|
||||
static dispatch_once_t once;
|
||||
|
||||
dispatch_once(&once, ^{
|
||||
m_root = new IORegistryEntry;
|
||||
m_root->registerInPlane(kIOServicePlane, "X11Display", IORegistryEntry::root());
|
||||
});
|
||||
|
||||
if (!m_display)
|
||||
{
|
||||
m_display = XOpenDisplay(NULL);
|
||||
@ -89,11 +103,18 @@ void IODisplayConnectX11::discoverDevices(Registry* targetRegistry)
|
||||
[props setObject: [NSNumber numberWithInt: year]
|
||||
forKey: @(kDisplayYearOfManufacture)];
|
||||
}
|
||||
else
|
||||
{
|
||||
[props setObject: [NSNumber numberWithInt: i+1]
|
||||
forKey: @(kDisplaySerialNumber)];
|
||||
}
|
||||
|
||||
XRRFreeCrtcInfo(crtc);
|
||||
}
|
||||
|
||||
targetRegistry->registerService(new IODisplayConnectX11(i, props));
|
||||
|
||||
IODisplayConnectX11* ioDisplay = new IODisplayConnectX11(i, props);
|
||||
targetServiceRegistry->registerService(ioDisplay);
|
||||
ioDisplay->registerInPlane(kIOServicePlane, oinfo->name, m_root);
|
||||
|
||||
XRRFreeOutputInfo(oinfo);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "IOObject.h"
|
||||
#include "iokitd.h"
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <os/log.h>
|
||||
#include <dispatch/private.h>
|
||||
extern "C" {
|
||||
@ -74,6 +75,11 @@ IOObject* IOObject::lookup(mach_port_t port)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool IOObject::conformsTo(const char* className)
|
||||
{
|
||||
return std::strcmp(className, this->className());
|
||||
}
|
||||
|
||||
boolean_t IOObject::deathNotify(mach_msg_header_t *request, mach_msg_header_t *reply)
|
||||
{
|
||||
mach_no_senders_notification_t* Request = (mach_no_senders_notification_t*) request;
|
||||
@ -106,3 +112,32 @@ boolean_t IOObject::deathNotify(mach_msg_header_t *request, mach_msg_header_t *r
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
kern_return_t is_io_object_get_class
|
||||
(
|
||||
mach_port_t object,
|
||||
io_name_t className
|
||||
)
|
||||
{
|
||||
IOObject* o = IOObject::lookup(object);
|
||||
if (!o)
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
|
||||
strlcpy(className, o->className(), sizeof(io_name_t));
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
kern_return_t is_io_object_conforms_to
|
||||
(
|
||||
mach_port_t object,
|
||||
io_name_t className,
|
||||
boolean_t *conforms
|
||||
)
|
||||
{
|
||||
IOObject* o = IOObject::lookup(object);
|
||||
if (!o)
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
|
||||
*conforms = o->conformsTo(className);
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ public:
|
||||
virtual ~IOObject();
|
||||
|
||||
virtual const char* className() const = 0;
|
||||
virtual bool conformsTo(const char* className);
|
||||
|
||||
void retain();
|
||||
void release();
|
||||
|
31
src/IORegistryEntry.h
Normal file
31
src/IORegistryEntry.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef IOKIT_IOREGISTRYENTRY_H
|
||||
#define IOKIT_IOREGISTRYENTRY_H
|
||||
#include "IOObject.h"
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <set>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
|
||||
class IORegistryEntry : public IOObject
|
||||
{
|
||||
public:
|
||||
virtual NSDictionary* getProperties();
|
||||
|
||||
const char* className() const override;
|
||||
|
||||
std::string_view getPathName(const char* plane);
|
||||
std::string getPath(const char* plane);
|
||||
std::set<IORegistryEntry*> getParents(const char* plane);
|
||||
std::set<IORegistryEntry*> getChildren(const char* plane);
|
||||
|
||||
static IORegistryEntry* root();
|
||||
|
||||
void registerInPlane(const char* plane, const char* pathName, IORegistryEntry* parent);
|
||||
protected:
|
||||
// The key is the plane name, e.g. kIOServicePlane (as declared in IOKit/IOKitKeys.h)
|
||||
std::unordered_map<std::string_view, std::string> m_name;
|
||||
std::unordered_map<std::string_view, std::set<IORegistryEntry*>> m_parents, m_children;
|
||||
};
|
||||
|
||||
#endif
|
164
src/IORegistryEntry.mm
Normal file
164
src/IORegistryEntry.mm
Normal file
@ -0,0 +1,164 @@
|
||||
#include "IORegistryEntry.h"
|
||||
#include <stack>
|
||||
#include <IOCFSerialize.h>
|
||||
#include <cstring>
|
||||
extern "C" {
|
||||
#include "iokitmigServer.h"
|
||||
}
|
||||
|
||||
NSDictionary* IORegistryEntry::getProperties()
|
||||
{
|
||||
return @{};
|
||||
}
|
||||
|
||||
const char* IORegistryEntry::className() const
|
||||
{
|
||||
return "IORegistryEntry";
|
||||
}
|
||||
|
||||
std::string_view IORegistryEntry::getPathName(const char* plane)
|
||||
{
|
||||
auto it = m_name.find(plane);
|
||||
if (it != m_name.end())
|
||||
return it->second;
|
||||
return "?";
|
||||
}
|
||||
|
||||
std::set<IORegistryEntry*> IORegistryEntry::getParents(const char* plane)
|
||||
{
|
||||
auto it = m_parents.find(plane);
|
||||
if (it != m_parents.end())
|
||||
return it->second;
|
||||
return std::set<IORegistryEntry*>();
|
||||
}
|
||||
|
||||
std::set<IORegistryEntry*> IORegistryEntry::getChildren(const char* plane)
|
||||
{
|
||||
auto it = m_children.find(plane);
|
||||
if (it != m_children.end())
|
||||
return it->second;
|
||||
return std::set<IORegistryEntry*>();
|
||||
}
|
||||
|
||||
void IORegistryEntry::registerInPlane(const char* plane, const char* pathName, IORegistryEntry* parent)
|
||||
{
|
||||
m_name[plane] = pathName;
|
||||
|
||||
auto it = m_parents.find(plane);
|
||||
|
||||
if (it == m_parents.end())
|
||||
it = m_parents.insert(std::make_pair(std::string_view(plane), std::set<IORegistryEntry*>())).first;
|
||||
|
||||
it->second.insert(parent);
|
||||
|
||||
it = parent->m_children.find(plane);
|
||||
if (it == parent->m_children.end())
|
||||
it = parent->m_children.insert(std::make_pair(std::string_view(plane), std::set<IORegistryEntry*>())).first;
|
||||
|
||||
it->second.insert(this);
|
||||
}
|
||||
|
||||
std::string IORegistryEntry::getPath(const char* plane)
|
||||
{
|
||||
std::stack<std::string> components;
|
||||
IORegistryEntry* cur = this;
|
||||
|
||||
while (true)
|
||||
{
|
||||
std::set<IORegistryEntry*> parents = cur->getParents(plane);
|
||||
if (parents.empty())
|
||||
{
|
||||
if (cur != root())
|
||||
return "?unsup_plane?";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
IORegistryEntry* parent = *parents.begin();
|
||||
components.push(parent->getPath(plane));
|
||||
cur = parent;
|
||||
}
|
||||
|
||||
std::string path = plane;
|
||||
path += ":";
|
||||
|
||||
while (!components.empty())
|
||||
{
|
||||
path += "/";
|
||||
path += components.top();
|
||||
components.pop();
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
IORegistryEntry* IORegistryEntry::root()
|
||||
{
|
||||
static IORegistryEntry e;
|
||||
return &e;
|
||||
}
|
||||
|
||||
kern_return_t is_io_registry_entry_get_path
|
||||
(
|
||||
mach_port_t registry_entry,
|
||||
io_name_t plane,
|
||||
io_string_t path
|
||||
)
|
||||
{
|
||||
IORegistryEntry* e = dynamic_cast<IORegistryEntry*>(IOObject::lookup(registry_entry));
|
||||
if (!e)
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
|
||||
std::string mypath = e->getPath(plane);
|
||||
strlcpy(path, mypath.c_str(), sizeof(io_string_t));
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
kern_return_t is_io_registry_entry_create_iterator
|
||||
(
|
||||
mach_port_t registry_entry,
|
||||
io_name_t plane,
|
||||
uint32_t options,
|
||||
mach_port_t *iterator
|
||||
)
|
||||
{
|
||||
puts("STUB is_io_registry_entry_create_iterator");
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_registry_entry_get_properties_bin
|
||||
(
|
||||
mach_port_t registry_entry,
|
||||
io_buf_ptr_t *properties,
|
||||
mach_msg_type_number_t *propertiesCnt
|
||||
)
|
||||
{
|
||||
IORegistryEntry* e = dynamic_cast<IORegistryEntry*>(IOObject::lookup(registry_entry));
|
||||
if (!e)
|
||||
return KERN_INVALID_ARGUMENT;
|
||||
|
||||
NSDictionary* props = e->getProperties();
|
||||
|
||||
CFDataRef data = IOCFSerialize(props, kIOCFSerializeToBinary);
|
||||
|
||||
*propertiesCnt = CFDataGetLength(data);
|
||||
kern_return_t kr = vm_allocate(mach_task_self(), (vm_address_t*) properties, *propertiesCnt, true);
|
||||
|
||||
if (kr == KERN_SUCCESS)
|
||||
{
|
||||
memcpy(*properties, CFDataGetBytePtr(data), *propertiesCnt);
|
||||
}
|
||||
|
||||
CFRelease(data);
|
||||
|
||||
return kr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// STUB called: is_io_registry_entry_get_property_bin
|
||||
// STUB called: is_io_registry_entry_create_iterator
|
||||
// STUB called: is_io_registry_entry_get_properties_bin
|
||||
// STUB called: is_io_registry_get_root_entry
|
||||
// STUB called: is_io_registry_entry_from_path
|
@ -1,9 +1,9 @@
|
||||
#ifndef IOKITD_IOSERVICE_H
|
||||
#define IOKITD_IOSERVICE_H
|
||||
#include <Foundation/NSDictionary.h>
|
||||
#include "IOObject.h"
|
||||
#include "IORegistryEntry.h"
|
||||
|
||||
class IOService : public IOObject
|
||||
class IOService : public IORegistryEntry
|
||||
{
|
||||
public:
|
||||
IOService();
|
||||
|
@ -5,12 +5,12 @@
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#include "IOIterator.h"
|
||||
|
||||
class Registry
|
||||
class ServiceRegistry
|
||||
{
|
||||
private:
|
||||
Registry() {}
|
||||
ServiceRegistry() {}
|
||||
public:
|
||||
static Registry* instance();
|
||||
static ServiceRegistry* instance();
|
||||
void registerService(IOService* service);
|
||||
IOIterator* iteratorForMatchingServices(NSDictionary* criteria) const;
|
||||
private:
|
@ -1,5 +1,5 @@
|
||||
#include "iokitd.h"
|
||||
#include "Registry.h"
|
||||
#include "ServiceRegistry.h"
|
||||
#include <IOCFUnserialize.h>
|
||||
#include <CoreFoundation/CFString.h>
|
||||
#include <os/log.h>
|
||||
@ -10,13 +10,13 @@ extern "C" {
|
||||
#include "iokitmigServer.h"
|
||||
}
|
||||
|
||||
Registry* Registry::instance()
|
||||
ServiceRegistry* ServiceRegistry::instance()
|
||||
{
|
||||
static Registry reg;
|
||||
static ServiceRegistry reg;
|
||||
return ®
|
||||
}
|
||||
|
||||
IOIterator* Registry::iteratorForMatchingServices(NSDictionary* criteria) const
|
||||
IOIterator* ServiceRegistry::iteratorForMatchingServices(NSDictionary* criteria) const
|
||||
{
|
||||
std::vector<IOObject*> matching;
|
||||
|
||||
@ -29,7 +29,7 @@ IOIterator* Registry::iteratorForMatchingServices(NSDictionary* criteria) const
|
||||
return new IOIterator(matching);
|
||||
}
|
||||
|
||||
void Registry::registerService(IOService* service)
|
||||
void ServiceRegistry::registerService(IOService* service)
|
||||
{
|
||||
m_registeredServices.push_back(service);
|
||||
}
|
||||
@ -67,7 +67,7 @@ kern_return_t is_io_service_get_matching_services_bin
|
||||
|
||||
// Criteria example:
|
||||
// IOProviderClass -> IODisplayConnect
|
||||
IOIterator* iterator = Registry::instance()->iteratorForMatchingServices((NSDictionary*) criteria);
|
||||
IOIterator* iterator = ServiceRegistry::instance()->iteratorForMatchingServices((NSDictionary*) criteria);
|
||||
CFShow(criteria);
|
||||
CFRelease(criteria);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <liblaunch/bootstrap.h>
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <dispatch/private.h>
|
||||
#include <IOKit/IOKitKeys.h>
|
||||
#include <cstdlib>
|
||||
#include "iokitd.h"
|
||||
#include "iokitmig.h"
|
||||
@ -77,6 +78,6 @@ int main(int argc, const char** argv)
|
||||
|
||||
static void discoverAllDevices()
|
||||
{
|
||||
Registry* registry = Registry::instance();
|
||||
ServiceRegistry* registry = ServiceRegistry::instance();
|
||||
IODisplayConnectX11::discoverDevices(registry);
|
||||
}
|
||||
|
109
src/stubs.c
109
src/stubs.c
@ -3,27 +3,6 @@
|
||||
|
||||
#define STUB() os_log(OS_LOG_DEFAULT, "%d STUB called: %s", getpid(), __FUNCTION__); printf("STUB called: %s\n", __FUNCTION__)
|
||||
|
||||
kern_return_t is_io_object_get_class
|
||||
(
|
||||
mach_port_t object,
|
||||
io_name_t className
|
||||
)
|
||||
{
|
||||
STUB();
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_object_conforms_to
|
||||
(
|
||||
mach_port_t object,
|
||||
io_name_t className,
|
||||
boolean_t *conforms
|
||||
)
|
||||
{
|
||||
STUB();
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_service_get_matching_services
|
||||
(
|
||||
mach_port_t master_port,
|
||||
@ -266,26 +245,6 @@ kern_return_t is_io_connect_method_structureI_structureO
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_registry_entry_get_path
|
||||
(
|
||||
mach_port_t registry_entry,
|
||||
io_name_t plane,
|
||||
io_string_t path
|
||||
)
|
||||
{
|
||||
STUB();
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_registry_get_root_entry
|
||||
(
|
||||
mach_port_t master_port,
|
||||
mach_port_t *root
|
||||
)
|
||||
{
|
||||
STUB();
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_registry_entry_set_properties
|
||||
(
|
||||
@ -340,18 +299,6 @@ kern_return_t is_io_service_wait_quiet
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_registry_entry_create_iterator
|
||||
(
|
||||
mach_port_t registry_entry,
|
||||
io_name_t plane,
|
||||
uint32_t options,
|
||||
mach_port_t *iterator
|
||||
)
|
||||
{
|
||||
STUB();
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_catalog_send_data
|
||||
(
|
||||
mach_port_t master_port,
|
||||
@ -904,30 +851,6 @@ kern_return_t is_io_server_version
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_registry_entry_get_properties_bin
|
||||
(
|
||||
mach_port_t registry_entry,
|
||||
io_buf_ptr_t *properties,
|
||||
mach_msg_type_number_t *propertiesCnt
|
||||
)
|
||||
{
|
||||
STUB();
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_registry_entry_get_property_bin
|
||||
(
|
||||
mach_port_t registry_entry,
|
||||
io_name_t plane,
|
||||
io_name_t property_name,
|
||||
uint32_t options,
|
||||
io_buf_ptr_t *properties,
|
||||
mach_msg_type_number_t *propertiesCnt
|
||||
)
|
||||
{
|
||||
STUB();
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_service_get_matching_service_bin
|
||||
(
|
||||
@ -985,13 +908,24 @@ kern_return_t is_io_service_add_notification_bin_64
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_registry_entry_get_path_ool
|
||||
kern_return_t is_io_registry_entry_get_property_bin
|
||||
(
|
||||
mach_port_t registry_entry,
|
||||
io_name_t plane,
|
||||
io_string_inband_t path,
|
||||
io_buf_ptr_t *path_ool,
|
||||
mach_msg_type_number_t *path_oolCnt
|
||||
io_name_t property_name,
|
||||
uint32_t options,
|
||||
io_buf_ptr_t *properties,
|
||||
mach_msg_type_number_t *propertiesCnt
|
||||
)
|
||||
{
|
||||
STUB();
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_registry_get_root_entry
|
||||
(
|
||||
mach_port_t master_port,
|
||||
mach_port_t *root
|
||||
)
|
||||
{
|
||||
STUB();
|
||||
@ -1011,3 +945,16 @@ kern_return_t is_io_registry_entry_from_path_ool
|
||||
STUB();
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
kern_return_t is_io_registry_entry_get_path_ool
|
||||
(
|
||||
mach_port_t registry_entry,
|
||||
io_name_t plane,
|
||||
io_string_inband_t path,
|
||||
io_buf_ptr_t *path_ool,
|
||||
mach_msg_type_number_t *path_oolCnt
|
||||
)
|
||||
{
|
||||
STUB();
|
||||
return KERN_NOT_SUPPORTED;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user