2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
24 * EventDriver.m - Event System module, ObjC implementation.
26 * The EventDriver is a pseudo-device driver.
29 * 31-Mar-92 Mike Paquette at NeXT
31 * 04-Aug-93 Erik Kay at NeXT
33 * 12-Dec-00 bubba at Apple.
34 * Handle eject key cases on Pro Keyboard.
37 #include <IOKit/system.h>
38 #include <IOKit/assert.h>
40 #include <libkern/c++/OSContainers.h>
41 #include <libkern/c++/OSCollectionIterator.h>
43 #include <IOKit/IOTimerEventSource.h>
44 #include <IOKit/IOCommandQueue.h>
45 #include <IOKit/IOMessage.h>
46 #include <IOKit/IOWorkLoop.h>
47 #include <IOKit/hidsystem/IOHIDevice.h>
48 #include <IOKit/hidsystem/IOHIDShared.h>
49 #include <IOKit/hidsystem/IOHIDSystem.h>
50 #include <IOKit/hidsystem/IOHIKeyboard.h>
51 #include <IOKit/hidsystem/IOHIPointing.h>
52 #include <IOKit/hidsystem/IOHIDParameter.h>
54 #include <IOKit/hidsystem/ev_private.h> /* Per-machine configuration info */
55 #include "IOHIDUserClient.h"
57 #include <sys/kdebug.h>
62 #include <UserNotification/KUNCUserNotifications.h>
66 bool displayWranglerUp( OSObject
*, void *, IOService
* );
68 static IOHIDSystem
* evInstance
= 0;
69 MasterAudioFunctions
*masterAudioFunctions
= 0;
71 #define xpr_ev_cursor(x, a, b, c, d, e)
72 #define PtInRect(ptp,rp) \
73 ((ptp)->x >= (rp)->minx && (ptp)->x < (rp)->maxx && \
74 (ptp)->y >= (rp)->miny && (ptp)->y < (rp)->maxy)
78 static inline unsigned AbsoluteTimeToTick( AbsoluteTime
* ts
)
81 absolutetime_to_nanoseconds(*ts
, &nano
);
85 static inline void TickToAbsoluteTime( unsigned tick
, AbsoluteTime
* ts
)
87 UInt64 nano
= ((UInt64
) tick
) << 24;
88 nanoseconds_to_absolutetime(nano
, ts
);
91 #define EV_NS_TO_TICK(ns) AbsoluteTimeToTick(ns)
92 #define EV_TICK_TO_NS(tick,ns) TickToAbsoluteTime(tick,ns)
95 #define super IOService
96 OSDefineMetaClassAndStructors(IOHIDSystem
, IOService
);
98 /* Return the current instance of the EventDriver, or 0 if none. */
99 IOHIDSystem
* IOHIDSystem::instance()
104 bool IOHIDSystem::init(OSDictionary
* properties
)
106 if (!super::init(properties
)) return false;
109 * Initialize minimal state.
113 kickConsumerLock
= NULL
;
122 IOHIDSystem
* IOHIDSystem::probe(IOService
* provider
,
125 if (!super::probe(provider
,score
)) return 0;
131 * Perform reusable initialization actions here.
133 IOWorkLoop
* IOHIDSystem::getWorkLoop() const
138 bool IOHIDSystem::start(IOService
* provider
)
140 bool iWasStarted
= false;
143 if (!super::start(provider
)) break;
147 driverLock
= IOLockAlloc(); // Event driver data protection lock
148 kickConsumerLock
= IOLockAlloc();
150 /* A few details to be set up... */
151 pointerLoc
.x
= INIT_CURSOR_X
;
152 pointerLoc
.y
= INIT_CURSOR_Y
;
157 evScreenSize
= sizeof(EvScreen
) * 6; // FIX
158 evScreen
= (void *) IOMalloc(evScreenSize
);
162 !evScreenSize
) break;
164 IOLockInit(driverLock
);
165 IOLockInit(kickConsumerLock
);
166 bzero(evScreen
, evScreenSize
);
169 * Start up the work loop
171 workLoop
= IOWorkLoop::workLoop();
172 cmdQ
= IOCommandQueue::commandQueue
173 (this, (IOCommandQueueAction
) &_doPerformInIOThread
);
174 timerES
= IOTimerEventSource::timerEventSource
175 (this, (IOTimerEventSource::Action
) &_periodicEvents
);
177 if (!workLoop
|| !cmdQ
|| !timerES
)
180 if ((workLoop
->addEventSource(cmdQ
) != kIOReturnSuccess
)
181 || (workLoop
->addEventSource(timerES
) != kIOReturnSuccess
))
184 publishNotify
= addNotification(
185 gIOPublishNotification
, serviceMatching("IOHIDevice"),
186 (IOServiceNotificationHandler
) &publishNotificationHandler
,
189 if (!publishNotify
) break;
192 * IOHIDSystem serves both as a service and a nub (we lead a double
193 * life). Register ourselves as a nub to kick off matching.
198 addNotification( gIOPublishNotification
,serviceMatching("IODisplayWrangler"), // look for the display wrangler
199 (IOServiceNotificationHandler
)displayWranglerUp
, this, 0 );
204 if (!iWasStarted
) evInstance
= 0;
209 // **********************************************************************************
212 // The Display Wrangler has appeared. We will be calling its
213 // activityTickle method when there is user activity.
214 // **********************************************************************************
215 bool displayWranglerUp( OSObject
* us
, void * ref
, IOService
* yourDevice
)
217 if ( yourDevice
!= NULL
) {
218 ((IOHIDSystem
*)us
)->displayManager
= yourDevice
;
219 ((IOHIDSystem
*)us
)->displayState
= yourDevice
->registerInterestedDriver((IOService
*)us
);
225 //*********************************************************************************
226 // powerStateDidChangeTo
228 // The display wrangler has changed state, so the displays have changed
229 // state, too. We save the new state.
230 //*********************************************************************************
232 IOReturn
IOHIDSystem::powerStateDidChangeTo ( IOPMPowerFlags theFlags
, unsigned long, IOService
*)
234 displayState
= theFlags
;
240 bool IOHIDSystem::publishNotificationHandler(
243 IOService
* newService
)
245 self
->attach( newService
);
247 // IOTakeLock( self->driverLock);
249 && OSDynamicCast(IOHIDevice
, newService
)) {
250 self
->registerEventSource((IOHIDevice
*) newService
);
252 // IOUnlock( self->driverLock);
259 * Free locally allocated resources, and then ourselves.
261 void IOHIDSystem::free()
263 /* Initiates a normal close if open & inited */
267 if (evScreen
) IOFree( (void *)evScreen
, evScreenSize
);
268 evScreen
= (void *)0;
271 if (timerES
) timerES
->release();
272 if (cmdQ
) cmdQ
->release();
273 if (workLoop
) workLoop
->release();
274 if (publishNotify
) publishNotify
->release();
276 /* Release locally allocated resources */
277 if (kickConsumerLock
) IOLockFree( kickConsumerLock
);
278 if (driverLock
) IOLockFree( driverLock
);
286 * Open the driver for business. This call must be made before
287 * any other calls to the Event driver. We can only be opened by
288 * one user at a time.
290 IOReturn
IOHIDSystem::evOpen(void)
292 IOReturn r
= kIOReturnSuccess
;
294 if ( evOpenCalled
== true )
303 evInitialized
= true;
304 curBright
= EV_SCREEN_MAX_BRIGHTNESS
; // FIXME: Set from NVRAM?
305 curVolume
= EV_AUDIO_MAX_VOLUME
/ 2; // FIXME: Set from NVRAM?
306 // Put code here that is to run on the first open ONLY.
313 IOReturn
IOHIDSystem::evClose(void)
315 IOTakeLock( driverLock
);
316 if ( evOpenCalled
== false )
318 IOUnlock( driverLock
);
319 return kIOReturnBadArgument
;
321 // Early close actions here
322 forceAutoDimState(false);
325 cursorStarted
= false;
326 cursorEnabled
= false;
327 IOUnlock( driverLock
);
329 // Release the input devices.
330 detachEventSources();
332 // Tear down the shared memory area if set up
333 // if ( eventsOpen == true )
334 // unmapEventShmem(eventPort);
336 IOTakeLock( driverLock
);
337 // Clear screens registry and related data
338 if ( evScreen
!= (void *)0 )
341 lastShmemPtr
= (void *)0;
343 // Remove port notification for the eventPort and clear the port out
344 setEventPort(MACH_PORT_NULL
);
345 // ipc_port_release_send(event_port);
347 // Clear local state to shutdown
348 evOpenCalled
= false;
351 IOUnlock( driverLock
);
353 return kIOReturnSuccess
;
357 // Dispatch state to screens registered with the Event Driver
358 // Pending state changes for a device may be coalesced.
361 // On entry, the driverLock should be set.
363 void IOHIDSystem::evDispatch(
364 /* command */ EvCmd evcmd
)
371 for( int i
= 0; i
< screens
; i
++ ) {
373 EvScreen
*esp
= &((EvScreen
*)evScreen
)[i
];
377 p
.x
= evg
->cursorLoc
.x
; // Copy from shmem.
378 p
.y
= evg
->cursorLoc
.y
;
380 bool onscreen
= (0 != (cursorScreens
& (1 << i
)));
386 esp
->instance
->moveCursor(&p
, evg
->frame
);
391 esp
->instance
->showCursor(&p
, evg
->frame
);
396 esp
->instance
->hideCursor();
401 /* lets keep that compiler happy */
409 // Dispatch mechanism for special key press. If a port has been registered,
410 // a message is built to be sent out to that port notifying that the key has
411 // changed state. A level in the range 0-64 is provided for convenience.
413 void IOHIDSystem::evSpecialKeyMsg(unsigned key
,
414 /* direction */ unsigned dir
,
415 /* flags */ unsigned f
,
416 /* level */ unsigned l
)
418 mach_port_t dst_port
;
419 struct evioSpecialKeyMsg
*msg
;
421 static const struct evioSpecialKeyMsg init_msg
=
422 { { MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, // mach3xxx, is the right?
423 MACH_MSG_TYPE_MAKE_SEND
), // mach_msg_bits_t msgh_bits;
424 sizeof (struct evioSpecialKeyMsg
), // mach_msg_size_t msgh_size;
425 MACH_PORT_NULL
, // mach_port_t msgh_remote_port;
426 MACH_PORT_NULL
, // mach_port_t msgh_local_port;
427 0, // mach_msg_size_t msgh_reserved;
428 EV_SPECIAL_KEY_MSG_ID
// mach_msg_id_t msgh_id;
436 if ( (dst_port
= specialKeyPort(key
)) == MACH_PORT_NULL
)
438 msg
= (struct evioSpecialKeyMsg
*) IOMalloc(
439 sizeof (struct evioSpecialKeyMsg
) );
443 // Initialize the message.
444 bcopy( &init_msg
, msg
, sizeof (struct evioSpecialKeyMsg
) );
445 msg
->Head
.msgh_remote_port
= dst_port
;
447 msg
->direction
= dir
;
451 // Send the message out from the I/O thread.
452 sendWorkLoopCommand(this,(IOHIDAction
)_performSpecialKeyMsg
,(void*)msg
);
456 // Reset instance variables to their default state for mice/pointers
458 void IOHIDSystem::_resetMouseParameters()
461 IOTakeLock( driverLock
);
462 if ( eventsOpen
== false )
464 IOUnlock( driverLock
);
467 nanoseconds_to_absolutetime( EV_DCLICKTIME
, &clickTimeThresh
);
468 clickSpaceThresh
.x
= clickSpaceThresh
.y
= EV_DCLICKSPACE
;
469 AbsoluteTime_to_scalar( &clickTime
) = 0;
470 clickLoc
.x
= clickLoc
.y
= -EV_DCLICKSPACE
;
472 nanoseconds_to_absolutetime( DAUTODIMPERIOD
, &autoDimPeriod
);
473 clock_get_uptime( &autoDimTime
);
474 ADD_ABSOLUTETIME( &autoDimTime
, &autoDimPeriod
);
475 dimmedBrightness
= DDIMBRIGHTNESS
;
477 IOUnlock( driverLock
);
480 void IOHIDSystem::_resetKeyboardParameters()
485 * Methods exported by the EventDriver.
487 * The screenRegister protocol is used by frame buffer drivers to register
488 * themselves with the Event Driver. These methods are called in response
489 * to a registerSelf or unregisterSelf message received from the Event
493 int IOHIDSystem::registerScreen(IOGraphicsDevice
* instance
,
494 /* bounds */ Bounds
* bp
)
498 if( (false == eventsOpen
) || (0 == bp
) )
503 if ( lastShmemPtr
== (void *)0 )
506 /* shmemSize and bounds already set */
507 esp
= &((EvScreen
*)evScreen
)[screens
];
508 esp
->instance
= instance
;
510 // Update our idea of workSpace bounds
511 if ( bp
->minx
< workSpace
.minx
)
512 workSpace
.minx
= bp
->minx
;
513 if ( bp
->miny
< workSpace
.miny
)
514 workSpace
.miny
= bp
->miny
;
515 if ( bp
->maxx
< workSpace
.maxx
)
516 workSpace
.maxx
= bp
->maxx
;
517 if ( esp
->bounds
->maxy
< workSpace
.maxy
)
518 workSpace
.maxy
= bp
->maxy
;
520 return(SCREENTOKEN
+ screens
++);
524 void IOHIDSystem::unregisterScreen(int index
)
526 index
-= SCREENTOKEN
;
528 IOTakeLock( driverLock
);
529 if ( eventsOpen
== false || index
< 0 || index
>= screens
)
531 IOUnlock( driverLock
);
536 // clear the state for the screen
537 ((EvScreen
*)evScreen
)[index
].instance
= 0;
538 // Put the cursor someplace reasonable if it was on the destroyed screen
539 cursorScreens
&= ~(1 << index
);
540 // This will jump the cursor back on screen
541 setCursorPosition((Point
*)&evg
->cursorLoc
, true);
545 IOUnlock( driverLock
);
548 /* Member of EventClient protocol
550 * Absolute position input devices and some specialized output devices
551 * may need to know the bounding rectangle for all attached displays.
552 * The following method returns a Bounds* for the workspace. Please note
553 * that the bounds are kept as signed values, and that on a multi-display
554 * system the minx and miny values may very well be negative.
556 Bounds
* IOHIDSystem::workspaceBounds()
561 IOReturn
IOHIDSystem::createShmem(void* p1
, void*, void*, void*, void*, void*)
563 int shmemVersion
= (int)p1
;
566 if( shmemVersion
!= kIOHIDCurrentShmemVersion
)
567 return( kIOReturnUnsupported
);
569 IOTakeLock( driverLock
);
571 if( 0 == globalMemory
) {
573 size
= sizeof(EvOffsets
) + sizeof(EvGlobals
);
574 globalMemory
= IOBufferMemoryDescriptor::withOptions(
575 kIODirectionNone
| kIOMemoryKernelUserShared
, size
);
578 IOUnlock( driverLock
);
579 return( kIOReturnNoMemory
);
581 shmem_addr
= (vm_offset_t
) globalMemory
->getBytesNoCopy();
586 IOUnlock( driverLock
);
588 return kIOReturnSuccess
;
592 // Initialize the shared memory area.
594 // On entry, the driverLock should be set.
595 void IOHIDSystem::initShmem()
600 /* top of sharedMem is EvOffsets structure */
601 eop
= (EvOffsets
*) shmem_addr
;
603 bzero( (void*)shmem_addr
, shmem_size
);
605 /* fill in EvOffsets structure */
606 eop
->evGlobalsOffset
= sizeof(EvOffsets
);
607 eop
->evShmemOffset
= eop
->evGlobalsOffset
+ sizeof(EvGlobals
);
609 /* find pointers to start of globals and private shmem region */
610 evg
= (EvGlobals
*)((char *)shmem_addr
+ eop
->evGlobalsOffset
);
611 evs
= (void *)((char *)shmem_addr
+ eop
->evShmemOffset
);
613 evg
->version
= kIOHIDCurrentShmemVersion
;
614 evg
->structSize
= sizeof( EvGlobals
);
616 /* Set default wait cursor parameters */
617 evg
->waitCursorEnabled
= TRUE
;
618 evg
->globalWaitCursorEnabled
= TRUE
;
619 evg
->waitThreshold
= (12 * EV_TICKS_PER_SEC
) / 10;
620 clock_interval_to_absolutetime_interval(DefaultWCFrameRate
, kNanosecondScale
,
622 clock_interval_to_absolutetime_interval(DefaultWCSustain
, kNanosecondScale
,
624 AbsoluteTime_to_scalar(&waitSusTime
) = 0;
625 AbsoluteTime_to_scalar(&waitFrameTime
) = 0;
627 EV_TICK_TO_NS(10,&periodicEventDelta
);
629 /* Set up low-level queues */
631 for (i
=lleqSize
; --i
!= -1; ) {
632 evg
->lleq
[i
].event
.type
= 0;
633 AbsoluteTime_to_scalar(&evg
->lleq
[i
].event
.time
) = 0;
634 evg
->lleq
[i
].event
.flags
= 0;
635 ev_init_lock(&evg
->lleq
[i
].sema
);
636 evg
->lleq
[i
].next
= i
+1;
639 evg
->lleq
[lleqSize
-1].next
= 0;
641 evg
->lleq
[evg
->LLELast
].next
;
643 evg
->lleq
[evg
->LLELast
].next
;
645 evg
->eNum
= INITEVENTNUM
;
650 clock_get_uptime( &ts
);
651 tick
= EV_NS_TO_TICK(&ts
);
653 tick
= 1; // No zero values allowed!
654 evg
->VertRetraceClock
= tick
;
656 evg
->cursorLoc
.x
= pointerLoc
.x
;
657 evg
->cursorLoc
.y
= pointerLoc
.y
;
658 evg
->dontCoalesce
= 0;
659 evg
->dontWantCoalesce
= 0;
660 evg
->wantPressure
= 0;
661 evg
->wantPrecision
= 0;
662 evg
->mouseRectValid
= 0;
664 ev_init_lock( &evg
->cursorSema
);
665 ev_init_lock( &evg
->waitCursorSema
);
666 // Set eventsOpen last to avoid race conditions.
671 // Set the event port. The event port is both an ownership token
672 // and a live port we hold send rights on. The port is owned by our client,
673 // the WindowServer. We arrange to be notified on a port death so that
674 // we can tear down any active resources set up during this session.
675 // An argument of PORT_NULL will cause us to forget any port death
676 // notification that's set up.
678 // The driverLock should be held on entry.
680 void IOHIDSystem::setEventPort(mach_port_t port
)
682 static struct _eventMsg init_msg
= { {
683 // mach_msg_bits_t msgh_bits;
684 MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
,0),
685 // mach_msg_size_t msgh_size;
686 sizeof (struct _eventMsg
),
687 // mach_port_t msgh_remote_port;
689 // mach_port_t msgh_local_port;
691 // mach_msg_size_t msgh_reserved;
693 // mach_msg_id_t msgh_id;
697 if ( eventMsg
== NULL
)
698 eventMsg
= IOMalloc( sizeof (struct _eventMsg
) );
700 // Initialize the events available message.
701 *((struct _eventMsg
*)eventMsg
) = init_msg
;
703 ((struct _eventMsg
*)eventMsg
)->h
.msgh_remote_port
= port
;
707 // Set the port to be used for a special key notification. This could be more
708 // robust about letting ports be set...
710 IOReturn
IOHIDSystem::setSpecialKeyPort(
711 /* keyFlavor */ int special_key
,
712 /* keyPort */ mach_port_t key_port
)
714 if ( special_key
>= 0 && special_key
< NX_NUM_SCANNED_SPECIALKEYS
)
715 _specialKeyPort
[special_key
] = key_port
;
716 return kIOReturnSuccess
;
719 mach_port_t
IOHIDSystem::specialKeyPort(int special_key
)
721 if ( special_key
>= 0 && special_key
< NX_NUM_SCANNED_SPECIALKEYS
)
722 return _specialKeyPort
[special_key
];
723 return MACH_PORT_NULL
;
727 // Helper functions for postEvent
729 static inline int myAbs(int a
) { return(a
> 0 ? a
: -a
); }
731 short IOHIDSystem::getUniqueEventNum()
733 while (++evg
->eNum
== NULLEVENTNUM
)
740 // This routine actually places events in the event queue which is in
741 // the EvGlobals structure. It is called from all parts of the ev
744 // On entry, the driverLock should be set.
747 void IOHIDSystem::postEvent(int what
,
748 /* at */ Point
* location
,
749 /* atTime */ AbsoluteTime ts
,
750 /* withData */ NXEventData
* myData
)
752 NXEQElement
* theHead
= (NXEQElement
*) &evg
->lleq
[evg
->LLEHead
];
753 NXEQElement
* theLast
= (NXEQElement
*) &evg
->lleq
[evg
->LLELast
];
754 NXEQElement
* theTail
= (NXEQElement
*) &evg
->lleq
[evg
->LLETail
];
756 unsigned theClock
= EV_NS_TO_TICK(&ts
);
758 /* Some events affect screen dimming */
759 if (EventCodeMask(what
) & NX_UNDIMMASK
) {
761 ADD_ABSOLUTETIME( &autoDimTime
, &autoDimPeriod
);
765 // Update the PS VertRetraceClock off of the timestamp if it looks sane
766 if ( theClock
> (unsigned)evg
->VertRetraceClock
767 && theClock
< (unsigned)(evg
->VertRetraceClock
+ (20 * EV_TICK_TIME
)) )
768 evg
->VertRetraceClock
= theClock
;
770 wereEvents
= EventsInQueue();
772 xpr_ev_post("postEvent: what %d, X %d Y %d Q %d, needKick %d\n",
773 what
,location
->x
,location
->y
,
774 EventsInQueue(), needToKickEventConsumer
);
776 if ((!evg
->dontCoalesce
) /* Coalescing enabled */
777 && (theHead
!= theTail
)
778 && (theLast
->event
.type
== what
)
779 && (EventCodeMask(what
) & COALESCEEVENTMASK
)
780 && ev_try_lock(&theLast
->sema
)) {
781 /* coalesce events */
782 theLast
->event
.location
.x
= location
->x
;
783 theLast
->event
.location
.y
= location
->y
;
784 absolutetime_to_nanoseconds(ts
, &theLast
->event
.time
);
786 theLast
->event
.data
= *myData
;
787 ev_unlock(&theLast
->sema
);
788 } else if (theTail
->next
!= evg
->LLEHead
) {
789 /* store event in tail */
790 theTail
->event
.type
= what
;
791 theTail
->event
.location
.x
= location
->x
;
792 theTail
->event
.location
.y
= location
->y
;
793 theTail
->event
.flags
= evg
->eventFlags
;
794 absolutetime_to_nanoseconds(ts
, &theLast
->event
.time
);
795 theTail
->event
.window
= 0;
797 theTail
->event
.data
= *myData
;
800 theTail
->event
.data
.mouse
.eventNum
=
801 leftENum
= getUniqueEventNum();
804 theTail
->event
.data
.mouse
.eventNum
=
805 rightENum
= getUniqueEventNum();
808 theTail
->event
.data
.mouse
.eventNum
= leftENum
;
809 leftENum
= NULLEVENTNUM
;
812 theTail
->event
.data
.mouse
.eventNum
= rightENum
;
813 rightENum
= NULLEVENTNUM
;
816 if (EventCodeMask(what
) & PRESSUREEVENTMASK
) {
817 theTail
->event
.data
.mouse
.pressure
= lastPressure
;
819 if (EventCodeMask(what
) & MOUSEEVENTMASK
) { /* Click state */
820 AbsoluteTime delta
= ts
;
821 SUB_ABSOLUTETIME( &delta
, &clickTime
);
822 if ((CMP_ABSOLUTETIME(&delta
, &clickTimeThresh
) <= 0)
823 && (myAbs(location
->x
- clickLoc
.x
) <= clickSpaceThresh
.x
)
824 && (myAbs(location
->y
- clickLoc
.y
) <= clickSpaceThresh
.y
)) {
825 if ((what
== NX_LMOUSEDOWN
)||(what
== NX_RMOUSEDOWN
)) {
827 theTail
->event
.data
.mouse
.click
= ++clickState
;
829 theTail
->event
.data
.mouse
.click
= clickState
;
831 } else if ((what
== NX_LMOUSEDOWN
)||(what
== NX_RMOUSEDOWN
)) {
832 clickLoc
= *location
;
835 theTail
->event
.data
.mouse
.click
= clickState
;
837 theTail
->event
.data
.mouse
.click
= 0;
840 pmon_log_event(PMON_SOURCE_EV
,
846 evg
->LLETail
= theTail
->next
;
847 evg
->LLELast
= theLast
->next
;
848 if ( ! wereEvents
) // Events available, so wake event consumer
854 * if queue is full, ignore event, too hard to take care of all cases
856 IOLog("%s: postEvent LLEventQueue overflow.\n", getName());
859 pmon_log_event( PMON_SOURCE_EV
,
869 * - kickEventConsumer
871 * Try to send a message out to let the event consumer know that
872 * there are now events available for consumption.
875 void IOHIDSystem::kickEventConsumer()
879 IOTakeLock( kickConsumerLock
);
880 xpr_ev_post("kickEventConsumer (need == %d)\n",
881 needToKickEventConsumer
,2,3,4,5);
882 if ( needToKickEventConsumer
== true )
884 IOUnlock( kickConsumerLock
);
885 return; // Request is already pending
887 needToKickEventConsumer
= true; // Posting a request now
888 IOUnlock( kickConsumerLock
);
890 err
= sendWorkLoopCommand(this, (IOHIDAction
)_performKickEventConsumer
,
894 IOLog("%s: cmdQ fail %d\n", getName(), err
);
898 * Event sources may need to use an I/O thread from time to time.
899 * Rather than have each instance running it's own thread, we provide
900 * a callback mechanism to let all the instances share a common Event I/O
901 * thread running in the IOTask space, and managed by the Event Driver.
904 IOReturn
IOHIDSystem::sendWorkLoopCommand(OSObject
* target
,
910 err
= cmdQ
->enqueueCommand( /* sleep */ true,
912 /* field1 */ (void *) action
,
915 return (err
== KERN_SUCCESS
) ? kIOReturnSuccess
: kIOReturnNoMemory
;
919 * The following methods are executed from the I/O thread only.
923 * This routine is run within the I/O thread, on demand from the
924 * sendWorkLoopCommand method above. We attempt to dispatch a message
925 * to the specified selector and instance.
927 void IOHIDSystem::_doPerformInIOThread(void* self
,
928 void* target
, /* IOCommandQueueAction */
933 (*((IOHIDAction
)action
))((OSObject
*)target
, data
);
937 * This is run in the I/O thread, to perform the actual message send operation.
940 void IOHIDSystem::_performSpecialKeyMsg(IOHIDSystem
* self
,
941 struct evioSpecialKeyMsg
*msg
)
946 xpr_ev_post("_performSpecialKeyMsg 0x%x\n", msg
,2,3,4,5);
949 /* FIXME: Don't block */
950 r
= mach_msg_send_from_kernel( &msg
->Head
, msg
->Head
.msgh_size
);
952 xpr_ev_post("_performSpecialKeyMsg: msg_send() == %d\n",r
,2,3,4,5);
953 if ( r
!= MACH_MSG_SUCCESS
)
955 IOLog("%s: _performSpecialKeyMsg msg_send returned %d\n",
958 if ( r
== MACH_SEND_INVALID_DEST
) /* Invalidate the port */
960 self
->setSpecialKeyPort(
961 /* keyFlavor */ msg
->key
,
962 /* keyPort */ MACH_PORT_NULL
);
964 IOFree( (void *)msg
, sizeof (struct evioSpecialKeyMsg
) );
968 * This is run in the I/O thread, to perform the actual message send operation.
969 * Note that we perform a non-blocking send. The Event port in the event
970 * consumer has a queue depth of 1 message. Once the consumer picks up that
971 * message, it runs until the event queue is exhausted before trying to read
972 * another message. If a message is pending,there is no need to enqueue a
973 * second one. This also keeps us from blocking the I/O thread in a msg_send
974 * which could result in a deadlock if the consumer were to make a call into
977 void IOHIDSystem::_performKickEventConsumer(IOHIDSystem
* self
, void *) /* IOHIDAction */
980 mach_msg_header_t
*msgh
982 xpr_ev_post("_performKickEventConsumer\n", 1,2,3,4,5);
983 IOTakeLock( self
->kickConsumerLock
);
984 self
->needToKickEventConsumer
= false; // Request received and processed
985 IOUnlock( self
->kickConsumerLock
);
987 msgh
= (mach_msg_header_t
*)self
->eventMsg
;
990 r
= mach_msg_send_from_kernel( msgh
, msgh
->msgh_size
);
993 case MACH_SEND_TIMED_OUT
:/* Already has a message posted */
994 case MACH_MSG_SUCCESS
: /* Message is posted */
996 default: /* Log the error */
997 IOLog("%s: _performKickEventConsumer msg_send returned %d\n",
1005 // Schedule the next periodic event to be run, based on the current state of
1006 // the event system. We have to consider things here such as when the last
1007 // periodic event pass ran, if there is currently any mouse delta accumulated,
1008 // and how long it has been since the last event was consumed by an app (for
1009 // driving the wait cursor).
1011 // This code should only be run from the periodicEvents method or
1012 // _setCursorPosition.
1014 void IOHIDSystem::scheduleNextPeriodicEvent()
1016 if (CMP_ABSOLUTETIME( &waitFrameTime
, &thisPeriodicRun
) > 0)
1018 AbsoluteTime time_for_next_run
;
1020 clock_get_uptime(&time_for_next_run
);
1021 ADD_ABSOLUTETIME( &time_for_next_run
, &periodicEventDelta
);
1023 if (CMP_ABSOLUTETIME( &waitFrameTime
, &time_for_next_run
) < 0) {
1024 timerES
->wakeAtTime(waitFrameTime
);
1029 timerES
->setTimeout(periodicEventDelta
);
1032 // Periodic events are driven from this method.
1033 // After taking care of all pending work, the method
1034 // calls scheduleNextPeriodicEvent to compute and set the
1038 void IOHIDSystem::_periodicEvents(IOHIDSystem
* self
,
1039 IOTimerEventSource
*timer
)
1041 self
->periodicEvents(timer
);
1044 void IOHIDSystem::periodicEvents(IOTimerEventSource
* /* timer */)
1045 /* IOTimerEventSource::Action, IOHIDAction */
1049 // If eventsOpen is false, then the driver shmem is
1050 // no longer valid, and it is in the process of shutting down.
1051 // We should give up without rescheduling.
1052 IOTakeLock( driverLock
);
1053 if ( eventsOpen
== false )
1055 IOUnlock( driverLock
);
1059 // Increment event time stamp last
1060 clock_get_uptime(&thisPeriodicRun
);
1062 // Temporary hack til we wean CGS off of VertRetraceClock
1063 tick
= EV_NS_TO_TICK(&thisPeriodicRun
);
1066 evg
->VertRetraceClock
= tick
;
1068 // Update cursor position if needed
1069 if ( needSetCursorPosition
== true )
1070 _setCursorPosition(&pointerLoc
, false);
1072 // WAITCURSOR ACTION
1073 if ( ev_try_lock(&evg
->waitCursorSema
) )
1075 if ( ev_try_lock(&evg
->cursorSema
) )
1077 // See if the current context has timed out
1078 if ( (evg
->AALastEventSent
!= evg
->AALastEventConsumed
)
1079 && ((evg
->VertRetraceClock
- evg
->AALastEventSent
>
1080 evg
->waitThreshold
)))
1081 evg
->ctxtTimedOut
= TRUE
;
1082 // If wait cursor enabled and context timed out, do waitcursor
1083 if (evg
->waitCursorEnabled
&& evg
->globalWaitCursorEnabled
&&
1086 /* WAIT CURSOR SHOULD BE ON */
1087 if (!evg
->waitCursorUp
)
1091 /* WAIT CURSOR SHOULD BE OFF */
1092 if (evg
->waitCursorUp
&&
1093 CMP_ABSOLUTETIME(&waitSusTime
, &thisPeriodicRun
) <= 0)
1096 /* Animate cursor */
1097 if (evg
->waitCursorUp
&&
1098 CMP_ABSOLUTETIME(&waitFrameTime
, &thisPeriodicRun
) <= 0)
1099 animateWaitCursor();
1100 ev_unlock(&evg
->cursorSema
);
1101 if ((CMP_ABSOLUTETIME(&thisPeriodicRun
, &autoDimTime
) > 0)
1105 ev_unlock(&evg
->waitCursorSema
);
1108 scheduleNextPeriodicEvent();
1109 IOUnlock( driverLock
);
1115 // Start the cursor system running.
1117 // At this point, the WindowServer is up, running, and ready to process events.
1118 // We will attach the keyboard and mouse, if none are available yet.
1121 bool IOHIDSystem::resetCursor()
1124 UInt32 newScreens
= 0;
1125 SInt32 pinScreen
= -1L;
1127 p
= &evg
->cursorLoc
;
1129 /* Get mask of screens on which the cursor is present */
1130 EvScreen
*screen
= (EvScreen
*)evScreen
;
1131 for (int i
= 0; i
< screens
; i
++ ) {
1132 if ((screen
[i
].instance
) && PtInRect(p
, screen
[i
].bounds
)) {
1134 newScreens
|= (1 << i
);
1138 if (newScreens
== 0)
1142 cursorPin
= *(((EvScreen
*)evScreen
)[pinScreen
].bounds
);
1143 cursorPin
.maxx
--; /* Make half-open rectangle */
1145 cursorPinScreen
= pinScreen
;
1147 if (newScreens
== 0) {
1148 /* Pin new cursor position to cursorPin rect */
1149 p
->x
= (p
->x
< cursorPin
.minx
) ?
1150 cursorPin
.minx
: ((p
->x
> cursorPin
.maxx
) ?
1151 cursorPin
.maxx
: p
->x
);
1152 p
->y
= (p
->y
< cursorPin
.miny
) ?
1153 cursorPin
.miny
: ((p
->y
> cursorPin
.maxy
) ?
1154 cursorPin
.maxy
: p
->y
);
1156 /* regenerate mask for new position */
1157 for (int i
= 0; i
< screens
; i
++ ) {
1158 if ((screen
[i
].instance
) && PtInRect(p
, screen
[i
].bounds
))
1159 newScreens
|= (1 << i
);
1163 cursorScreens
= newScreens
;
1165 pointerDelta
.x
+= (evg
->cursorLoc
.x
- pointerLoc
.x
);
1166 pointerDelta
.y
+= (evg
->cursorLoc
.y
- pointerLoc
.y
);
1167 pointerLoc
.x
= evg
->cursorLoc
.x
;
1168 pointerLoc
.y
= evg
->cursorLoc
.y
;
1173 bool IOHIDSystem::startCursor()
1177 if (0 == screens
) // no screens, no cursor
1184 // Start the cursor control callouts
1185 ok
= (kIOReturnSuccess
==
1186 sendWorkLoopCommand(this, (IOHIDAction
)_periodicEvents
, timerES
));
1193 // Wait Cursor machinery. The driverLock should be held on entry to
1194 // these methods, and the shared memory area must be set up.
1196 void IOHIDSystem::showWaitCursor()
1198 xpr_ev_cursor("showWaitCursor\n",1,2,3,4,5);
1199 evg
->waitCursorUp
= true;
1201 evg
->frame
= EV_WAITCURSOR
;
1203 // Set animation and sustain absolute times.
1205 waitSusTime
= waitFrameTime
= thisPeriodicRun
;
1206 ADD_ABSOLUTETIME( &waitFrameTime
, &waitFrameRate
);
1207 ADD_ABSOLUTETIME( &waitSusTime
, &waitSustain
);
1210 void IOHIDSystem::hideWaitCursor()
1212 xpr_ev_cursor("hideWaitCursor\n",1,2,3,4,5);
1213 evg
->waitCursorUp
= false;
1215 evg
->frame
= EV_STD_CURSOR
;
1217 AbsoluteTime_to_scalar(&waitFrameTime
) = 0;
1218 AbsoluteTime_to_scalar(&waitSusTime
) = 0;
1221 void IOHIDSystem::animateWaitCursor()
1223 xpr_ev_cursor("animateWaitCursor\n",1,2,3,4,5);
1224 changeCursor(evg
->frame
+ 1);
1225 // Set the next animation time.
1226 waitFrameTime
= thisPeriodicRun
;
1227 ADD_ABSOLUTETIME( &waitFrameTime
, &waitFrameRate
);
1230 void IOHIDSystem::changeCursor(int frame
)
1233 (frame
> EV_MAXCURSOR
) ? EV_WAITCURSOR
: frame
;
1234 xpr_ev_cursor("changeCursor %d\n",evg
->frame
,2,3,4,5);
1239 // Return the screen number in which point p lies. Return -1 if the point
1240 // lies outside of all registered screens.
1242 int IOHIDSystem::pointToScreen(Point
* p
)
1245 EvScreen
*screen
= (EvScreen
*)evScreen
;
1246 for (i
=screens
; --i
!= -1; ) {
1247 if (screen
[i
].instance
!= 0
1248 && (p
->x
>= screen
[i
].bounds
->minx
)
1249 && (p
->x
< screen
[i
].bounds
->maxx
)
1250 && (p
->y
>= screen
[i
].bounds
->miny
)
1251 && (p
->y
< screen
[i
].bounds
->maxy
))
1254 return(-1); /* Cursor outside of known screen boundary */
1258 // API used to manipulate screen brightness
1260 // On entry to each of these, the driverLock should be set.
1262 // Set the current brightness
1263 void IOHIDSystem::setBrightness(int b
)
1265 if ( b
< EV_SCREEN_MIN_BRIGHTNESS
)
1266 b
= EV_SCREEN_MIN_BRIGHTNESS
;
1267 else if ( b
> EV_SCREEN_MAX_BRIGHTNESS
)
1268 b
= EV_SCREEN_MAX_BRIGHTNESS
;
1269 if ( b
!= curBright
)
1272 if ( autoDimmed
== false )
1277 int IOHIDSystem::brightness()
1282 // Set the current brightness
1283 void IOHIDSystem::setAutoDimBrightness(int b
)
1285 if ( b
< EV_SCREEN_MIN_BRIGHTNESS
)
1286 b
= EV_SCREEN_MIN_BRIGHTNESS
;
1287 else if ( b
> EV_SCREEN_MAX_BRIGHTNESS
)
1288 b
= EV_SCREEN_MAX_BRIGHTNESS
;
1289 if ( b
!= dimmedBrightness
)
1291 dimmedBrightness
= b
;
1292 if ( autoDimmed
== true )
1297 int IOHIDSystem::autoDimBrightness()
1299 return dimmedBrightness
;
1302 int IOHIDSystem::currentBrightness() // Return the current brightness
1304 if ( autoDimmed
== true && dimmedBrightness
< curBright
)
1305 return dimmedBrightness
;
1310 void IOHIDSystem::doAutoDim()
1316 // Return display brightness to normal
1317 void IOHIDSystem::undoAutoDim()
1323 void IOHIDSystem::forceAutoDimState(bool dim
)
1327 if ( autoDimmed
== false )
1329 if ( eventsOpen
== true )
1330 clock_get_uptime( &autoDimTime
);
1336 if ( autoDimmed
== true )
1338 if ( eventsOpen
== true ) {
1339 clock_get_uptime( &autoDimTime
);
1340 ADD_ABSOLUTETIME( &autoDimTime
, &autoDimPeriod
);
1348 // API used to manipulate sound volume/attenuation
1350 // Set the current brightness.
1351 void IOHIDSystem::setAudioVolume(int v
)
1353 if ( v
< EV_AUDIO_MIN_VOLUME
)
1354 v
= EV_AUDIO_MIN_VOLUME
;
1355 else if ( v
> EV_AUDIO_MAX_VOLUME
)
1356 v
= EV_AUDIO_MAX_VOLUME
;
1361 // Volume set programatically, rather than from keyboard
1363 void IOHIDSystem::setUserAudioVolume(int v
)
1366 // Let sound driver know about the change
1367 evSpecialKeyMsg( NX_KEYTYPE_SOUND_UP
,
1368 /* direction */ NX_KEYDOWN
,
1370 /* level */ curVolume
);
1373 int IOHIDSystem::audioVolume()
1379 // API used to drive event state out to attached screens
1381 // On entry to each of these, the driverLock should be set.
1383 inline void IOHIDSystem::setBrightness() // Propagate state out to screens
1385 evDispatch(/* command */ EVLEVEL
);
1388 inline void IOHIDSystem::showCursor()
1390 evDispatch(/* command */ EVSHOW
);
1392 inline void IOHIDSystem::hideCursor()
1394 evDispatch(/* command */ EVHIDE
);
1397 inline void IOHIDSystem::moveCursor()
1399 evDispatch(/* command */ EVMOVE
);
1403 // - attachDefaultEventSources
1404 // Attach the default event sources.
1406 void IOHIDSystem::attachDefaultEventSources()
1409 OSIterator
* sources
;
1412 sources
= getProviderIterator();
1414 if (!sources
) return;
1416 while( (source
= sources
->getNextObject())) {
1417 if (OSDynamicCast(IOHIDevice
, source
)) {
1419 registerEventSource((IOHIDevice
*)source
);
1426 // - detachEventSources
1427 // Detach all event sources
1429 void IOHIDSystem::detachEventSources()
1432 IOHIDevice
* srcInstance
;
1434 iter
= getOpenProviderIterator();
1436 while( (srcInstance
= (IOHIDevice
*) iter
->getNextObject())) {
1438 kprintf("detachEventSource:%s\n", srcInstance
->getName());
1440 srcInstance
->close(this);
1447 // EventSrcClient implementation
1451 // A new device instance desires to be added to our list.
1452 // Try to get ownership of the device. If we get it, add it to
1455 bool IOHIDSystem::registerEventSource(IOHIDevice
* source
)
1457 bool success
= false;
1460 kprintf("registerEventSource:%s\n", ((IOHIDevice
*)source
)->getName());
1463 if ( OSDynamicCast(IOHIKeyboard
, source
) ) {
1464 success
= ((IOHIKeyboard
*)source
)->open(this, kIOServiceSeize
,
1465 (KeyboardEventAction
) _keyboardEvent
,
1466 (KeyboardSpecialEventAction
) _keyboardSpecialEvent
,
1467 (UpdateEventFlagsAction
) _updateEventFlags
);
1468 } else if ( OSDynamicCast(IOHIPointing
, source
) ) {
1469 success
= ((IOHIPointing
*)source
)->open(this, kIOServiceSeize
,
1470 (RelativePointerEventAction
) _relativePointerEvent
,
1471 (AbsolutePointerEventAction
) _absolutePointerEvent
,
1472 (ScrollWheelEventAction
) _scrollWheelEvent
);
1475 if ( success
== false )
1476 IOLog("%s: Seize of %s failed.\n", getName(), source
->getName());
1481 IOReturn
IOHIDSystem::message(UInt32 type
, IOService
* provider
,
1484 IOReturn status
= kIOReturnSuccess
;
1488 case kIOMessageServiceIsTerminated
:
1490 kprintf("detachEventSource:%s\n", provider
->getName());
1492 provider
->close( this );
1493 case kIOMessageServiceWasClosed
:
1497 status
= super::message(type
, provider
, argument
);
1505 // This will scale the point at location in the coordinate system represented by bounds
1506 // to the coordinate system of the current screen.
1507 // This is needed for absolute pointer events that come from devices with different bounds.
1509 void IOHIDSystem::_scaleLocationToCurrentScreen(Point
*location
, Bounds
*bounds
)
1511 // We probably also need to look at current screen offsets as well
1512 // but that shouldn't matter until we provide tablets with a way to
1513 // switch screens...
1514 location
->x
= ((location
->x
- bounds
->minx
) * (cursorPin
.maxx
- cursorPin
.minx
+ 1)
1515 / (bounds
->maxx
- bounds
->minx
)) + cursorPin
.minx
;
1516 location
->y
= ((location
->y
- bounds
->miny
) * (cursorPin
.maxy
- cursorPin
.miny
+ 1)
1517 / (bounds
->maxy
- bounds
->miny
)) + cursorPin
.miny
;
1524 // Process a mouse status change. The driver should sign extend
1525 // it's deltas and perform any bit flipping needed there.
1527 // We take the state as presented and turn it into events.
1529 void IOHIDSystem::_relativePointerEvent(IOHIDSystem
* self
,
1531 /* deltaX */ int dx
,
1532 /* deltaY */ int dy
,
1533 /* atTime */ AbsoluteTime ts
)
1535 self
->relativePointerEvent(buttons
, dx
, dy
, ts
);
1538 void IOHIDSystem::relativePointerEvent(int buttons
,
1539 /* deltaX */ int dx
,
1540 /* deltaY */ int dy
,
1541 /* atTime */ AbsoluteTime ts
)
1543 AbsoluteTime nextVBL
, vblDeltaTime
, eventDeltaTime
, moveDeltaTime
;
1545 if( displayManager
!= NULL
) // if there is a display manager, tell
1546 displayManager
->activityTickle(0,0); // it there is user activity
1548 IOTakeLock( driverLock
);
1549 if( eventsOpen
== false )
1551 IOUnlock( driverLock
);
1554 // Fake up pressure changes from button state changes
1555 if( (buttons
& EV_LB
) != (evg
->buttons
& EV_LB
) )
1557 if ( buttons
& EV_LB
)
1558 lastPressure
= MAXPRESSURE
;
1560 lastPressure
= MINPRESSURE
;
1562 _setButtonState(buttons
, /* atTime */ ts
);
1564 // figure cursor movement
1567 eventDeltaTime
= ts
;
1568 SUB_ABSOLUTETIME( &eventDeltaTime
, &lastEventTime
);
1571 IOGraphicsDevice
* instance
= ((EvScreen
*)evScreen
)[cursorPinScreen
].instance
;
1573 instance
->getVBLTime( &nextVBL
, &vblDeltaTime
);
1575 nextVBL
.hi
= nextVBL
.lo
= vblDeltaTime
.hi
= vblDeltaTime
.lo
= 0;
1577 if( dx
&& ((dx
^ accumDX
) < 0))
1579 if( dy
&& ((dy
^ accumDY
) < 0))
1582 KERNEL_DEBUG(0x0c000060 | DBG_FUNC_NONE
,
1583 nextVBL
.hi
, nextVBL
.lo
, postedVBLTime
.hi
, postedVBLTime
.lo
, 0);
1585 if( (nextVBL
.lo
|| nextVBL
.hi
)
1586 && (nextVBL
.lo
== postedVBLTime
.lo
) && (nextVBL
.hi
== postedVBLTime
.hi
)) {
1591 SInt32 num
= 0, div
= 0;
1597 SUB_ABSOLUTETIME( &moveDeltaTime
, &lastMoveTime
);
1600 if( (eventDeltaTime
.lo
< vblDeltaTime
.lo
) && (0 == eventDeltaTime
.hi
)
1601 && vblDeltaTime
.lo
&& moveDeltaTime
.lo
) {
1602 num
= vblDeltaTime
.lo
;
1603 div
= moveDeltaTime
.lo
;
1604 dx
= (num
* dx
) / div
;
1605 dy
= (num
* dy
) / div
;
1608 KERNEL_DEBUG(0x0c000000 | DBG_FUNC_NONE
,
1609 dx
, dy
, num
, div
, 0);
1611 postedVBLTime
= nextVBL
; // we have posted for this vbl
1612 accumDX
= accumDY
= 0;
1617 pointerDelta
.x
+= dx
;
1618 pointerDelta
.y
+= dy
;
1619 _setCursorPosition(&pointerLoc
, false);
1623 IOUnlock( driverLock
);
1626 void IOHIDSystem::_absolutePointerEvent(IOHIDSystem
* self
,
1628 /* at */ Point
* newLoc
,
1629 /* withBounds */ Bounds
* bounds
,
1630 /* inProximity */ bool proximity
,
1631 /* withPressure */ int pressure
,
1632 /* withAngle */ int stylusAngle
,
1633 /* atTime */ AbsoluteTime ts
)
1635 self
->absolutePointerEvent(buttons
, newLoc
, bounds
, proximity
,
1636 pressure
, stylusAngle
, ts
);
1639 void IOHIDSystem::absolutePointerEvent(int buttons
,
1640 /* at */ Point
* newLoc
,
1641 /* withBounds */ Bounds
* bounds
,
1642 /* inProximity */ bool proximity
,
1643 /* withPressure */ int pressure
,
1644 /* withAngle */ int /* stylusAngle */,
1645 /* atTime */ AbsoluteTime ts
)
1649 * If you don't know what to pass for the following fields, pass the
1650 * default values below:
1651 * pressure = MINPRESSURE or MAXPRESSURE
1655 NXEventData outData
; /* dummy data */
1657 if ( displayManager
!= NULL
) { // if there is a display manager, tell
1658 displayManager
->activityTickle(0,0); // it there is user activity
1661 IOTakeLock( driverLock
);
1662 if ( eventsOpen
== false )
1664 IOUnlock( driverLock
);
1668 lastPressure
= pressure
;
1670 _scaleLocationToCurrentScreen(newLoc
, bounds
);
1671 if ( newLoc
->x
!= pointerLoc
.x
|| newLoc
->y
!= pointerLoc
.y
)
1673 pointerDelta
.x
+= (newLoc
->x
- pointerLoc
.x
);
1674 pointerDelta
.y
+= (newLoc
->y
- pointerLoc
.y
);
1675 pointerLoc
= *newLoc
;
1676 _setCursorPosition(&pointerLoc
, false);
1678 if ( lastProximity
!= proximity
&& proximity
== true )
1680 evg
->eventFlags
|= NX_STYLUSPROXIMITYMASK
;
1681 bzero( (char *)&outData
, sizeof outData
);
1682 postEvent( NX_FLAGSCHANGED
,
1683 /* at */ (Point
*)&pointerLoc
,
1685 /* withData */ &outData
);
1687 if ( proximity
== true )
1688 _setButtonState(buttons
, /* atTime */ ts
);
1689 if ( lastProximity
!= proximity
&& proximity
== false )
1691 evg
->eventFlags
&= ~NX_STYLUSPROXIMITYMASK
;
1692 bzero( (char *)&outData
, sizeof outData
);
1693 postEvent( NX_FLAGSCHANGED
,
1694 /* at */ (Point
*)&pointerLoc
,
1696 /* withData */ &outData
);
1698 lastProximity
= proximity
;
1699 IOUnlock( driverLock
);
1702 void IOHIDSystem::_scrollWheelEvent(IOHIDSystem
* self
,
1706 /* atTime */ AbsoluteTime ts
)
1708 self
->scrollWheelEvent(deltaAxis1
, deltaAxis2
, deltaAxis3
, ts
);
1711 void IOHIDSystem::scrollWheelEvent(short deltaAxis1
,
1714 /* atTime */ AbsoluteTime ts
)
1717 NXEventData wheelData
;
1719 if ((deltaAxis1
== 0) && (deltaAxis2
== 0) && (deltaAxis3
== 0)) {
1723 IOTakeLock( driverLock
);
1726 IOUnlock(driverLock
);
1730 bzero((char *)&wheelData
, sizeof wheelData
);
1731 wheelData
.scrollWheel
.deltaAxis1
= deltaAxis1
;
1732 wheelData
.scrollWheel
.deltaAxis2
= deltaAxis2
;
1733 wheelData
.scrollWheel
.deltaAxis3
= deltaAxis3
;
1735 postEvent( NX_SCROLLWHEELMOVED
,
1736 /* at */ (Point
*)&evg
->cursorLoc
,
1738 /* withData */ &wheelData
);
1740 IOUnlock(driverLock
);
1744 void IOHIDSystem::_tabletEvent(IOHIDSystem
*self
,
1745 NXEventData
*tabletData
,
1748 self
->tabletEvent(tabletData
, ts
);
1751 void IOHIDSystem::tabletEvent(NXEventData
*tabletData
,
1754 IOTakeLock(driverLock
);
1757 postEvent(NX_TABLETPOINTER
,
1758 (Point
*)&evg
->cursorLoc
,
1763 IOUnlock(driverLock
);
1768 void IOHIDSystem::_proximityEvent(IOHIDSystem
*self
,
1769 NXEventData
*proximityData
,
1772 self
->proximityEvent(proximityData
, ts
);
1775 void IOHIDSystem::proximityEvent(NXEventData
*proximityData
,
1778 IOTakeLock(driverLock
);
1781 postEvent(NX_TABLETPROXIMITY
,
1782 (Point
*)&evg
->cursorLoc
,
1787 IOUnlock(driverLock
);
1793 // Process a keyboard state change.
1795 void IOHIDSystem::_keyboardEvent(IOHIDSystem
* self
,
1797 /* flags */ unsigned flags
,
1798 /* keyCode */ unsigned key
,
1799 /* charCode */ unsigned charCode
,
1800 /* charSet */ unsigned charSet
,
1801 /* originalCharCode */ unsigned origCharCode
,
1802 /* originalCharSet */ unsigned origCharSet
,
1803 /* keyboardType */ unsigned keyboardType
,
1804 /* repeat */ bool repeat
,
1805 /* atTime */ AbsoluteTime ts
)
1807 self
->keyboardEvent(eventType
, flags
, key
, charCode
, charSet
,
1808 origCharCode
, origCharSet
, keyboardType
, repeat
, ts
);
1811 void IOHIDSystem::keyboardEvent(unsigned eventType
,
1812 /* flags */ unsigned flags
,
1813 /* keyCode */ unsigned key
,
1814 /* charCode */ unsigned charCode
,
1815 /* charSet */ unsigned charSet
,
1816 /* originalCharCode */ unsigned origCharCode
,
1817 /* originalCharSet */ unsigned origCharSet
,
1818 /* keyboardType */ unsigned keyboardType
,
1819 /* repeat */ bool repeat
,
1820 /* atTime */ AbsoluteTime ts
)
1822 NXEventData outData
;
1824 if ( ! (displayState
& IOPMDeviceUsable
) ) { // display is off, consume the keystroke
1825 if ( eventType
== NX_KEYDOWN
) {
1828 if ( displayManager
!= NULL
) { // but if there is a display manager, tell
1829 displayManager
->activityTickle(0,0); // it there is user activity
1834 if ( displayManager
!= NULL
) { // if there is a display manager, tell
1835 displayManager
->activityTickle(0,0); // it there is user activity
1838 outData
.key
.repeat
= repeat
;
1839 outData
.key
.keyCode
= key
;
1840 outData
.key
.charSet
= charSet
;
1841 outData
.key
.charCode
= charCode
;
1842 outData
.key
.origCharSet
= origCharSet
;
1843 outData
.key
.origCharCode
= origCharCode
;
1844 outData
.key
.keyboardType
= keyboardType
;
1846 IOTakeLock( driverLock
);
1847 if ( eventsOpen
== false )
1849 IOUnlock( driverLock
);
1852 evg
->eventFlags
= (evg
->eventFlags
& ~KEYBOARD_FLAGSMASK
)
1853 | (flags
& KEYBOARD_FLAGSMASK
);
1855 postEvent( eventType
,
1856 /* at */ (Point
*)&pointerLoc
,
1858 /* withData */ &outData
);
1860 IOUnlock( driverLock
);
1863 void IOHIDSystem::_keyboardSpecialEvent( IOHIDSystem
* self
,
1865 /* flags */ unsigned flags
,
1866 /* keyCode */ unsigned key
,
1867 /* specialty */ unsigned flavor
,
1868 /* guid */ UInt64 guid
,
1869 /* repeat */ bool repeat
,
1870 /* atTime */ AbsoluteTime ts
)
1872 self
->keyboardSpecialEvent(eventType
, flags
, key
, flavor
, guid
, repeat
, ts
);
1876 void IOHIDSystem::keyboardSpecialEvent( unsigned eventType
,
1877 /* flags */ unsigned flags
,
1878 /* keyCode */ unsigned key
,
1879 /* specialty */ unsigned flavor
,
1880 /* guid */ UInt64 guid
,
1881 /* repeat */ bool repeat
,
1882 /* atTime */ AbsoluteTime ts
)
1884 NXEventData outData
;
1887 bzero( (void *)&outData
, sizeof outData
);
1889 IOTakeLock( driverLock
);
1890 if ( eventsOpen
== false )
1892 IOUnlock( driverLock
);
1897 evg
->eventFlags
= (evg
->eventFlags
& ~KEYBOARD_FLAGSMASK
)
1898 | (flags
& KEYBOARD_FLAGSMASK
);
1900 if ( eventType
== NX_KEYDOWN
)
1904 case NX_KEYTYPE_SOUND_UP
:
1905 if ( (flags
& SPECIALKEYS_MODIFIER_MASK
) == 0 )
1907 //level = IOAudioManager::sharedInstance()->incrementMasterVolume();
1908 if (masterAudioFunctions
&& masterAudioFunctions
->incrementMasterVolume
)
1910 masterAudioFunctions
->incrementMasterVolume();
1915 if( !(evg
->eventFlags
& NX_COMMANDMASK
) &&
1916 !(evg
->eventFlags
& NX_CONTROLMASK
) &&
1917 !(evg
->eventFlags
& NX_SHIFTMASK
) &&
1918 (evg
->eventFlags
& NX_ALTERNATEMASK
) )
1920 // Open the sound preferences control panel.
1921 KUNCExecute( "Sound.preference", kOpenAppAsConsoleUser
, kOpenPreferencePanel
);
1925 case NX_KEYTYPE_SOUND_DOWN
:
1926 if ( (flags
& SPECIALKEYS_MODIFIER_MASK
) == 0 )
1928 //level = IOAudioManager::sharedInstance()->decrementMasterVolume();
1929 if (masterAudioFunctions
&& masterAudioFunctions
->decrementMasterVolume
)
1931 masterAudioFunctions
->decrementMasterVolume();
1936 if( !(evg
->eventFlags
& NX_COMMANDMASK
) &&
1937 !(evg
->eventFlags
& NX_CONTROLMASK
) &&
1938 !(evg
->eventFlags
& NX_SHIFTMASK
) &&
1939 (evg
->eventFlags
& NX_ALTERNATEMASK
) )
1941 // Open the sound preferences control panel.
1942 KUNCExecute( "Sound.preference", kOpenAppAsConsoleUser
, kOpenPreferencePanel
);
1946 case NX_KEYTYPE_MUTE
:
1947 if ( (flags
& SPECIALKEYS_MODIFIER_MASK
) == 0 )
1949 //level = IOAudioManager::sharedInstance()->toggleMasterMute();
1950 if (masterAudioFunctions
&& masterAudioFunctions
->toggleMasterMute
)
1952 masterAudioFunctions
->toggleMasterMute();
1957 if( !(evg
->eventFlags
& NX_COMMANDMASK
) &&
1958 !(evg
->eventFlags
& NX_CONTROLMASK
) &&
1959 !(evg
->eventFlags
& NX_SHIFTMASK
) &&
1960 (evg
->eventFlags
& NX_ALTERNATEMASK
) )
1962 // Open the sound preferences control panel.
1963 KUNCExecute( "Sound.preference", kOpenAppAsConsoleUser
, kOpenPreferencePanel
);
1967 case NX_KEYTYPE_EJECT
:
1969 // Special key handlers:
1971 // Command = invoke macsbug
1972 // Command+option = sleep now
1973 // Command+option+control = shutdown now
1974 // Control = logout dialog
1976 if( (evg
->eventFlags
& NX_COMMANDMASK
) &&
1977 !(evg
->eventFlags
& NX_CONTROLMASK
) &&
1978 !(evg
->eventFlags
& NX_SHIFTMASK
) &&
1979 !(evg
->eventFlags
& NX_ALTERNATEMASK
) )
1981 // Post a power key event, Classic should pick this up and
1982 // drop into MacsBug.
1984 outData
.compound
.subType
= NX_SUBTYPE_POWER_KEY
;
1985 postEvent( NX_SYSDEFINED
,
1986 /* at */ (Point
*)&pointerLoc
,
1988 /* withData */ &outData
);
1990 else if( (evg
->eventFlags
& NX_COMMANDMASK
) &&
1991 !(evg
->eventFlags
& NX_CONTROLMASK
) &&
1992 !(evg
->eventFlags
& NX_SHIFTMASK
) &&
1993 (evg
->eventFlags
& NX_ALTERNATEMASK
) )
1995 //IOLog( "IOHIDSystem -- sleep now!\n" );
1997 // Post the sleep now event. Someone else will handle the actual call.
1999 outData
.compound
.subType
= NX_SUBTYPE_SLEEP_EVENT
;
2000 postEvent( NX_SYSDEFINED
,
2001 /* at */ (Point
*)&pointerLoc
,
2003 /* withData */ &outData
);
2005 else if( (evg
->eventFlags
& NX_COMMANDMASK
) &&
2006 (evg
->eventFlags
& NX_CONTROLMASK
) &&
2007 !(evg
->eventFlags
& NX_SHIFTMASK
) &&
2008 (evg
->eventFlags
& NX_ALTERNATEMASK
) )
2010 //IOLog( "IOHIDSystem -- shutdown now!\n" );
2012 // Post the shutdown now event. Someone else will handle the actual call.
2014 outData
.compound
.subType
= NX_SUBTYPE_SHUTDOWN_EVENT
;
2015 postEvent( NX_SYSDEFINED
,
2016 /* at */ (Point
*)&pointerLoc
,
2018 /* withData */ &outData
);
2020 else if( (evg
->eventFlags
& NX_COMMANDMASK
) &&
2021 (evg
->eventFlags
& NX_CONTROLMASK
) &&
2022 !(evg
->eventFlags
& NX_SHIFTMASK
) &&
2023 !(evg
->eventFlags
& NX_ALTERNATEMASK
) )
2026 //IOLog( "IOHIDSystem -- Restart now!\n" );
2028 // Post the Restart now event. Someone else will handle the actual call.
2030 outData
.compound
.subType
= NX_SUBTYPE_RESTART_EVENT
;
2031 postEvent( NX_SYSDEFINED
,
2032 /* at */ (Point
*)&pointerLoc
,
2034 /* withData */ &outData
);
2036 else if( !(evg
->eventFlags
& NX_COMMANDMASK
) &&
2037 (evg
->eventFlags
& NX_CONTROLMASK
) &&
2038 !(evg
->eventFlags
& NX_SHIFTMASK
) &&
2039 !(evg
->eventFlags
& NX_ALTERNATEMASK
) )
2041 // Looks like we should put up the normal 'Power Key' dialog.
2043 // Set the event flags to zero, because the system will not do the right
2044 // thing if we don't zero this out (it will ignore the power key event
2045 // we post, thinking that some modifiers are down).
2047 evg
->eventFlags
= 0;
2049 // Post the power keydown event.
2051 outData
.compound
.subType
= NX_SUBTYPE_POWER_KEY
;
2052 postEvent( NX_SYSDEFINED
,
2053 /* at */ (Point
*)&pointerLoc
,
2055 /* withData */ &outData
);
2059 // After all that checking, no modifiers are down, so let's pump up a
2060 // system defined eject event. This way we can have anyone who's watching
2061 // for this event (aka LoginWindow) route this event to the right target
2062 // (aka AutoDiskMounter).
2064 //IOLog( "IOHIDSystem--Normal Eject action!\n" );
2066 // Post the eject keydown event.
2068 outData
.compound
.subType
= NX_SUBTYPE_EJECT_KEY
;
2069 postEvent( NX_SYSDEFINED
,
2070 /* at */ (Point
*)&pointerLoc
,
2072 /* withData */ &outData
);
2077 outData
.compound
.subType
= NX_SUBTYPE_POWER_KEY
;
2078 postEvent( NX_SYSDEFINED
,
2079 /* at */ (Point
*)&pointerLoc
,
2081 /* withData */ &outData
);
2085 #if 0 /* So far, nothing to do on keyup */
2086 else if ( eventType
== NX_KEYUP
)
2090 case NX_KEYTYPE_SOUND_UP
:
2092 case NX_KEYTYPE_SOUND_DOWN
:
2094 case NX_KEYTYPE_MUTE
:
2101 if( (0 == (flags
& SPECIALKEYS_MODIFIER_MASK
))
2102 && ((1 << flavor
) & NX_SPECIALKEY_POST_MASK
)) {
2103 outData
.compound
.subType
= NX_SUBTYPE_AUX_CONTROL_BUTTONS
;
2104 outData
.compound
.misc
.S
[0] = flavor
;
2105 outData
.compound
.misc
.C
[2] = eventType
;
2106 outData
.compound
.misc
.C
[3] = repeat
;
2107 outData
.compound
.misc
.L
[1] = guid
& 0xffffffff;
2108 outData
.compound
.misc
.L
[2] = guid
>> 32;
2110 postEvent( NX_SYSDEFINED
,
2111 /* at */ (Point
*)&pointerLoc
,
2113 /* withData */ &outData
);
2116 IOUnlock( driverLock
);
2117 if ( level
!= -1 ) // An interesting special key event occurred
2119 evSpecialKeyMsg( flavor
,
2120 /* direction */ eventType
,
2127 * Update current event flags. Restricted to keyboard flags only, this
2128 * method is used to silently update the flags state for keys which both
2129 * generate characters and flag changes. The specs say we don't generate
2130 * a flags-changed event for such keys. This method is also used to clear
2131 * the keyboard flags on a keyboard subsystem reset.
2133 void IOHIDSystem::_updateEventFlags(IOHIDSystem
* self
, unsigned flags
)
2135 self
->updateEventFlags(flags
);
2138 void IOHIDSystem::updateEventFlags(unsigned flags
)
2140 IOTakeLock( driverLock
);
2142 evg
->eventFlags
= (evg
->eventFlags
& ~KEYBOARD_FLAGSMASK
)
2143 | (flags
& KEYBOARD_FLAGSMASK
);
2144 IOUnlock( driverLock
);
2148 // - _setButtonState:(int)buttons atTime:(int)t
2149 // Update the button state. Generate button events as needed
2151 void IOHIDSystem::_setButtonState(int buttons
,
2152 /* atTime */ AbsoluteTime ts
)
2154 // Magic uber-mouse buttons changed event so we can get all of the buttons...
2155 if(evg
->buttons
^ buttons
)
2158 unsigned long hwButtons
, hwDelta
, temp
;
2160 /* I'd like to keep the event button mapping linear, so
2161 I have to "undo" the LB/RB mouse bit numbering funkiness
2162 before I pass the information down to the app. */
2163 /* Ideally this would all go away if we fixed EV_LB and EV_RB
2164 to be bits 0 and 1 */
2165 hwButtons
= buttons
& ~7; /* Keep everything but bottom 3 bits. */
2166 hwButtons
|= (buttons
& 3) << 1; /* Map bits 01 to 12 */
2167 hwButtons
|= (buttons
& 4) >> 2; /* Map bit 2 back to bit 0 */
2168 temp
= evg
->buttons
^ buttons
;
2169 hwDelta
= temp
& ~7;
2170 hwDelta
|= (temp
& 3) << 1; /* Map bits 01 to 12 */
2171 hwDelta
|= (temp
& 4) >> 2; /* Map bit 2 back to bit 0 */
2173 evData
.compound
.reserved
= 0;
2174 evData
.compound
.subType
= NX_SUBTYPE_AUX_MOUSE_BUTTONS
;
2175 evData
.compound
.misc
.L
[0] = hwDelta
;
2176 evData
.compound
.misc
.L
[1] = hwButtons
;
2178 postEvent( NX_SYSDEFINED
,
2179 /* at */ (Point
*)&evg
->cursorLoc
,
2181 /* withData */ &evData
);
2184 if ((evg
->buttons
& EV_LB
) != (buttons
& EV_LB
))
2186 if (buttons
& EV_LB
)
2188 postEvent( NX_LMOUSEDOWN
,
2189 /* at */ (Point
*)&evg
->cursorLoc
,
2191 /* withData */ NULL
);
2195 postEvent( NX_LMOUSEUP
,
2196 /* at */ (Point
*)&evg
->cursorLoc
,
2198 /* withData */ NULL
);
2200 // After entering initial up/down event, set up
2201 // coalescing state so drags will behave correctly
2202 evg
->dontCoalesce
= evg
->dontWantCoalesce
;
2203 if (evg
->dontCoalesce
)
2204 evg
->eventFlags
|= NX_NONCOALSESCEDMASK
;
2206 evg
->eventFlags
&= ~NX_NONCOALSESCEDMASK
;
2209 if ((evg
->buttons
& EV_RB
) != (buttons
& EV_RB
)) {
2210 if (buttons
& EV_RB
) {
2211 postEvent( NX_RMOUSEDOWN
,
2212 /* at */ (Point
*)&evg
->cursorLoc
,
2214 /* withData */ NULL
);
2216 postEvent( NX_RMOUSEUP
,
2217 /* at */ (Point
*)&evg
->cursorLoc
,
2219 /* withData */ NULL
);
2223 evg
->buttons
= buttons
;
2226 // Sets the cursor position (evg->cursorLoc) to the new
2227 // location. The location is clipped against the cursor pin rectangle,
2228 // mouse moved/dragged events are generated using the given event mask,
2229 // and a mouse-exited event may be generated. The cursor image is
2231 // On entry, the driverLock should be set.
2233 void IOHIDSystem::setCursorPosition(Point
* newLoc
, bool external
)
2235 if ( eventsOpen
== true )
2237 pointerDelta
.x
+= (newLoc
->x
- pointerLoc
.x
);
2238 pointerDelta
.y
+= (newLoc
->y
- pointerLoc
.y
);
2239 pointerLoc
= *newLoc
;
2240 _setCursorPosition(newLoc
, external
);
2245 // This mechanism is used to update the cursor position, possibly generating
2246 // messages to registered frame buffer devices and posting drag, tracking, and
2247 // mouse motion events.
2249 // On entry, the driverLock should be set.
2250 // This can be called from setCursorPosition:(Point *)newLoc to set the
2251 // position by a _IOSetParameterFromIntArray() call, directly from the absolute or
2252 // relative pointer device routines, or on a timed event callback.
2254 void IOHIDSystem::_setCursorPosition(Point
* newLoc
, bool external
)
2256 bool cursorMoved
= true;
2261 if( ev_try_lock(&evg
->cursorSema
) == 0 ) // host using shmem
2263 needSetCursorPosition
= true; // try again later
2264 // scheduleNextPeriodicEvent();
2268 // Past here we hold the cursorSema lock. Make sure the lock is
2269 // cleared before returning or the system will be wedged.
2271 needSetCursorPosition
= false; // We WILL succeed
2273 if (cursorCoupled
|| external
)
2275 UInt32 newScreens
= 0;
2276 SInt32 pinScreen
= -1L;
2278 /* Get mask of screens on which the cursor is present */
2279 EvScreen
*screen
= (EvScreen
*)evScreen
;
2280 for (int i
= 0; i
< screens
; i
++ ) {
2281 if ((screen
[i
].instance
) && PtInRect(newLoc
, screen
[i
].bounds
)) {
2283 newScreens
|= (1 << i
);
2287 if (newScreens
== 0) {
2288 /* At this point cursor has gone off all screens,
2289 just clip it to one of the previous screens. */
2290 newLoc
->x
= (newLoc
->x
< cursorPin
.minx
) ?
2291 cursorPin
.minx
: ((newLoc
->x
> cursorPin
.maxx
) ?
2292 cursorPin
.maxx
: newLoc
->x
);
2293 newLoc
->y
= (newLoc
->y
< cursorPin
.miny
) ?
2294 cursorPin
.miny
: ((newLoc
->y
> cursorPin
.maxy
) ?
2295 cursorPin
.maxy
: newLoc
->y
);
2296 /* regenerate mask for new position */
2297 for (int i
= 0; i
< screens
; i
++ ) {
2298 if ((screen
[i
].instance
) && PtInRect(newLoc
, screen
[i
].bounds
)) {
2300 newScreens
|= (1 << i
);
2305 pointerLoc
= *newLoc
; // Sync up pointer with clipped cursor
2306 /* Catch the no-move case */
2307 if ((evg
->cursorLoc
.x
== newLoc
->x
) && (evg
->cursorLoc
.y
== newLoc
->y
)) {
2308 if ((pointerDelta
.x
== 0) && (pointerDelta
.y
== 0)) {
2309 ev_unlock(&evg
->cursorSema
);
2312 cursorMoved
= false; // mouse moved, but cursor didn't
2314 evg
->cursorLoc
.x
= newLoc
->x
;
2315 evg
->cursorLoc
.y
= newLoc
->y
;
2317 /* If cursor changed screens */
2318 if (newScreens
!= cursorScreens
) {
2319 hideCursor(); /* hide cursor on old screens */
2320 cursorScreens
= newScreens
;
2321 cursorPin
= *(((EvScreen
*)evScreen
)[pinScreen
].bounds
);
2322 cursorPin
.maxx
--; /* Make half-open rectangle */
2324 cursorPinScreen
= pinScreen
;
2327 /* cursor moved on same screens */
2332 /* cursor uncoupled */
2333 pointerLoc
.x
= evg
->cursorLoc
.x
;
2334 pointerLoc
.y
= evg
->cursorLoc
.y
;
2338 clock_get_uptime(&ts
);
2340 /* See if anybody wants the mouse moved or dragged events */
2341 if (evg
->movedMask
) {
2342 if ((evg
->movedMask
&NX_LMOUSEDRAGGEDMASK
)&&(evg
->buttons
& EV_LB
)) {
2343 _postMouseMoveEvent(NX_LMOUSEDRAGGED
, newLoc
, ts
);
2344 } else if ((evg
->movedMask
&NX_RMOUSEDRAGGEDMASK
) && (evg
->buttons
& EV_RB
)) {
2345 _postMouseMoveEvent(NX_RMOUSEDRAGGED
, newLoc
, ts
);
2346 } else if (evg
->movedMask
& NX_MOUSEMOVEDMASK
) {
2347 _postMouseMoveEvent(NX_MOUSEMOVED
, newLoc
, ts
);
2351 /* check new cursor position for leaving evg->mouseRect */
2352 if (cursorMoved
&& evg
->mouseRectValid
&& (!PtInRect(newLoc
, &evg
->mouseRect
)))
2354 if (evg
->mouseRectValid
)
2356 postEvent( NX_MOUSEEXITED
,
2359 /* withData */ NULL
);
2360 evg
->mouseRectValid
= 0;
2363 ev_unlock(&evg
->cursorSema
);
2366 void IOHIDSystem::_postMouseMoveEvent(int what
,
2372 data
.mouseMove
.dx
= pointerDelta
.x
;
2373 data
.mouseMove
.dy
= pointerDelta
.y
;
2378 postEvent(what
, location
, ts
, &data
);
2382 ** IOUserClient methods
2385 IOReturn
IOHIDSystem::newUserClient(task_t
/* owningTask */,
2386 /* withToken */ void * /* security_id */,
2387 /* ofType */ UInt32 type
,
2388 /* client */ IOUserClient
** handler
)
2390 IOUserClient
* newConnect
= 0;
2391 IOReturn err
= kIOReturnNoMemory
;
2393 IOTakeLock( driverLock
);
2396 if( type
== kIOHIDParamConnectType
) {
2398 newConnect
= paramConnect
;
2399 newConnect
->retain();
2400 } else if( eventsOpen
) {
2401 newConnect
= new IOHIDParamUserClient
;
2403 err
= kIOReturnNotOpen
;
2407 } else if( type
== kIOHIDServerConnectType
) {
2408 newConnect
= new IOHIDUserClient
;
2410 err
= kIOReturnUnsupported
;
2415 // initialization is getting out of hand
2417 if( (newConnect
!= paramConnect
) && (
2418 (false == newConnect
->init())
2419 || (false == newConnect
->attach( this ))
2420 || (false == newConnect
->start( this ))
2421 || ((type
== kIOHIDServerConnectType
)
2422 && (err
= evOpen()))
2424 newConnect
->detach( this );
2425 newConnect
->release();
2429 if( type
== kIOHIDParamConnectType
)
2430 paramConnect
= newConnect
;
2431 err
= kIOReturnSuccess
;
2435 IOUnlock( driverLock
);
2437 *handler
= newConnect
;
2442 IOReturn
IOHIDSystem::setEventsEnable(void*p1
,void*,void*,void*,void*,void*)
2444 bool enable
= (bool)p1
;
2447 attachDefaultEventSources();
2448 _resetMouseParameters();
2449 _resetKeyboardParameters();
2451 return( kIOReturnSuccess
);
2454 IOReturn
IOHIDSystem::setCursorEnable(void*p1
,void*,void*,void*,void*,void*)
2456 bool enable
= (bool)p1
;
2457 IOReturn err
= kIOReturnSuccess
;
2459 IOTakeLock( driverLock
);
2460 if ( eventsOpen
== false ) {
2461 IOUnlock( driverLock
);
2462 return( kIOReturnNotOpen
);
2465 if( 0 == screens
) { // Should be at least 1!
2466 IOUnlock( driverLock
);
2467 return( kIOReturnNoDevice
);
2471 if( cursorStarted
) {
2473 cursorEnabled
= resetCursor();
2476 cursorEnabled
= startCursor();
2478 cursorEnabled
= enable
;
2480 cursorCoupled
= cursorEnabled
;
2482 IOUnlock( driverLock
);
2487 IOReturn
IOHIDSystem::extPostEvent(void*p1
,void*,void*,void*,void*,void*)
2489 struct evioLLEvent
* event
= (struct evioLLEvent
*)p1
;
2491 IOTakeLock( driverLock
);
2493 if( event
->setCursor
)
2494 setCursorPosition(&event
->location
, true);
2496 if( event
->setFlags
)
2497 evg
->eventFlags
= (evg
->eventFlags
& ~KEYBOARD_FLAGSMASK
)
2498 | (event
->flags
& KEYBOARD_FLAGSMASK
);
2501 clock_get_uptime(&ts
);
2502 postEvent( event
->type
,
2503 /* at */ &event
->location
,
2505 /* withData */ &event
->data
);
2507 IOUnlock( driverLock
);
2508 return( kIOReturnSuccess
);
2511 IOReturn
IOHIDSystem::extSetMouseLocation(void*p1
,void*,void*,void*,void*,void*)
2513 Point
* loc
= (Point
*)p1
;
2515 IOTakeLock( driverLock
);
2516 setCursorPosition(loc
, true);
2517 IOUnlock( driverLock
);
2518 return( kIOReturnSuccess
);
2521 IOReturn
IOHIDSystem::extGetButtonEventNum(void*p1
,void*p2
,void*,void*,void*,void*)
2523 NXMouseButton button
= (NXMouseButton
)(int)p1
;
2524 int * eventNum
= (int *)p2
;
2525 IOReturn err
= kIOReturnSuccess
;
2527 IOTakeLock( driverLock
);
2530 *eventNum
= leftENum
;
2532 case NX_RightButton
:
2533 *eventNum
= rightENum
;
2536 err
= kIOReturnBadArgument
;
2539 IOUnlock( driverLock
);
2543 bool IOHIDSystem::updateProperties( void )
2545 UInt64 clickTimeThreshNano
;
2546 UInt64 autoDimThresholdNano
;
2547 UInt64 autoDimTimeNano
;
2548 UInt64 idleTimeNano
;
2549 AbsoluteTime time1
, time2
;
2552 absolutetime_to_nanoseconds( clickTimeThresh
, &clickTimeThreshNano
);
2553 absolutetime_to_nanoseconds( autoDimPeriod
, &autoDimThresholdNano
);
2555 clock_get_uptime( &time1
);
2557 autoDimTimeNano
= 0;
2558 // now - (autoDimTime - autoDimPeriod)
2559 SUB_ABSOLUTETIME( &time1
, &autoDimTime
);
2560 ADD_ABSOLUTETIME( &time1
, &autoDimPeriod
);
2561 absolutetime_to_nanoseconds( time1
, &idleTimeNano
);
2563 // autoDimTime - now
2564 time2
= autoDimTime
;
2565 SUB_ABSOLUTETIME( &time2
, &time1
);
2566 absolutetime_to_nanoseconds( time2
, &autoDimTimeNano
);
2567 // autoDimPeriod - (autoDimTime - evg->VertRetraceClock)
2568 time1
= autoDimPeriod
;
2569 SUB_ABSOLUTETIME( &time1
, &time2
);
2570 absolutetime_to_nanoseconds( time1
, &idleTimeNano
);
2573 absolutetime_to_nanoseconds( autoDimPeriod
, &autoDimTimeNano
);
2574 idleTimeNano
= 0; // user is active
2577 ok
= setProperty( kIOHIDClickTimeKey
, &clickTimeThreshNano
,
2579 & setProperty( kIOHIDClickSpaceKey
, &clickSpaceThresh
,
2580 sizeof( clickSpaceThresh
))
2581 & setProperty( kIOHIDAutoDimThresholdKey
, &autoDimThresholdNano
,
2583 & setProperty( kIOHIDAutoDimTimeKey
, &autoDimTimeNano
,
2585 & setProperty( kIOHIDIdleTimeKey
, &idleTimeNano
,
2587 & setProperty( kIOHIDAutoDimStateKey
, &autoDimmed
,
2588 sizeof( autoDimmed
))
2589 & setProperty( kIOHIDBrightnessKey
, &curBright
,
2591 & setProperty( kIOHIDAutoDimBrightnessKey
, &dimmedBrightness
,
2592 sizeof( dimmedBrightness
));
2597 bool IOHIDSystem::serializeProperties( OSSerialize
* s
) const
2599 ((IOHIDSystem
*) this)->updateProperties();
2601 return( super::serializeProperties( s
));
2604 IOReturn
IOHIDSystem::setParamProperties( OSDictionary
* dict
)
2607 IOReturn err
= kIOReturnSuccess
;
2609 IOTakeLock( driverLock
);
2610 if( (data
= OSDynamicCast( OSData
, dict
->getObject(kIOHIDClickTimeKey
))))
2612 UInt64 nano
= *((UInt64
*)(data
->getBytesNoCopy()));
2613 nanoseconds_to_absolutetime(nano
, &clickTimeThresh
);
2615 if( (data
= OSDynamicCast( OSData
,
2616 dict
->getObject(kIOHIDClickSpaceKey
)))) {
2617 clickSpaceThresh
.x
= ((UInt32
*) (data
->getBytesNoCopy()))[EVSIOSCS_X
];
2618 clickSpaceThresh
.y
= ((UInt32
*) (data
->getBytesNoCopy()))[EVSIOSCS_Y
];
2621 if( (data
= OSDynamicCast( OSData
, dict
->getObject(kIOHIDAutoDimThresholdKey
)))) {
2622 AbsoluteTime oldPeriod
= autoDimPeriod
;
2623 UInt64 nano
= *((UInt64
*)(data
->getBytesNoCopy()));
2624 nanoseconds_to_absolutetime(nano
, &autoDimPeriod
);
2625 // autoDimTime = autoDimTime - oldPeriod + autoDimPeriod;
2626 SUB_ABSOLUTETIME( &autoDimTime
, &oldPeriod
);
2627 ADD_ABSOLUTETIME( &autoDimTime
, &autoDimPeriod
);
2630 if( (data
= OSDynamicCast( OSData
, dict
->getObject(kIOHIDAutoDimStateKey
))))
2631 forceAutoDimState( 0 != *((SInt32
*) (data
->getBytesNoCopy())));
2633 if( (data
= OSDynamicCast( OSData
, dict
->getObject(kIOHIDBrightnessKey
))))
2634 setBrightness( *((SInt32
*) (data
->getBytesNoCopy())));
2636 if( (data
= OSDynamicCast( OSData
, dict
->getObject(kIOHIDAutoDimBrightnessKey
))))
2637 setAutoDimBrightness( *((SInt32
*) (data
->getBytesNoCopy())));
2639 IOUnlock( driverLock
);