1/*
2 * @APPLE_LICENSE_HEADER_START@
3 *
4 * Copyright (c) 1999-2009 Apple Computer, Inc.  All Rights Reserved.
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24 * 07 Jan 2002 		ryepez
25 *			This class is based off IOHIPointing and handles
26 *			USB HID report based pointing devices
27 */
28
29#include <IOKit/IOLib.h>
30#include <IOKit/assert.h>
31#include <IOKit/hidsystem/IOHIDShared.h>
32#include <IOKit/hidsystem/IOHIDDescriptorParser.h>
33
34#include "IOHIDParameter.h"
35#include "IOHIDPointing.h"
36#include "IOHIDKeys.h"
37#include "IOHIDElement.h"
38
39#define super IOHITablet
40OSDefineMetaClassAndStructors(IOHIDPointing, IOHITablet);
41
42//====================================================================================================
43// IOHIDPointing::Pointing
44//====================================================================================================
45IOHIDPointing * IOHIDPointing::Pointing(
46                                UInt32          buttonCount,
47                                IOFixed         pointerResolution,
48                                IOFixed         scrollResolution,
49                                bool            isDispatcher)
50{
51    IOHIDPointing 	*nub 			= new IOHIDPointing;
52
53    if ((nub == 0) || !nub->initWithMouseProperties(buttonCount, pointerResolution, scrollResolution, isDispatcher) )
54    {
55        if (nub) nub->release();
56        return 0;
57    }
58
59    return nub;
60}
61
62
63//====================================================================================================
64// IOHIDPointing::initWithMouseProperties
65//====================================================================================================
66bool IOHIDPointing::initWithMouseProperties(
67                                UInt32          buttonCnt,
68                                IOFixed         pointerResolution,
69                                IOFixed         scrollResolution,
70                                bool            isDispatcher)
71{
72    if (!super::init(0))  return false;
73
74    _numButtons         = (buttonCnt > 0) ? buttonCnt : 1;
75    _resolution         = pointerResolution;
76    _scrollResolution   = scrollResolution;
77    _isDispatcher       = isDispatcher;
78
79    return true;
80}
81
82//====================================================================================================
83// IOHIDPointing::start
84//====================================================================================================
85bool IOHIDPointing::start(IOService *provider)
86{
87
88	_provider = OSDynamicCast(IOHIDEventService, provider);
89
90	if (!_provider)
91		return false;
92
93    // push up properties from our provider
94    setupProperties();
95
96    return super::start(provider);
97}
98
99//====================================================================================================
100// IOHIDPointing::dispatchAbsolutePointerEvent
101//====================================================================================================
102void IOHIDPointing::dispatchAbsolutePointerEvent(
103                                AbsoluteTime                timeStamp,
104                                IOGPoint *                  newLoc,
105                                IOGBounds *                 bounds,
106                                UInt32                      buttonState,
107                                bool                        inRange,
108                                SInt32                      tipPressure,
109                                SInt32                      tipPressureMin,
110                                SInt32                      tipPressureMax,
111                                IOOptionBits                options)
112{
113    bool    convertToRelative   = ((options & kHIDDispatchOptionPointerAbsolutToRelative) != 0);
114    bool    accelerate          = ((options & kHIDDispatchOptionPointerNoAcceleration) == 0);
115    UInt32  pointingMode        = getPointingMode();
116
117    if ( (((pointingMode & kAccelMouse) != 0) != accelerate) && (((pointingMode & kAbsoluteConvertMouse) != 0) != convertToRelative))
118    {
119        if ( accelerate )
120            pointingMode |= kAccelMouse;
121        else
122            pointingMode &= ~kAccelMouse;
123
124        if ( convertToRelative )
125            pointingMode |= kAbsoluteConvertMouse;
126        else
127            pointingMode &= ~kAbsoluteConvertMouse;
128
129        setPointingMode(pointingMode);
130    }
131
132	super::dispatchAbsolutePointerEvent(newLoc, bounds, buttonState, inRange, tipPressure, tipPressureMin, tipPressureMax, 90, timeStamp);
133}
134
135//====================================================================================================
136// IOHIDPointing::dispatchRelativePointerEvent
137//====================================================================================================
138void IOHIDPointing::dispatchRelativePointerEvent(
139                                AbsoluteTime                timeStamp,
140                                SInt32                      dx,
141                                SInt32                      dy,
142                                UInt32                      buttonState,
143                                IOOptionBits                options)
144{
145    bool    accelerate      = ((options & kHIDDispatchOptionPointerNoAcceleration) == 0);
146    UInt32  pointingMode    = getPointingMode();
147
148    if ( ((pointingMode & kAccelMouse) != 0) != accelerate)
149    {
150        if ( accelerate )
151            pointingMode |= kAccelMouse;
152        else
153            pointingMode &= ~kAccelMouse;
154
155        setPointingMode(pointingMode);
156    }
157
158	super::dispatchRelativePointerEvent(dx, dy, buttonState, timeStamp);
159}
160
161//====================================================================================================
162// IOHIDPointing::dispatchScrollWheelEvent
163//====================================================================================================
164void IOHIDPointing::dispatchScrollWheelEvent(
165                                AbsoluteTime                timeStamp,
166                                SInt32                      deltaAxis1,
167                                SInt32                      deltaAxis2,
168                                UInt32                      deltaAxis3,
169                                IOOptionBits                options)
170{
171    // no good initial check
172    {
173        UInt32  oldEventType    = getScrollType();
174        UInt32  newEventType    = oldEventType & ~( kScrollTypeMomentumAny | kScrollTypeOptionPhaseAny );
175        bool    setScroll       = false;
176
177        UInt32 dispatchKey = kHIDDispatchOptionScrollMomentumContinue;
178        UInt32 eventKey    = kScrollTypeMomentumContinue;
179        bool   dispatchVal = options & dispatchKey ? true : false;
180        bool   eventVal    = oldEventType & eventKey ? true : false;
181        if (dispatchVal != eventVal) {
182            if (dispatchVal) {
183                newEventType |= eventKey;
184            }
185            setScroll = true;
186        }
187
188        dispatchKey = kHIDDispatchOptionScrollMomentumStart;
189        eventKey    = kScrollTypeMomentumStart;
190        dispatchVal = options & dispatchKey ? true : false;
191        eventVal    = oldEventType & eventKey ? true : false;
192        if (dispatchVal != eventVal) {
193            if (dispatchVal) {
194                newEventType |= eventKey;
195            }
196            setScroll = true;
197        }
198
199        dispatchKey = kHIDDispatchOptionScrollMomentumEnd;
200        eventKey    = kScrollTypeMomentumEnd;
201        dispatchVal = options & dispatchKey ? true : false;
202        eventVal    = oldEventType & eventKey ? true : false;
203        if (dispatchVal != eventVal) {
204            if (dispatchVal) {
205                newEventType |= eventKey;
206            }
207            setScroll = true;
208        }
209
210        // Slight idiom change here because kHIDDispatchOptionPhaseAny << 4 == kScrollTypeOptionPhaseAny
211        dispatchKey = (options & kHIDDispatchOptionPhaseAny) << 4;
212        eventKey    = (oldEventType & kScrollTypeOptionPhaseAny);
213        if (dispatchKey != eventKey) {
214            newEventType |= dispatchKey;
215            setScroll = true;
216        }
217
218        if (setScroll) {
219            setScrollType(newEventType);
220        }
221    }
222
223    // rdar://13002702
224    bool    accelerate      = ((options & kHIDDispatchOptionScrollNoAcceleration) == 0) && ((options & kHIDDispatchOptionPhaseEnded) == 0);
225    UInt32  pointingMode    = getPointingMode();
226
227    if (((pointingMode & kAccelScroll) != 0) != accelerate)
228    {
229        if ( accelerate )
230            pointingMode |= kAccelScroll;
231        else
232            pointingMode &= ~kAccelScroll;
233
234        setPointingMode(pointingMode);
235    }
236
237	super::dispatchScrollWheelEvent(deltaAxis1, deltaAxis2, deltaAxis3, timeStamp);
238}
239
240//====================================================================================================
241// IOHIDPointing::generateDeviceID
242//====================================================================================================
243UInt16 IOHIDPointing::generateDeviceID()
244{
245    static UInt16 sNextDeviceID = 0x8000;
246    return sNextDeviceID++;
247}
248
249//====================================================================================================
250// IOHIDPointing::dispatchTabletPointEvent
251//====================================================================================================
252void IOHIDPointing::dispatchTabletEvent(
253                                    NXEventData *           tabletEvent,
254                                    AbsoluteTime            ts)
255{
256    super::dispatchTabletEvent(tabletEvent, ts);
257}
258
259//====================================================================================================
260// IOHIDPointing::dispatchTabletProximityEvent
261//====================================================================================================
262void IOHIDPointing::dispatchProximityEvent(
263                                    NXEventData *           proximityEvent,
264                                    AbsoluteTime            ts)
265{
266    super::dispatchProximityEvent(proximityEvent, ts);
267}
268
269
270// subclasses override
271
272//====================================================================================================
273// IOHIDPointing::buttonCount
274//====================================================================================================
275IOItemCount IOHIDPointing::buttonCount()
276{
277    return _numButtons;
278}
279
280//====================================================================================================
281// IOHIDPointing::resolution
282//====================================================================================================
283IOFixed IOHIDPointing::resolution()
284{
285    return _resolution;
286}
287
288
289//====================================================================================================
290// IOHIDPointing::setupProperties
291//====================================================================================================
292void IOHIDPointing::setupProperties()
293{
294    OSNumber *  number  = NULL;
295
296	// Store the resolution
297	number = (OSNumber*)_provider->copyProperty(kIOHIDPointerResolutionKey);
298    if ( OSDynamicCast(OSNumber, number) )
299    {
300        IOFixed newResolution = number->unsigned32BitValue();
301        if ( newResolution != 0 ) {
302            _resolution = number->unsigned32BitValue();
303            setProperty(kIOHIDPointerResolutionKey, number);
304            _isDispatcher = FALSE;
305        }
306    }
307    else if ( _resolution )
308    {
309        setProperty(kIOHIDPointerResolutionKey, _resolution, 32);
310    }
311    OSSafeReleaseNULL(number);
312
313	// Store the scroll resolution
314	number = (OSNumber*)_provider->copyProperty(kIOHIDScrollResolutionKey);
315    if ( OSDynamicCast(OSNumber, number) )
316    {
317        _scrollResolution = number->unsigned32BitValue();
318        setProperty(kIOHIDScrollResolutionKey, number);
319		_isDispatcher = FALSE;
320    }
321    else if ( _scrollResolution )
322    {
323        setProperty(kIOHIDScrollResolutionKey, _scrollResolution, 32);
324    }
325    OSSafeReleaseNULL(number);
326
327	// deal with buttons
328	if ( (_numButtons == 1) &&
329	     (NULL != (number = (OSNumber*)_provider->copyProperty(kIOHIDPointerButtonCountKey))) &&
330	     OSDynamicCast(OSNumber, number) )
331	{
332		_numButtons = number->unsigned32BitValue();
333		_isDispatcher = FALSE;
334	}
335    OSSafeReleaseNULL(number);
336
337    if ( _isDispatcher )
338        setProperty(kIOHIDVirtualHIDevice, kOSBooleanTrue);
339
340    // vtn3: These unsafe, but unlikely to cause a problem. Additionally, making it "safe" is going to be cumbersome and irritating.
341    setProperty(kIOHIDScrollAccelerationTypeKey, _provider->getProperty( kIOHIDScrollAccelerationTypeKey ));
342    setProperty(kIOHIDPointerAccelerationTypeKey, _provider->getProperty( kIOHIDPointerAccelerationTypeKey ));
343
344    setProperty(kIOHIDPointerAccelerationTableKey, _provider->getProperty( kIOHIDPointerAccelerationTableKey ));
345    setProperty(kIOHIDScrollAccelerationTableKey, _provider->getProperty( kIOHIDScrollAccelerationTableKey ));
346    setProperty(kIOHIDScrollAccelerationTableXKey, _provider->getProperty( kIOHIDScrollAccelerationTableXKey ));
347    setProperty(kIOHIDScrollAccelerationTableYKey, _provider->getProperty( kIOHIDScrollAccelerationTableYKey ));
348    setProperty(kIOHIDScrollAccelerationTableZKey, _provider->getProperty( kIOHIDScrollAccelerationTableZKey ));
349
350    setProperty(kIOHIDScrollReportRateKey, _provider->getProperty( kIOHIDScrollReportRateKey ));
351
352    setProperty( kIOHIDScrollMouseButtonKey, _provider->getProperty( kIOHIDScrollMouseButtonKey ));
353
354    setProperty(kIOHIDScrollResolutionXKey, _provider->getProperty( kIOHIDScrollResolutionXKey ));
355    setProperty(kIOHIDScrollResolutionYKey, _provider->getProperty( kIOHIDScrollResolutionYKey ));
356    setProperty(kIOHIDScrollResolutionZKey, _provider->getProperty( kIOHIDScrollResolutionZKey ));
357}
358