1/*
2 * @APPLE_LICENSE_HEADER_START@
3 *
4 * Copyright (c) 2011 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#include <IOKit/IOLib.h>
25#include "IOHIDSystemCursorHelper.h"
26
27//===========================================================================
28boolean_t IOHIDSystemCursorHelper::init()
29{
30    location.fromIntFloor(0, 0);
31    locationDelta.fromIntFloor(0, 0);
32    locationDeltaPosting.fromIntFloor(0, 0);
33    locationDeltaAccumulated.fromIntFloor(0, 0);
34    screenLocation.fromIntFloor(0, 0);
35    expectedCountValue.fromIntFloor(0);
36    eventCount = 0;
37    eventCountPosting = 0;
38
39    return true;
40}
41
42//===========================================================================
43void IOHIDSystemCursorHelper::startPosting()
44{
45    locationDeltaPosting = locationDeltaAccumulated;
46    locationDeltaAccumulated.fromIntFloor(0, 0);
47    eventCountPosting = eventCount;
48    eventCount = 0;
49}
50
51//===========================================================================
52void IOHIDSystemCursorHelper::updateScreenLocation(IOGBounds *desktop,
53                                                   IOGBounds *screen)
54{
55    if (!desktop || !screen) {
56        // no transform can be performed
57        screenLocation = location;
58    }
59    else {
60        if (*(UInt64*)desktop == *(UInt64*)screen) {
61            //  no transform needed
62            screenLocation = location;
63        }
64        else {
65            int screenWidth   = screen->maxx  - screen->minx;
66            int screenHeight  = screen->maxy  - screen->miny;
67            int desktopWidth  = desktop->maxx - desktop->minx;
68            int desktopHeight = desktop->maxy - desktop->miny;
69            IOFixedPoint64 scratch;
70            if ((screenWidth <= 0) || (screenHeight <= 0) || (desktopWidth <= 0) || (desktopHeight <= 0)) {
71                // no transform can be performed
72            }
73            else {
74                if ((screenWidth == desktopWidth) && (screenHeight == desktopHeight)) {
75                    // translation only
76                    screenLocation = location;
77                    screenLocation += scratch.fromIntFloor(screen->minx - desktop->minx,
78                                                           screen->miny - desktop->miny);
79                }
80                else {
81                    // full transform
82                    IOFixed64 x_scale;
83                    IOFixed64 y_scale;
84                    x_scale.fromIntFloor(screenWidth) /= desktopWidth;
85                    y_scale.fromIntFloor(screenHeight) /= desktopHeight;
86                    screenLocation = location;
87                    screenLocation -= scratch.fromIntFloor(desktop->minx, desktop->miny);
88                    screenLocation *= scratch.fromFixed64(x_scale, y_scale);
89                    screenLocation += scratch.fromIntFloor(screen->minx, screen->miny);
90                }
91            }
92        }
93    }
94}
95
96//===========================================================================
97void IOHIDSystemCursorHelper::applyPostingDelta()
98{
99    if (eventCountPosting && expectedCountValue) {
100        // unless the eventCountPosting is within the expectedCount ± 1, this adjustment
101        // will cause more harm than good.
102        if ((expectedCountValue <= eventCountPosting + 1LL) &&
103            (expectedCountValue >= eventCountPosting - 1LL)) {
104            locationDeltaPosting *= expectedCountValue;
105            locationDeltaPosting /= eventCountPosting;
106        }
107    }
108    eventCountPosting = 0;
109    location += locationDeltaPosting;
110    locationDelta += locationDeltaPosting;
111    locationDeltaPosting.fromIntFloor(0, 0);
112}
113
114
115//===========================================================================
116bool IOHIDSystemCursorHelper::isPosting()
117{
118    bool result = false;
119    if (locationDeltaPosting) {
120        result = true;
121    }
122    return result;
123}
124
125//===========================================================================
126void IOHIDSystemCursorHelper::logPosition(const char *name, uint64_t ts)
127{
128    IOLog("IOHIDSystem::%-20s cursor @ %lld: "
129          "(%4lld.%02lld, %4lld.%02lld) "
130          "[%+3lld.%02lld, %+3lld.%02lld] "
131          "P[%+3lld.%02lld, %+3lld.%02lld] "
132          "A[%+3lld.%02lld, %+3lld.%02lld] "
133          "S(%4lld.%02lld, %4lld.%02lld) "
134          "C %ld/%ld of %lld.%01lld\n",
135          name, ts,
136          location.xValue().as64(), (location.xValue().asFixed64() & 0xffff) / 656,
137          location.yValue().as64(), (location.yValue().asFixed64() & 0xffff) / 656,
138          locationDelta.xValue().as64(), (locationDelta.xValue().asFixed64() & 0xffff) / 656,
139          locationDelta.yValue().as64(), (locationDelta.yValue().asFixed64() & 0xffff) / 656,
140          locationDeltaPosting.xValue().as64(), (locationDeltaPosting.xValue().asFixed64() & 0xffff) / 656,
141          locationDeltaPosting.yValue().as64(), (locationDeltaPosting.yValue().asFixed64() & 0xffff) / 656,
142          locationDeltaAccumulated.xValue().as64(), (locationDeltaAccumulated.xValue().asFixed64() & 0xffff) / 656,
143          locationDeltaAccumulated.yValue().as64(), (locationDeltaAccumulated.yValue().asFixed64() & 0xffff) / 656,
144          screenLocation.xValue().as64(), (screenLocation.xValue().asFixed64() & 0xffff) / 656,
145          screenLocation.yValue().as64(), (screenLocation.yValue().asFixed64() & 0xffff) / 656,
146          (long int)eventCount,
147          (long int)eventCountPosting,
148          expectedCountValue.as64(), (expectedCountValue.asFixed64() & 0xffff) / 6554
149          );
150}
151
152//===========================================================================
153void IOHIDSystemCursorHelper::klogPosition(const char *name, uint64_t ts)
154{
155    kprintf("IOHIDSystem::%-20s cursor @ %lld: "
156            "(%016llx, %016llx) "
157            "[%016llx, %016llx] "
158            "P[%016llx, %016llx] "
159            "A[%016llx, %016llx] "
160            "S(%016llx, %016llx) "
161            "C %ld/%ld of %016llx\n",
162            name, ts,
163            location.xValue().asFixed64(),
164            location.yValue().asFixed64(),
165            locationDelta.xValue().asFixed64(),
166            locationDelta.yValue().asFixed64(),
167            locationDeltaPosting.xValue().asFixed64(),
168            locationDeltaPosting.yValue().asFixed64(),
169            locationDeltaAccumulated.xValue().asFixed64(),
170            locationDeltaAccumulated.yValue().asFixed64(),
171            screenLocation.xValue().asFixed64(),
172            screenLocation.yValue().asFixed64(),
173            (long int)eventCount,
174            (long int)eventCountPosting,
175            expectedCountValue.asFixed64()
176            );
177}
178
179//===========================================================================
180