/*
* Copyright (c) 1998-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* The contents of this file constitute Original Code as defined in and
* are subject to the Apple Public Source License Version 1.1 (the
* "License"). You may not use this file except in compliance with the
* License. Please obtain a copy of the License at
* http://www.apple.com/publicsource and read it before using this file.
*
* This 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 OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* 18 June 1998 sdouglas Start IOKit version.
* 18 Nov 1998 suurballe port to C++
* 4 Oct 1999 decesare Revised for Type 4 support and sub-classed drivers.
* 28 June 2005 ffscroll Move most trackpad data and preferences into structs to make them easier to manage
*/
#include <IOKit/adb/IOADBDevice.h>
#include <IOKit/hidsystem/IOHIPointing.h>
#include <IOKit/hid/IOHIDDevice.h>
#include <IOKit/IOTimerEventSource.h>
#include "FFScrollRegKeys.h"
//#define FFSPREFSDEBUG
//#define FFSDEBUGCOORDS
//#define FFSDEBUG
//#define FFSDEBUGSCROLLING
class AppleADBMouse: public IOHIPointing
{
OSDeclareDefaultStructors(AppleADBMouse);
protected:
IOADBDevice * adbDevice;
IOFixed _resolution;
IOItemCount _buttonCount;
public:
virtual IOService * probe(IOService * provider, SInt32 * score);
virtual bool start(IOService * provider);
virtual UInt32 interfaceID(void);
virtual UInt32 deviceType(void);
virtual IOFixed resolution(void);
virtual IOItemCount buttonCount(void);
virtual void packet(UInt8 adbCommand, IOByteCount length, UInt8 * data);
};
class AppleADBMouseType1 : public AppleADBMouse
{
OSDeclareDefaultStructors(AppleADBMouseType1);
public:
virtual IOService * probe(IOService * provider, SInt32 * score);
virtual bool start(IOService * provider);
};
class AppleADBMouseType2 : public AppleADBMouse
{
OSDeclareDefaultStructors(AppleADBMouseType2);
public:
virtual IOService * probe(IOService * provider, SInt32 * score);
virtual bool start(IOService * provider);
};
typedef struct coord
{
SInt16 x0,x1,y0,y1;
} COORD;
typedef struct scrollhotspot // struct defining scroll hotspots
{
int type; // [0:absolute, 1:relative, 2:full relative]
COORD coordRel; // relative coords
COORD coordAbs; // absolute coords
bool invert; // invert direction? [true:invert, false:normal]
int direction; // direction of the scroll area [0:vertical, 1:horizontal, 2:both]
bool scrollOutsideArea; // continue scrolling outside the region [true:continue, false:don't]
bool scaleSpeed; // scale the speed of the scolling [true, false]
int speedScale; // amount to scale the speed by [100..1000]
int autoScrollCap; // size of caps (for region scrolling) [0..50]
int autoScrollRate; // rate to autoscroll at (for non vel) [10..100]
int autoScrollMode; // which autoscroll mode to use [0:no autoscrolling, 1:autoscrolling in regions, 2:velocity autoscrolling, 3:always autoscrolling]
} SCROLLHOTSPOT;
typedef struct actionhotspot // struct defining action hotspots
{
int type; // [0:absolute, 1:relative, 2:full relative]
COORD coordRel; // relative coords
COORD coordAbs; // absolute coords
int button; // what mouse button it maps to [1..6:mouse button]
} ACTIONHOTSPOT;
typedef struct twofingerscrollingprefs // struct to hold prefs related to two-finger scrolling
{
bool circularScrollingEnabled;
bool horizontalScrollingEnabled;
bool verticalScrollingEnabled;
UInt16 circularScrollingRate;
UInt16 horizontalScrollingRate;
UInt16 verticalScrollingRate;
bool invertCircularScrolling;
bool invertVerticalScrolling;
bool invertHorizontalScrolling;
UInt16 circularScrollingThreshold;
UInt16 horizontalScrollingThreshold;
UInt16 verticalScrollingThreshold;
bool scrollDominantOnly;
int zArraySize; // number of z points to remember
SInt16 zAcceptThreshold; // threshold to accept z sample as 2 finger down
SInt16 zDeclineThreshold; // threshold to accept z sample as 2 finger up
SInt16 stickTwoFingerStart; // number of samples required to start 2 finger function
SInt16 stickTwoFingerStop; // number of samples required to stop 2 finger function
} TWOFINGERSCROLLINGPREFS;
typedef struct padprefs // all time units are in ns
{
//TODO
UInt64 minTapDuration; //TOADD
UInt64 maxTapDuration; //maximum gap between finger down and finger up to cause a tap event
UInt64 minTapDragTime; //minimum amount of time finger must leave the pad for it to be considered the start of a drag after a tap
UInt64 maxTapDragTime; //maximum amount of time between tap and drag start to cause a drag event
UInt64 minDragAssumedTime; //time finger must spend on pad after starting a drag for it to be considered one
UInt64 maxTapDragRevTime; // maximum amount of time finger can leave a pad without ending a drag event
bool tapDragLock; // preference for if drag locks or not, currently not working properly (may be an OSX thing )
bool tapDragEnable; // if tap dragging is turned on
bool tapClickEnable; // if you can cause a click by tapping the trackpad
int physicalButtonAction; // the action taken by pressing the physical trackpad button in bit form (ie 2^(n-1) represents button n)
int physicalButtonDragAction; // the action taken by pressing the physical trackpad button in bit form (ie 2^(n-1) represents button n)
// bool buttonMaintainsDrag; // if holding a button down keeps the tap drag event going (stickTapDrag is kept set while the button is on the trackpad)
bool buttonStopsDrag; // only really makes sense when physicalButtonDragAction==1 if on button press the drag event is ended (if the button is mapped to the same as the drag event then you will be dragging until the button is released)
bool buttonStopsDragWhenFingerUp; // if finger is off the pad then the button returns to its normal action
UInt16 minX,minY,maxX,maxY; // limits of the trackpad values
TWOFINGERSCROLLINGPREFS twoFingerScrollingPrefs; // Preferences for two finger scrolling
// ACTION HOTSPOTS
// ---------------
bool hasHotspots; // has areas on the trackpad that when tapped do something other than a normal click
int numberOfHotspots; // number of hotspots
ACTIONHOTSPOT* Hotspots; // Array containing hotspots
// SCROLL HOTSPOTS
// ---------------
bool hasScrollAreas; // if we have scroll areas defined
int numberOfScrollAreas; // number of scroll hotspots
SCROLLHOTSPOT* ScrollAreas; // array of scrollHotspots
bool scaleTrackpadSpeed; // if we should scale trackpad speed
UInt16 speedScale; // the amount we should scale by *100
UInt16 doubleTapTolerance; // maximum distance two taps can be apart to register as a double click or tap-drag
UInt16 tapTolerance; // maximum distance finger can move while considering it a tap
UInt16 dragTolerance;
bool calibrateMode; // if the pad is to write calibration properties out
} PADPREFS;
typedef struct paddata{
SInt16 x,y,z; // previous positions of x y z
SInt16 downX,downY,downZ; // Where the finger was last put down on the trackpad
UInt64 fingerDownTime; // time when finger was put down on track pad in ns since some time
SInt16 lastTapX,lastTapY;
UInt64 lastTapTime; // time when last tap event was registered
UInt64 lastFingerContactTime; // time when finger was last on the trackpad
UInt64 tapDragStartTime; // time when tap drag started
bool stickTapDrag; // if the pointer is currently dragging
SInt16* zArray; // array filled with data of previous z axis values used for determining two finger mode
bool zArrayFilled; // if the array is filled - wont start two finger testing until it is
int zArrayCurrent; // current position in the array
bool stickTwoFinger; // two finger mode engaged
bool buttonPressedWhileFingerOnPadDragging; // used to determine if the button should act as tho it was pressed while dragging or not
SInt16 xrem; // Variables to track remainders when scaling is on
SInt16 yrem;
SInt16 horizontalScrollingRem; // Variables to track remainders for scrolling
SInt16 verticalScrollingRem;
int scrollHotspotActive; // Hotspot that is currently active (-1 if none are)
UInt64 lastCalibrationUpdate; // last time preferences were written out
bool calibrationHasChanged; // if calibration has changed
int lastButtonState; // The bit field for the last state the button was in used when we send the finger up in the callback
int buttonStateToSend;
int clickCallbacksAwaited;
int mouseupCallbacksAwaited;
int distanceScrolled;
UInt64 lastScrollXTime;
UInt64 lastScrollYTime;
bool autoScrollXActivated;
bool autoScrollYActivated;
UInt64 scrollStrokeXStartTime;
UInt64 scrollStrokeYStartTime;
UInt64 scrollStrokeXLastUpdateTime;
UInt64 scrollStrokeYLastUpdateTime;
SInt16 scrollStrokeXStartPos;
SInt16 scrollStrokeYStartPos;
} PADDATA;
class FFScroll : public AppleADBMouse
{
OSDeclareDefaultStructors(FFScroll);
private:
bool Clicking, Dragging, DragLock, typeTrackpad;
bool _jitterclick, _jittermove;
bool _palmnomove, _palmnoaction, _2fingernoaction, _sticky2finger, _zonenomove,
_zonenoaction, _zonepecknomove, _ignorezone, _isWEnhanced, _usePantherSettings;
UInt8 _WThreshold;
UInt16 _jitterdelta;
UInt32 _ignoreTrackpadState, _oldButtonState;
UInt64 _jitterclicktime64, _zonepeckingtime64, _timeoutSticky64, _sticky2fingerTime64,
_fake5min;
AbsoluteTime _jitterclicktimeAB, _zonepeckingtimeAB, _timeoutStickyAB, _sticky2fingerTimeAB,
_fake5minAB, _keyboardTimeAB;
// Stuff added for FFScroll
bool _isAbsolute;
PADDATA _trackpaddata; // struct to store all the data about usage of the pad
PADPREFS _trackpadprefs; // struct to store user preferences about the pad
IOTimerEventSource* timeout; // timer used to send mouse up
IOTimerEventSource* clickTimer; // timer used to send mouse down
virtual void doScrolling(SInt16 dx,SInt16 dy, AbsoluteTime now); // procedure to handle 2 finger scrolling
virtual bool enableABS(); // function to enable abs mode
void packetABS(UInt8 adbCommand, IOByteCount length, UInt8* data); // procedure to handle packets in absolute mode
void trackpadClick(int x,int y,AbsoluteTime now); // procedure that determines how a tap on the trackpad is interpreted based on location
void generateAbsoluteHotspots();
void updateHotspot(COORD *coordRaw, COORD *coordAbs, int coordType, char* kind);
bool FFScroll::addTimers();
void FFScroll::setupDataAndPrefs();
void FFScroll::hotspotScrolling(int dx,int dy, AbsoluteTime now,UInt64 nowNs);
void FFScroll::proportionalAutoScrolling(AbsoluteTime now, UInt64 nowNs); // new Scrolling mode that makes it autoscrolling depending on how far you are from the center
int FFScroll::autoScrolling(AbsoluteTime now, UInt64 nowNs,int direction); //
int FFScroll::velocityAutoScrolling(AbsoluteTime now, UInt64 nowNs, int direction); // direction 1=x,2=y,3=both
// End Stuff
virtual IOReturn setParamProperties( OSDictionary * dict );
bool enableEnhancedMode();
IOService *_pADBKeyboard;
IONotifier * _notifierA, * _notifierT;
const OSSymbol *_gettime;
IOLock * _mouseLock;
OSSet * _externalMice;
protected:
UInt32 deviceSignature;
UInt16 deviceResolution;
UInt8 deviceClass;
UInt8 deviceNumButtons;
public:
// Stuff added for FFScroll
void sendClickNow();
static void FFScroll::sendClick(OSObject* trackpad,IOTimerEventSource *sender);
static void sendClickUp(OSObject*,IOTimerEventSource*);
void sendClickUpIfNotDragging();
virtual void stop(IOService*); //used to clean out the timers
//End Stuff
virtual IOService * probe(IOService * provider, SInt32 * score);
virtual bool start(IOService * provider);
virtual void packet(UInt8 adbCommand, IOByteCount length, UInt8 * data);
virtual void packetW(UInt8 adbCommand, IOByteCount length, UInt8 * data);
virtual void packetWP(UInt8 adbCommand, IOByteCount length, UInt8 * data);
virtual OSData * copyAccelerationTable();
virtual void _check_usb_mouse(IOService * service, bool added);
virtual void free();
};