AppleUserTestHIDDevice.cpp [plain text]
#include <assert.h>
#include <AssertMacros.h>
#include <stdio.h>
#include <stdlib.h>
#include <libkern/OSAtomic.h>
#include <IOKit/IOUserServer.h>
#include <DriverKit/DriverKit.h>
#include <DriverKit/OSCollections.h>
#include <IOKitUser/IODispatchQueue.h>
#include <IOKitUser/OSAction.h>
#include <IOKitUser/IOBufferMemoryDescriptor.h>
#include <HIDDriverKit/IOHIDInterface.h>
#include <HIDDriverKit/IOHIDDevice.h>
#include "Implementation/IOKitUser/AppleUserTestHIDDevice.h"
#define DLog(fmt, args...) printf("[DEF][AppleUserTestHIDDevice:%p] " fmt "\n", this, ##args)
#define ELog(fmt, args...) printf("[ERR][AppleUserTestHIDDevice:%p] " fmt "\n" , this, ##args)
struct AppleUserTestHIDDevice_IVars
{
IOHIDInterface * interface;
OSAction * interfaceAction;
OSDictionaryPtr properies;
IODispatchQueue * queue;
};
#define _interface (ivars->interface)
#define _interfaceAction (ivars->interfaceAction)
#define _properies (ivars->properies)
#define _queue (ivars->queue)
#undef super
#define super IOUserHIDDevice
bool AppleUserTestHIDDevice::init ()
{
bool ret;
DLog("Init:%p", this);
ret = super::init();
require_action(ret, exit, ELog("Init(SUPERDISPATCH):%x", ret));
assert(IOService::ivars);
ret = (ivars = IONewZero(AppleUserTestHIDDevice_IVars, 1));
exit:
return ret;
}
kern_return_t
IMPL(AppleUserTestHIDDevice, Start)
{
kern_return_t ret = kIOReturnError;
uint64_t pID;
uint64_t sID;
provider->GetRegistryEntryID(&pID);
GetRegistryEntryID(&sID);
DLog("Start:%p (id:0x%llx) provider:%p (id:0x%llx) ", this, sID, provider, pID);
_interface = OSDynamicCast(IOHIDInterface, provider);
require_action (_interface, exit, ELog("Invalid provider"));
_interface->retain();
ret = _interface->CopyProperties(&_properies);
require_noerr_action (ret, exit, ELog("CopyProperties:%x", ret));
OSObjectLog (_properies);
ret = Start(provider, SUPERDISPATCH);
require_noerr_action (ret, exit, ELog("Start:%x", ret));
ret = CopyDispatchQueue("Default", &_queue);
require_noerr_action (ret, exit, ELog("CopyDispatchQueue:%x", ret));
ret = CreateActionHandleReportCallback(
sizeof(uint64_t),
&_interfaceAction);
require_noerr_action (ret, exit, ELog("CreateActionHandleReportCallback:%x", ret));
ret = _interface->Open(0, _interfaceAction);
require_noerr_action (ret, exit, ELog("IOHIDInterface::Open:%x", ret));
exit:
return ret;
}
kern_return_t
IMPL(AppleUserTestHIDDevice, Stop)
{
if (_interface) {
_interface->Close(0);
}
Stop (provider, SUPERDISPATCH);
return kIOReturnSuccess;
}
void AppleUserTestHIDDevice::free()
{
OSSafeReleaseNULL(_interface);
OSSafeReleaseNULL(_interfaceAction);
OSSafeReleaseNULL(_queue);
OSObjectSafeReleaseNULL(_properies);
IOSafeDeleteNULL(ivars, AppleUserTestHIDDevice_IVars, 1);
super::free ();
}
void
IMPL(AppleUserTestHIDDevice, HandleReportCallback)
{
DLog("HandleReportCallback: %llx\n", timestamp);
HandleReport(timestamp, report, type, 0);
}
kern_return_t AppleUserTestHIDDevice::getReport(IOMemoryDescriptor * report,
IOHIDReportType reportType,
IOOptionBits options,
uint32_t completionTimeout,
OSAction * action)
{
kern_return_t ret;
ret = _interface->GetReport(report, reportType, options & 0xff, options & (~0xff));
require_noerr_action (ret, exit, ELog("IOHIDInterface::GetReport:0x%x\n", ret));
if (action) {
action->retain();
_queue->DispatchAsync(^{
CompleteReport(action, ret, 0);
action->release();
});
}
exit:
return ret;
}
kern_return_t AppleUserTestHIDDevice::setReport(IOMemoryDescriptor * report,
IOHIDReportType reportType,
IOOptionBits options,
uint32_t completionTimeout,
OSAction * action)
{
kern_return_t ret;
ret = _interface->SetReport(report, reportType, options & 0xff, options & (~0xff));
require_noerr_action (ret, exit, ELog("IOHIDInterface::SetReport:0x%x\n", ret));
if (action) {
action->retain();
_queue->DispatchAsync(^{
CompleteReport(action, ret, 0);
action->release();
});
}
exit:
return ret;
}
OSData * AppleUserTestHIDDevice::newReportDescriptor ()
{
OSData * descriptor = OSDynamicCast (OSData, OSDictionaryGetValue (_properies, kIOHIDReportDescriptorKey));
if (descriptor) {
descriptor->retain();
}
return descriptor;
}
#define CopyProperty(d,s,key) \
{ \
OSObjectPtr value = OSDictionaryGetValue (s,key); \
if (value) { \
OSDictionarySetValue (d, key, value); \
} \
}
OSDictionary * AppleUserTestHIDDevice::newDeviceDescription ()
{
OSDictionary * dictionary = OSDictionary::withCapacity(6);
require_action (dictionary, exit,ELog("OSDictionaryCreate"));
OSDictionarySetStringValue(dictionary, kIOHIDTransportKey, "TESTHID");
CopyProperty(dictionary, _properies, kIOHIDReportIntervalKey);
OSDictionarySetUInt64Value (dictionary, kIOHIDProductIDKey, 556);
OSDictionarySetUInt64Value (dictionary, kIOHIDVendorIDKey, 556);
OSDictionarySetStringValue (dictionary, kIOHIDTransportKey, "PassThrough");
exit:
return dictionary;
}