IOHIDPointingEventDevice.cpp [plain text]
#include <IOKit/IOLib.h>
#include "IOHIDFamilyPrivate.h"
#include "IOHIDPointingEventDevice.h"
#include "IOHIDPointing.h"
#include "IOHIDPrivateKeys.h"
#include "IOHIDDebug.h"
static UInt8 DefaultMouseDesc[] = {
0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, 0x08, 0x15, 0x00, 0x25, 0x01, 0x95, 0x08, 0x75, 0x01, 0x81, 0x02, 0x95, 0x00, 0x75, 0x01, 0x81, 0x00, 0x05, 0x01, 0x09, 0x01, 0xA1, 0x00, 0x09, 0x30, 0x09, 0x31, 0x16, 0x01, 0x80, 0x26, 0xFF, 0x7F, 0x36, 0x00, 0x00, 0x46, 0x00, 0x00, 0x65, 0x00, 0x55, 0x00, 0x09, 0x32, 0x75, 0x10, 0x95, 0x03, 0x81, 0x06, 0x95, 0x01, 0x75, 0x10, 0x16, 0x01, 0x80, 0x26, 0xFF, 0x7F, 0x09, 0x38, 0x81, 0x06, 0xC0, 0xC0, };
#define super IOHIDDeviceShim
OSDefineMetaClassAndStructors( IOHIDPointingEventDevice, IOHIDDeviceShim )
IOHIDPointingEventDevice *
IOHIDPointingEventDevice::newPointingDeviceAndStart(IOService *owner)
{
IOHIDPointingEventDevice * device = new IOHIDPointingEventDevice;
if (device)
{
if (!device->initWithParameters(0, true)){
device->release();
return 0;
}
device->setProperty("HIDDefaultBehavior", kOSBooleanTrue);
device->setProperty(kIOHIDCompatibilityInterface, kOSBooleanTrue);
if ( device->attach(owner) )
{
if (!device->start(owner))
{
device->detach(owner);
device->release();
device = 0;
}
}
else
{
device->release();
device = 0;
}
}
return device;
}
bool IOHIDPointingEventDevice::initWithLocation( UInt32 location )
{
if (!super::initWithLocation(location))
return false;
_report = 0;
return true;
}
void IOHIDPointingEventDevice::free()
{
if (_report) _report->release();
super::free();
}
bool IOHIDPointingEventDevice::handleStart( IOService * provider )
{
if (!super::handleStart(provider)) {
return false;
}
_report = IOBufferMemoryDescriptor::withCapacity(sizeof(GenericReport), kIODirectionNone, true);
if (_report) {
bzero(_report->getBytesNoCopy(), sizeof(GenericReport));
}
return (_report) ? true : false;
}
bool IOHIDPointingEventDevice::start( IOService * provider ) {
bool success = false;
if ( !super::start(provider) ) {
HIDLogError ("failed");
return false;
}
success = ((IOHIPointing*)provider)->open(
this,
kIOServiceSeize,
0,
(RelativePointerEventCallback) _relativePointerEvent,
(AbsolutePointerEventCallback) _absolutePointerEvent,
(ScrollWheelEventCallback) _scrollWheelEvent
);
provider->setProperty(kIOHIDResetPointerKey, kOSBooleanTrue);
return success;
}
IOReturn IOHIDPointingEventDevice::newReportDescriptor(
IOMemoryDescriptor ** descriptor ) const
{
void *desc;
if (!descriptor)
return kIOReturnBadArgument;
*descriptor = IOBufferMemoryDescriptor::withCapacity(
sizeof(DefaultMouseDesc),
kIODirectionNone,
true);
if (! *descriptor)
return kIOReturnNoMemory;
desc = ((IOBufferMemoryDescriptor *)(*descriptor))->getBytesNoCopy();
bcopy(DefaultMouseDesc, desc, sizeof(DefaultMouseDesc));
return kIOReturnSuccess;
}
IOReturn IOHIDPointingEventDevice::getReport(IOMemoryDescriptor *report,
IOHIDReportType reportType,
IOOptionBits options __unused )
{
if (!report)
return kIOReturnError;
if ( reportType != kIOHIDReportTypeInput)
return kIOReturnUnsupported;
report->writeBytes(0, _report->getBytesNoCopy(), min(report->getLength(), _report->getLength()));
return kIOReturnSuccess;
}
#define CONVERT_EV_TO_HW_BUTTONS(ev_buttons) ((ev_buttons & ~7) | ((ev_buttons & 3) << 1) | ((ev_buttons & 4) >> 2))
void IOHIDPointingEventDevice::_relativePointerEvent(
IOHIDPointingEventDevice * self,
int buttons,
int dx,
int dy,
AbsoluteTime ts __unused,
OSObject * sender __unused,
void * refcon __unused)
{
self->postMouseEvent(CONVERT_EV_TO_HW_BUTTONS(buttons), dx, dy, 0, 0);
}
void IOHIDPointingEventDevice::_absolutePointerEvent(
IOHIDPointingEventDevice * self __unused,
int buttons __unused,
IOGPoint * newLoc __unused,
IOGBounds * bounds __unused,
bool proximity __unused,
int pressure __unused,
int stylusAngle __unused,
AbsoluteTime ts __unused,
OSObject * sender __unused,
void * refcon __unused)
{
}
void IOHIDPointingEventDevice::_scrollWheelEvent(
IOHIDPointingEventDevice * self,
short deltaAxis1 __unused,
short deltaAxis2 __unused,
short deltaAxis3 __unused,
IOFixed fixedDelta1 __unused,
IOFixed fixedDelta2 __unused,
IOFixed fixedDelta3 __unused,
SInt32 pointDeltaAxis1,
SInt32 pointDeltaAxis2,
SInt32 pointDeltaAxis3 __unused,
UInt32 options __unused,
AbsoluteTime ts __unused,
OSObject * sender __unused,
void * refcon __unused)
{
self->postMouseEvent(0, 0, 0, pointDeltaAxis1, pointDeltaAxis2);
}
void IOHIDPointingEventDevice::postMouseEvent(UInt8 buttons, SInt16 x, SInt16 y, SInt16 vscroll, SInt16 hscroll)
{
GenericReport *report = (GenericReport*)_report->getBytesNoCopy();
if (!report) {
return;
}
report->buttons = buttons;
report->x = x;
report->y = y;
report->vscroll = vscroll;
report->hscroll = hscroll;
handleReport(_report);
}
OSString * IOHIDPointingEventDevice::newProductString() const
{
OSString * string = 0;
if ( !(string = super::newProductString()) )
string = OSString::withCString("Virtual Mouse");
return string;
}
OSNumber * IOHIDPointingEventDevice::newVendorIDNumber() const
{
return OSNumber::withNumber(0x5ac, 32);
}
OSNumber * IOHIDPointingEventDevice::newProductIDNumber() const
{
return OSNumber::withNumber(0xffff, 32);
}
OSString * IOHIDPointingEventDevice::newManufacturerString() const
{
return OSString::withCString("Apple");
}
IOReturn IOHIDPointingEventDevice::message(UInt32 type, IOService * provider, void * argument __unused)
{
IOReturn status = kIOReturnSuccess;
switch (type)
{
case kIOMessageServiceIsTerminated:
if (provider) {
provider->close( this );
}
break;
}
return status;
}
bool IOHIDPointingEventDevice::matchPropertyTable(OSDictionary *table, SInt32 * score __unused)
{
if (super::matchPropertyTable(table, score) == false) {
return false;
}
if (table->getObject(kIOHIDCompatibilityInterface)) {
return true;
}
return false;
}