IOHIDEventProcessorFilter.hpp [plain text]
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 2016 Apple Computer, Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef IOHIDEventProcessorFilter_hpp
#define IOHIDEventProcessorFilter_hpp
#include <sys/cdefs.h>
#include <CoreFoundation/CoreFoundation.h>
#if COREFOUNDATION_CFPLUGINCOM_SEPARATE
#include <CoreFoundation/CFPlugInCOM.h>
#endif
#include <IOKit/hid/IOHIDServiceFilterPlugIn.h>
typedef enum _KPState {
kKPStateNone = 0,
kKPStateFirstDown,
kKPStateFirstUp,
kKPStateSecondDown,
kKPStateSecondUp,
kKPStateThirdDown,
kKPStateThirdUp,
kKPStateTerminalEvent,
kKPStateLongPress,
kKPStateCount,
} KPState;
typedef enum _KPTransition {
kKPTransitionDown,
kKPTransitionUp,
kKPTransitionTimeout,
kKPTransitionCount,
} KPTransition;
class Event;
class IOHIDEventProcessor;
class Timer {
private:
dispatch_source_t _timer;
dispatch_queue_t _queue;
Event * _headEvent;
public:
Timer();
void init(dispatch_queue_t q);
void cancel(dispatch_queue_t q);
void setQueue(dispatch_queue_t q) { _queue = q; };
void registerEventTimeout(Event * event, UInt64 deadline);
void callTimeoutHandlers();
void removeEvent(Event * event);
void insertEvent(Event * event);
void updateTimeout();
};
class Event {
private:
UInt64 _nextTimeout;
Event * _nextEvent;
Event * _nextTimerEvent;
IOHIDEventProcessor * _owner;
bool _isComplete;
protected:
IOHIDEventType _eventType;
UInt32 _usagePage;
UInt32 _usage;
Timer * _timer;
UInt32 _state;
UInt32 _timeoutState;
int _multiEventCount;
bool _terminalEventDispatched;
UInt64 _secondEventTimeout;
UInt64 _thirdEventTimeout;
UInt64 _lastActionTimestamp;
UInt64 _longPressTimeout;
public:
void init(IOHIDEventProcessor * owner, Timer * timer, IOHIDEventType type, UInt32 usagePage, UInt32 usage, UInt64 secondEventTimeout, UInt64 thirdEventTimeout, UInt64 longPressTimeout);
bool eventOccurred(IOHIDEventRef event, bool timedOut, IOHIDEventRef &terminalEvent);
bool conformsTo(IOHIDEventType type, UInt32 usagePage, UInt32 usage);
Event();
virtual ~Event();
IOHIDEventType getEventType() { return _eventType; };
Event * getNextEvent() { return _nextEvent; };
void setNextEvent(Event *event) { _nextEvent = event; };
Event * getNextTimerEvent() { return _nextTimerEvent; };
void setNextTimerEvent(Event *event) { _nextTimerEvent = event; };
UInt64 getNextTimeout() { return _nextTimeout; };
void setEventType(IOHIDEventType type) { _eventType = type; };
void setSecondEventTimeout(UInt64 timeout) { _secondEventTimeout = timeout; };
void setThirdEventTimeout(UInt64 timeout) { _thirdEventTimeout = timeout; };
void setLongPressTimeout(UInt64 timeout) { _longPressTimeout = timeout; };
void dispatchEvent(IOHIDEventRef event);
void completed();
bool assignTerminalEventOnTimeout(UInt64 timeout, IOHIDEventRef &terminalEvent);
void setNextTimeout(UInt64 timeout) { _nextTimeout = timeout; };
virtual IOHIDEventRef createSyntheticEvent(bool isTerminalEvent) = 0;
virtual void setMultiEventCount(IOHIDEventRef event, CFIndex count) = 0;
virtual void NoneEnter(IOHIDEventRef event) = 0;
virtual void FDEnter(IOHIDEventRef event) = 0;
virtual void FUEnter(IOHIDEventRef event) = 0;
virtual void SDEnter(IOHIDEventRef event) = 0;
virtual void SUEnter(IOHIDEventRef event) = 0;
virtual void TDEnter(IOHIDEventRef event) = 0;
virtual void TUEnter(IOHIDEventRef event) = 0;
virtual void TOEnter(IOHIDEventRef event) = 0;
virtual void TEEnter(IOHIDEventRef event) = 0;
virtual void LPEnter(IOHIDEventRef event) = 0;
bool stateHandler(KPTransition e, IOHIDEventRef event = 0);
inline bool operator == (const Event &b) const
{
return ((b._usagePage == _usagePage) && (b._usage == _usage) && (b._eventType == _eventType));
}
bool isComplete() {return _isComplete;};
UInt64 epoch() {return _lastActionTimestamp;};
};
class ButtonEvent : public Event {
private:
IOHIDEventRef createSyntheticEvent(bool isTerminalEvent);
void setMultiEventCount(IOHIDEventRef event, CFIndex count);
void NoneEnter(IOHIDEventRef event);
void FDEnter(IOHIDEventRef event);
void FUEnter(IOHIDEventRef event);
void SDEnter(IOHIDEventRef event);
void SUEnter(IOHIDEventRef event);
void TDEnter(IOHIDEventRef event);
void TUEnter(IOHIDEventRef event);
void TOEnter(IOHIDEventRef event);
void TEEnter(IOHIDEventRef event);
void LPEnter(IOHIDEventRef event);
};
class TapEvent : public Event {
private:
IOHIDEventRef createSyntheticEvent(bool isTerminalEvent);
void setMultiEventCount(IOHIDEventRef event, CFIndex count);
void NoneEnter(IOHIDEventRef event);
void FDEnter(IOHIDEventRef event);
void FUEnter(IOHIDEventRef event);
void SDEnter(IOHIDEventRef event);
void SUEnter(IOHIDEventRef event);
void TDEnter(IOHIDEventRef event);
void TUEnter(IOHIDEventRef event);
void TOEnter(IOHIDEventRef event);
void TEEnter(IOHIDEventRef event);
void LPEnter(IOHIDEventRef event);
};
class IOHIDEventProcessor {
public:
IOHIDEventProcessor(CFUUIDRef factoryID);
~IOHIDEventProcessor();
HRESULT QueryInterface( REFIID iid, LPVOID *ppv );
ULONG AddRef();
ULONG Release();
SInt32 match(IOHIDServiceRef service, IOOptionBits options);
IOHIDEventRef filter(IOHIDEventRef event);
IOHIDEventRef filterCopyEvent(IOHIDEventRef event);
void open(IOHIDServiceRef service, IOOptionBits options);
CFTypeRef copyPropertyForClient(CFStringRef key, CFTypeRef client);
void setPropertyForClient(CFStringRef key, CFTypeRef property, CFTypeRef client);
void dispatchEvent(IOHIDEventRef event);
void returnToFreePool(Event * event);
private:
static IOHIDServiceFilterPlugInInterface sIOHIDEventProcessorFtbl;
IOHIDServiceFilterPlugInInterface *_serviceInterface;
CFUUIDRef _factoryID;
UInt32 _refCount;
dispatch_queue_t _queue;
IOHIDServiceRef _service;
IOHIDServiceEventCallback _eventCallback;
void * _eventTarget;
void * _eventContext;
bool _multiPressTrackingEnabled;
CFArrayRef _multiPressUsagePairs;
UInt64 _multiPressDoublePressTimeout;
UInt64 _multiPressTriplePressTimeout;
bool _multiTapTrackingEnabled;
UInt64 _multiTapDoubleTapTimeout;
UInt64 _multiTapTripleTapTimeout;
UInt64 _longPressTimeout;
Event * _eventHead;
Event * _freeButtonHead;
Event * _freeTapHead;
Timer * _timer;
static HRESULT QueryInterface( void *self, REFIID iid, LPVOID *ppv );
static ULONG AddRef( void *self );
static ULONG Release( void *self );
static SInt32 match(void * self, IOHIDServiceRef service, IOOptionBits options);
static IOHIDEventRef filter(void * self, IOHIDEventRef event);
static void setEventCallback(void * self, IOHIDServiceEventCallback callback, void * target, void * refcon);
static IOHIDEventRef filterCopyEvent(void * self, IOHIDEventRef event);
static CFTypeRef copyPropertyForClient(void * self,CFStringRef key, CFTypeRef client);
static void setPropertyForClient(void * self,CFStringRef key, CFTypeRef property, CFTypeRef client);
static void scheduleWithDispatchQueue(void * self, dispatch_queue_t queue);
static void unscheduleFromDispatchQueue(void * self, dispatch_queue_t queue);
static void open(void * self, IOHIDServiceRef service, IOOptionBits options);
IOHIDEventProcessor(const IOHIDEventProcessor &);
IOHIDEventProcessor &operator=(const IOHIDEventProcessor &);
void scheduleWithDispatchQueue(dispatch_queue_t queue);
void unscheduleFromDispatchQueue(dispatch_queue_t queue);
void setEventCallback(IOHIDServiceEventCallback callback, void * target, void * refcon);
void setTimeoutForState(UInt64 timeout, KPState state);
void serialize (CFMutableDictionaryRef dict) const;
};
#endif /* IOHIDEventProcessorFilter_hpp */