1/*
2 *
3 * @APPLE_LICENSE_HEADER_START@
4 *
5 * Copyright (c) 1999-2013 Apple Computer, Inc.  All Rights Reserved.
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#include "IOHIDEventOverrideDriver.h"
26#include "IOHIDUsageTables.h"
27
28//===========================================================================
29// IOHIDEventOverrideDriver class
30
31#define super IOHIDEventDriver
32
33OSDefineMetaClassAndStructors( IOHIDEventOverrideDriver, IOHIDEventDriver )
34
35//====================================================================================================
36// IOHIDEventOverrideDriver::dispatchKeyboardEvent
37//====================================================================================================
38bool IOHIDEventOverrideDriver::handleStart( IOService * provider )
39{
40    OSArray *   maps = NULL;
41    int         index;
42
43    if ( !super::handleStart(provider) )
44        return false;
45
46    for ( index=0; index<32; index++ ) {
47        _buttonMap[index].eventType         = kIOHIDEventTypePointer;
48        _buttonMap[index].u.pointer.mask    = (1<<index);
49    }
50
51    maps = OSDynamicCast(OSArray, getProperty("ButtonMaps"));
52    if ( maps ) {
53
54        for ( index=0; index<maps->getCount(); index++ ) {
55            OSDictionary *  map;
56            OSNumber *      number;
57            uint32_t        button;
58
59            map = OSDynamicCast(OSDictionary, maps->getObject(index));
60            if ( !map )
61                continue;
62
63            number = OSDynamicCast(OSNumber, map->getObject("ButtonNumber"));
64            if ( !number )
65                continue;
66
67            button = number->unsigned32BitValue();
68            if ( !button || button>32 )
69                continue;
70
71            number = OSDynamicCast(OSNumber, map->getObject("EventType"));
72            if ( !number )
73                continue;
74
75            _buttonMap[button-1].eventType = number->unsigned32BitValue();
76
77            switch ( _buttonMap[button-1].eventType ) {
78                case kIOHIDEventTypeKeyboard:
79                    {
80                        uint32_t usagePage, usage;
81
82                        number = OSDynamicCast(OSNumber, map->getObject("UsagePage"));
83                        if ( !number )
84                            break;
85
86                        usagePage = number->unsigned32BitValue();
87
88                        number = OSDynamicCast(OSNumber, map->getObject("Usage"));
89                        if ( !number )
90                            break;
91
92                        usage = number->unsigned32BitValue();
93
94                        _buttonMap[button-1].u.keyboard.usagePage  = usagePage;
95                        _buttonMap[button-1].u.keyboard.usage      = usage;
96
97                    }
98                    break;
99                case kIOHIDEventTypePointer:
100                    {
101                        uint32_t mask;
102
103                        number = OSDynamicCast(OSNumber, map->getObject("Mask"));
104                        if ( !number )
105                            break;
106
107                        mask = number->unsigned32BitValue();
108
109
110                        _buttonMap[button-1].u.pointer.mask = mask;
111                    }
112                    break;
113                default:
114                    break;
115            }
116
117        }
118    }
119
120    return true;
121}
122
123//====================================================================================================
124// IOHIDEventOverrideDriver::dispatchEvent
125//====================================================================================================
126void IOHIDEventOverrideDriver::dispatchEvent(IOHIDEvent * event, IOOptionBits options)
127{
128    IOHIDEvent * targetEvent = NULL;
129
130    if ( (targetEvent = event->getEvent(kIOHIDEventTypePointer)) ) {
131
132        IOHIDEvent *    newEvent                        = NULL;
133        AbsoluteTime    timestamp                       = targetEvent->getTimeStamp();
134        uint32_t        rawPointerButtonMask            = targetEvent->getIntegerValue(kIOHIDEventFieldPointerButtonMask);
135        uint32_t        rawPointerButtonMaskDelta       = _rawPointerButtonMask ^ rawPointerButtonMask;
136        uint32_t        resultantPointerButtonMask      = _resultantPointerButtonMask;
137        int             index;
138
139        for ( index=0; index<32; index++ ) {
140
141            bool value = rawPointerButtonMask & (1<<index);
142
143            if ( (rawPointerButtonMaskDelta & (1<<index)) == 0 )
144                continue;
145
146            switch (_buttonMap[index].eventType ) {
147                case kIOHIDEventTypeKeyboard:
148                    dispatchKeyboardEvent(timestamp, _buttonMap[index].u.keyboard.usagePage, _buttonMap[index].u.keyboard.usage, value);
149                    break;
150                case kIOHIDEventTypePointer:
151                    if ( value )
152                        resultantPointerButtonMask |= _buttonMap[index].u.pointer.mask;
153                    else
154                        resultantPointerButtonMask &= ~_buttonMap[index].u.pointer.mask;
155                    break;
156                default:
157                    break;
158            }
159        }
160
161        _rawPointerButtonMask = rawPointerButtonMask;
162
163        newEvent = IOHIDEvent::relativePointerEvent(timestamp, event->getIntegerValue(kIOHIDEventFieldPointerX), event->getIntegerValue(kIOHIDEventFieldPointerY), event->getIntegerValue(kIOHIDEventFieldPointerZ), resultantPointerButtonMask, _resultantPointerButtonMask);
164        if ( newEvent ) {
165            super::dispatchEvent(newEvent);
166            newEvent->release();
167        }
168
169        _resultantPointerButtonMask = resultantPointerButtonMask;
170
171    } else {
172        super::dispatchEvent(event, options);
173    }
174}
175
176