1/*
2 * Copyright (c) 1998-2009 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
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 * Copyright (c) 1998 Apple Computer, Inc.  All rights reserved.
25 *
26 * HISTORY
27 *
28 */
29
30#include <unistd.h>
31#include <sys/types.h>
32#include <CoreFoundation/CoreFoundation.h>
33#include <libkern/OSByteOrder.h>
34#include <bootstrap_priv.h>
35#include <mach/mach.h>
36
37
38#include <IOKit/IOKitLib.h>
39#include <IOKit/hidsystem/IOHIDLib.h>
40#include <IOKit/hid/IOHIDLibPrivate.h>
41#include <IOKit/pwr_mgt/IOPMLibPrivate.h>
42#include <servers/bootstrap.h>
43#include "powermanagement.h"
44
45#if !TARGET_OS_IPHONE
46kern_return_t IOFramebufferServerStart( void );
47#endif
48
49kern_return_t
50IOHIDCreateSharedMemory( io_connect_t connect,
51	unsigned int version )
52{
53#if !TARGET_OS_IPHONE
54    IOFramebufferServerStart();
55#endif
56    uint64_t inData = version;
57    return IOConnectCallMethod( connect, 0,		// Index
58			   &inData, 1, NULL, 0,		// Input
59			   NULL, NULL, NULL, NULL);	// Output
60}
61
62kern_return_t
63IOHIDSetEventsEnable( io_connect_t connect,
64	boolean_t enable )
65{
66    uint64_t inData = enable;
67    return IOConnectCallMethod( connect, 1,		// Index
68			   &inData, 1, NULL, 0,		// Input
69			   NULL, NULL, NULL, NULL);	// Output
70}
71
72kern_return_t
73IOHIDSetCursorEnable( io_connect_t connect,
74	boolean_t enable )
75{
76    uint64_t inData = enable;
77    return IOConnectCallMethod( connect, 2,		// Index
78			   &inData, 1, NULL, 0,		// Input
79			   NULL, NULL, NULL, NULL);	// Output
80}
81
82/* DEPRECATED form of IOHIDPostEvent().
83kern_return_t
84IOHIDPostEvent( mach_port_t connect,
85                int type, IOGPoint location, NXEventData *data,
86                boolean_t setCursor, int flags, boolean_t setFlags)
87*/
88
89static bool _IOPMReportSoftwareHIDEvent(UInt32 eventType)
90{
91    mach_port_t         newConnection;
92    kern_return_t       kern_result = KERN_SUCCESS;
93    int                 allowEvent = true;
94
95    kern_result = bootstrap_look_up2(bootstrap_port,
96                                     kIOPMServerBootstrapName,
97                                     &newConnection,
98                                     0,
99                                     BOOTSTRAP_PRIVILEGED_SERVER);
100    if(KERN_SUCCESS == kern_result) {
101        io_pm_hid_event_report_activity(newConnection, eventType, &allowEvent);
102        mach_port_deallocate(mach_task_self(), newConnection);
103    }
104    return allowEvent;
105}
106
107kern_return_t
108IOHIDPostEvent( io_connect_t        connect,
109                UInt32              eventType,
110                IOGPoint            location,
111                const NXEventData * eventData,
112                UInt32              eventDataVersion,
113                IOOptionBits        eventFlags,
114                IOOptionBits        options )
115{
116    int *               eventPid = 0;
117    size_t              dataSize = sizeof(struct evioLLEvent) + sizeof(int);
118    char                data[dataSize];
119    struct evioLLEvent* event;
120    UInt32              eventDataSize = sizeof(NXEventData);
121    int                 allowEvent = true;
122
123    bzero(data, dataSize);
124
125    event = (struct evioLLEvent*)data;
126
127    event->type      = eventType;
128    event->location  = location;
129    event->flags     = eventFlags;
130    event->setFlags  = options;
131    event->setCursor = options & (kIOHIDSetCursorPosition | kIOHIDSetRelativeCursorPosition);
132
133    eventPid = (int *)(event + 1);
134    *eventPid = getpid();
135
136    if ( eventDataVersion < 2 )
137    {
138        // Support calls from legacy IOHIDPostEvent clients.
139        // 1. NXEventData was 32 bytes long.
140        // 2. eventDataVersion was (boolean_t) setCursor
141        eventDataSize   = 32;
142        event->setCursor = eventDataVersion; // 0 or 1
143    }
144
145    if ( eventDataSize < sizeof(event->data) )
146    {
147        bcopy( eventData, &(event->data), eventDataSize );
148        bzero( ((UInt8 *)(&(event->data))) + eventDataSize,
149               sizeof(event->data) - eventDataSize );
150    }
151    else
152        bcopy( eventData, &event->data, sizeof(event->data) );
153
154
155    // Let PM log the software HID events
156    // also checks if NULL events are allowed in the current system state
157    allowEvent  = _IOPMReportSoftwareHIDEvent(event->type);
158
159    if (allowEvent) {
160        return IOConnectCallMethod(connect, 3,		// Index
161                   NULL, 0,    data, dataSize,	// Input
162                   NULL, NULL, NULL, NULL);	// Output
163    }
164    else {
165        return KERN_SUCCESS;
166    }
167}
168
169extern kern_return_t
170IOHIDSetCursorBounds( io_connect_t connect, const IOGBounds * bounds )
171{
172	if ( !bounds )
173		return kIOReturnBadArgument;
174
175	return IOConnectCallMethod(connect, 6,			// Index
176			NULL, 0,    bounds, sizeof(*bounds),	// Input,
177			NULL, NULL, NULL,   NULL);				// Output
178}
179
180kern_return_t
181IOHIDSetMouseLocation( io_connect_t connect, int x, int y )
182{
183    return IOHIDSetFixedMouseLocation(connect, x << 8, y << 8);
184}
185
186kern_return_t
187IOHIDSetFixedMouseLocation( io_connect_t connect, int32_t x, int32_t y )
188{
189    int32_t     data[3] = {x, y, 0};
190
191    data[2] = getpid();
192
193    return IOConnectCallMethod(connect, 4,                      // Index
194                               NULL, 0,    data, sizeof(data),  // Input
195                               NULL, NULL, NULL, NULL);         // Output
196}
197
198kern_return_t
199IOHIDGetButtonEventNum( io_connect_t connect,
200	NXMouseButton button, int * eventNum )
201{
202    kern_return_t	err;
203
204	uint64_t inData = button;
205	uint64_t outData;
206	uint32_t outSize = 1;
207	err = IOConnectCallMethod(connect, 5,						// Index
208						  &inData, 1, NULL, 0,				// Input
209						  &outData, &outSize, NULL, NULL);	// Output
210	*eventNum = (int) outData;
211    return( err);
212}
213
214kern_return_t
215IOHIDGetStateForSelector( io_connect_t handle, int selector, UInt32 *state )
216{
217    kern_return_t err;
218    uint64_t        inData[1] = {selector};
219    uint64_t        outData[1] = {0};
220    uint32_t        outCount = 1;
221    err = IOConnectCallMethod(handle, 5,      // Index
222                              inData, 1, NULL, 0,    // Input
223                              outData, &outCount, NULL, NULL); // Output
224
225    *state = outData[0];
226    return err;
227}
228
229kern_return_t
230IOHIDSetStateForSelector( io_connect_t handle, int selector, UInt32 state )
231{
232    kern_return_t err;
233    uint64_t        inData[2] = {selector, state};
234    uint32_t        outCount = 0;
235
236    err = IOConnectCallMethod(handle, 6,      // Index
237                              inData, 2, NULL, 0,    // Input
238                              NULL, &outCount, NULL, NULL); // Output
239
240    return err;
241}
242
243kern_return_t
244IOHIDGetModifierLockState( io_connect_t handle, int selector, bool *state )
245{
246    UInt32  internalState = 0;
247    kern_return_t err = IOHIDGetStateForSelector(handle, selector, &internalState);
248    *state = internalState ? true : false;
249    return err;
250}
251
252kern_return_t
253IOHIDSetModifierLockState( io_connect_t handle, int selector, bool state )
254{
255    return IOHIDSetStateForSelector(handle, selector, state);
256}
257
258kern_return_t
259IOHIDRegisterVirtualDisplay( io_connect_t handle, UInt32 *display_token )
260{
261    kern_return_t err;
262    uint64_t        outData[1] = {0};
263    uint32_t        outCount = 1;
264
265    err = IOConnectCallMethod(handle, 7,      // Index
266                              NULL, 0, NULL, 0,    // Input
267                              outData, &outCount, NULL, NULL); // Output
268    *display_token = outData[0];
269    return err;
270}
271
272kern_return_t
273IOHIDUnregisterVirtualDisplay( io_connect_t handle, UInt32 display_token )
274{
275    kern_return_t err;
276    uint64_t        inData[1] = {display_token};
277    uint32_t        outCount = 0;
278
279    err = IOConnectCallMethod(handle, 8,      // Index
280                              inData, 1, NULL, 0,    // Input
281                              NULL, &outCount, NULL, NULL); // Output
282
283    return err;
284}
285
286kern_return_t
287IOHIDSetVirtualDisplayBounds( io_connect_t handle, UInt32 display_token, const IOGBounds * bounds )
288{
289    kern_return_t err;
290    uint64_t        inData[5] = {display_token, bounds->minx, bounds->maxx, bounds->miny, bounds->maxy};
291    uint32_t        outCount = 0;
292
293    err = IOConnectCallMethod(handle, 9,      // Index
294                              inData, 5, NULL, 0,    // Input
295                              NULL, &outCount, NULL, NULL); // Output
296
297    return err;
298}
299
300kern_return_t
301IOHIDGetActivityState( io_connect_t handle, bool *hidActivityIdle )
302{
303    kern_return_t err;
304    uint64_t        outData[1] = {0};
305    uint32_t        outCount = 1;
306
307    if (!hidActivityIdle) return kIOReturnBadArgument;
308
309    err = IOConnectCallMethod(handle, 10,      // Index
310                              NULL, 0, NULL, 0,    // Input
311                              outData, &outCount, NULL, NULL); // Output
312    *hidActivityIdle = outData[0] ? true : false;
313    return err;
314
315}
316