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
42    if ( !super::handleStart(provider) )
43        return false;
44
45    maps = OSDynamicCast(OSArray, getProperty("ButtonMaps"));
46    if ( maps ) {
47        int index;
48
49        for ( index=0; index<maps->getCount(); index++ ) {
50            OSDictionary *  map;
51            OSNumber *      number;
52            uint32_t        button;
53            uint32_t        usagePage;
54            uint32_t        usage;
55            uint32_t        eventType;
56
57            map = OSDynamicCast(OSDictionary, maps->getObject(index));
58            if ( !map )
59                continue;
60
61            number = OSDynamicCast(OSNumber, map->getObject("ButtonNumber"));
62            if ( !number )
63                continue;
64
65            button = number->unsigned32BitValue();
66            if ( !button || button>32 )
67                continue;
68
69            number = OSDynamicCast(OSNumber, map->getObject("EventType"));
70            if ( !number )
71                continue;
72
73            eventType = number->unsigned32BitValue();
74
75            number = OSDynamicCast(OSNumber, map->getObject("UsagePage"));
76            if ( !number )
77                continue;
78
79            usagePage = number->unsigned32BitValue();
80
81            number = OSDynamicCast(OSNumber, map->getObject("Usage"));
82            if ( !number )
83                continue;
84
85            usage = number->unsigned32BitValue();
86
87            _buttonMap[button-1].eventType  = eventType;
88            _buttonMap[button-1].usagePage  = usagePage;
89            _buttonMap[button-1].usage      = usage;
90        }
91    }
92
93    return true;
94}
95
96//====================================================================================================
97// IOHIDEventOverrideDriver::dispatchKeyboardEvent
98//====================================================================================================
99void IOHIDEventOverrideDriver::dispatchEvent(IOHIDEvent * event, IOOptionBits options)
100{
101    IOHIDEvent * targetEvent = NULL;
102    if ( (targetEvent = event->getEvent(kIOHIDEventTypePointer)) ) {
103        AbsoluteTime    timestamp               = targetEvent->getTimeStamp();
104        uint32_t        pointerButtonMaskNew    = targetEvent->getIntegerValue(kIOHIDEventFieldPointerButtonMask);
105        uint32_t        pointerButtonMaskDelta  = _pointerButtonMask ^ pointerButtonMaskNew;
106        int             index;
107
108        for ( index=0; index<32; index++ ) {
109            bool value;
110            if ( (pointerButtonMaskDelta & (1<<index)) == 0 )
111                continue;
112
113            switch (_buttonMap[index].eventType ) {
114                case kIOHIDEventTypeKeyboard:
115                    value = pointerButtonMaskNew & (1<<index);
116                    dispatchKeyboardEvent(timestamp, _buttonMap[index].usagePage, _buttonMap[index].usage, value);
117                    break;
118                default:
119                    break;
120            }
121        }
122
123        _pointerButtonMask = pointerButtonMaskNew;
124    } else {
125        super::dispatchEvent(event, options);
126    }
127}
128
129