|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
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.
11: *
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
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved.
23: *
24: * EventDriver.m - Event System module, ObjC implementation.
25: *
26: * The EventDriver is a pseudo-device driver.
27: *
28: * HISTORY
29: * 31-Mar-92 Mike Paquette at NeXT
30: * Created.
31: * 4 Aug 1993 Erik Kay at NeXT
32: * minor API cleanup
33: */
34:
35: #include <IOKit/system.h>
36: #include <IOKit/assert.h>
37:
38: #include <libkern/c++/OSContainers.h>
39: #include <libkern/c++/OSCollectionIterator.h>
40: #include <IOKit/IOTimerEventSource.h>
41: #include <IOKit/IOCommandQueue.h>
42: #include <IOKit/IOMessage.h>
43: #include <IOKit/IOWorkLoop.h>
44: #include <IOKit/hidsystem/IOHIDevice.h>
45: #include <IOKit/hidsystem/IOHIDShared.h>
46: #include <IOKit/hidsystem/IOHIDSystem.h>
47: #include <IOKit/hidsystem/IOHIKeyboard.h>
48: #include <IOKit/hidsystem/IOHIPointing.h>
49: #include <IOKit/hidsystem/IOHIDParameter.h>
50: #include <IOKit/audio/IOAudioManager.h>
51:
52: #include <IOKit/hidsystem/ev_private.h> /* Per-machine configuration info */
53: #include "IOHIDUserClient.h"
54:
55: bool displayWranglerUp( OSObject *, void *, IOService * );
56:
57: static IOHIDSystem * evInstance = 0;
58:
59:
60: #define xpr_ev_cursor(x, a, b, c, d, e)
61: #define PtInRect(ptp,rp) \
62: ((ptp)->x >= (rp)->minx && (ptp)->x < (rp)->maxx && \
63: (ptp)->y >= (rp)->miny && (ptp)->y < (rp)->maxy)
64:
65:
66:
67: static inline unsigned AbsoluteTimeToTick( AbsoluteTime * ts )
68: {
69: UInt64 nano;
70: absolutetime_to_nanoseconds(*ts, &nano);
71: return( nano >> 24 );
72: }
73:
74: static inline void TickToAbsoluteTime( unsigned tick, AbsoluteTime * ts )
75: {
76: UInt64 nano = ((UInt64) tick) << 24;
77: nanoseconds_to_absolutetime(nano, ts);
78: }
79:
80: #define EV_NS_TO_TICK(ns) AbsoluteTimeToTick(ns)
81: #define EV_TICK_TO_NS(tick,ns) TickToAbsoluteTime(tick,ns)
82:
83:
84: #define super IOService
85: OSDefineMetaClassAndStructors(IOHIDSystem, IOService);
86:
87: /* Return the current instance of the EventDriver, or 0 if none. */
88: IOHIDSystem * IOHIDSystem::instance()
89: {
90: return evInstance;
91: }
92:
93: bool IOHIDSystem::init(OSDictionary * properties)
94: {
95: if (!super::init(properties)) return false;
96:
97: /*
98: * Initialize minimal state.
99: */
100:
101: driverLock = NULL;
102: kickConsumerLock = NULL;
103: evScreen = NULL;
104: timerES = 0;
105: cmdQ = 0;
106: workLoop = 0;
107:
108: return true;
109: }
110:
111: IOHIDSystem * IOHIDSystem::probe(IOService * provider,
112: SInt32 * score)
113: {
114: if (!super::probe(provider,score)) return 0;
115:
116: return this;
117: }
118:
119: /*
120: * Perform reusable initialization actions here.
121: */
122: IOWorkLoop * IOHIDSystem::getWorkLoop() const
123: {
124: return workLoop;
125: }
126:
127: bool IOHIDSystem::start(IOService * provider)
128: {
129: bool iWasStarted = false;
130:
131: do {
132: if (!super::start(provider)) break;
133:
134: evInstance = this;
135:
136: driverLock = IOLockAlloc(); // Event driver data protection lock
137: kickConsumerLock = IOLockAlloc();
138:
139: /* A few details to be set up... */
140: pointerLoc.x = INIT_CURSOR_X;
141: pointerLoc.y = INIT_CURSOR_Y;
142:
143: pointerDelta.x = 0;
144: pointerDelta.y = 0;
145:
146: evScreenSize = sizeof(EvScreen) * 6; // FIX
147: evScreen = (void *) IOMalloc(evScreenSize);
148:
149: if (!driverLock ||
150: !kickConsumerLock ||
151: !evScreenSize) break;
152:
153: IOLockInit(driverLock);
154: IOLockInit(kickConsumerLock);
155: bzero(evScreen, evScreenSize);
156:
157: /*
158: * Start up the work loop
159: */
160: workLoop = IOWorkLoop::workLoop();
161: cmdQ = IOCommandQueue::commandQueue
162: (this, (IOCommandQueueAction) &_doPerformInIOThread );
163: timerES = IOTimerEventSource::timerEventSource
164: (this, (IOTimerEventSource::Action) &_periodicEvents );
165:
166: if (!workLoop || !cmdQ || !timerES)
167: break;
168:
169: if (workLoop->addEventSource(cmdQ) != kIOReturnSuccess
170: || workLoop->addEventSource(timerES) != kIOReturnSuccess)
171: break;
172:
173: publishNotify = addNotification(
174: gIOPublishNotification, serviceMatching("IOHIDevice"),
175: (IOServiceNotificationHandler) &publishNotificationHandler,
176: this, 0 );
177:
178: if (!publishNotify) break;
179:
180: /*
181: * IOHIDSystem serves both as a service and a nub (we lead a double
182: * life). Register ourselves as a nub to kick off matching.
183: */
184:
185: registerService();
186:
187: addNotification( gIOPublishNotification,serviceMatching("IODisplayWrangler"), // look for the display wrangler
188: (IOServiceNotificationHandler)displayWranglerUp, this, 0 );
189:
190: iWasStarted = true;
191: } while(false);
192:
193: if (!iWasStarted) evInstance = 0;
194:
195: return iWasStarted;
196: }
197:
198: // **********************************************************************************
199: // displayWranglerUp
200: //
201: // The Display Wrangler has appeared. We will be calling its
202: // activityTickle method when there is user activity.
203: // **********************************************************************************
204: bool displayWranglerUp( OSObject * us, void * ref, IOService * yourDevice )
205: {
206: if ( yourDevice != NULL ) {
207: ((IOHIDSystem *)us)->displayManager = yourDevice;
208: }
209: return true;
210: }
211:
212:
213: bool IOHIDSystem::publishNotificationHandler(
214: IOHIDSystem * self,
215: void * /* ref */,
216: IOService * newService )
217: {
218: self->attach( newService );
219:
220: // IOTakeLock( self->driverLock);
221: if( self->eventsOpen
222: && OSDynamicCast(IOHIDevice, newService)) {
223: self->registerEventSource((IOHIDevice *) newService);
224: }
225: // IOUnlock( self->driverLock);
226:
227: return true;
228: }
229:
230:
231: /*
232: * Free locally allocated resources, and then ourselves.
233: */
234: void IOHIDSystem::free()
235: {
236: /* Initiates a normal close if open & inited */
237: if( driverLock)
238: evClose();
239:
240: if (evScreen) IOFree( (void *)evScreen, evScreenSize );
241: evScreen = (void *)0;
242: evScreenSize = 0;
243:
244: if (timerES) timerES->release();
245: if (cmdQ) cmdQ->release();
246: if (workLoop) workLoop->release();
247: if (publishNotify) publishNotify->release();
248:
249: /* Release locally allocated resources */
250: if (kickConsumerLock) IOLockFree( kickConsumerLock);
251: if (driverLock) IOLockFree( driverLock);
252:
253: super::free();
254: }
255:
256:
257:
258: /*
259: * Open the driver for business. This call must be made before
260: * any other calls to the Event driver. We can only be opened by
261: * one user at a time.
262: */
263: IOReturn IOHIDSystem::evOpen(void)
264: {
265: IOReturn r = kIOReturnSuccess;
266:
267: if ( evOpenCalled == true )
268: {
269: r = kIOReturnBusy;
270: goto done;
271: }
272: evOpenCalled = true;
273:
274: if (!evInitialized)
275: {
276: evInitialized = true;
277: curBright = EV_SCREEN_MAX_BRIGHTNESS; // FIXME: Set from NVRAM?
278: curVolume = EV_AUDIO_MAX_VOLUME / 2; // FIXME: Set from NVRAM?
279: // Put code here that is to run on the first open ONLY.
280: }
281:
282: done:
283: return r;
284: }
285:
286: IOReturn IOHIDSystem::evClose(void)
287: {
288: IOTakeLock( driverLock);
289: if ( evOpenCalled == false )
290: {
291: IOUnlock( driverLock);
292: return kIOReturnBadArgument;
293: }
294: // Early close actions here
295: forceAutoDimState(false);
296: if( cursorEnabled)
297: hideCursor();
298: cursorStarted = false;
299: cursorEnabled = false;
300: IOUnlock( driverLock);
301:
302: // Release the input devices.
303: detachEventSources();
304:
305: // Tear down the shared memory area if set up
306: // if ( eventsOpen == true )
307: // unmapEventShmem(eventPort);
308:
309: IOTakeLock( driverLock);
310: // Clear screens registry and related data
311: if ( evScreen != (void *)0 )
312: {
313: screens = 0;
314: lastShmemPtr = (void *)0;
315: }
316: // Remove port notification for the eventPort and clear the port out
317: setEventPort(MACH_PORT_NULL);
318: // ipc_port_release_send(event_port);
319:
320: // Clear local state to shutdown
321: evOpenCalled = false;
322: eventsOpen = false;
323:
324: IOUnlock( driverLock);
325:
326: return kIOReturnSuccess;
327: }
328:
329: //
330: // Dispatch state to screens registered with the Event Driver
331: // Pending state changes for a device may be coalesced.
332: //
333: //
334: // On entry, the driverLock should be set.
335: //
336: void IOHIDSystem::evDispatch(int screen,
337: /* command */ EvCmd evcmd)
338: {
339: Point p;
340: EvScreen *esp = &((EvScreen*)evScreen)[screen];
341:
342: if ( !eventsOpen || (screen < 0) )
343: return;
344:
345: p.x = evg->cursorLoc.x; // Copy from shmem.
346: p.y = evg->cursorLoc.y;
347: if ( esp->instance )
348: {
349: switch ( evcmd )
350: {
351: case EVMOVE:
352: esp->instance->moveCursor(&p, evg->frame);
353: break;
354:
355: case EVSHOW:
356: esp->instance->showCursor(&p, evg->frame);
357: break;
358:
359: case EVHIDE:
360: esp->instance->hideCursor();
361: break;
362:
363: case EVLEVEL:
364: esp->instance->setBrightness(currentBrightness());
365: break;
366:
367: case EVNOP:
368: /* lets keep that compiler happy */
369: break;
370: }
371: }
372: }
373:
374: //
375: // Dispatch mechanism for special key press. If a port has been registered,
376: // a message is built to be sent out to that port notifying that the key has
377: // changed state. A level in the range 0-64 is provided for convenience.
378: //
379: void IOHIDSystem::evSpecialKeyMsg(unsigned key,
380: /* direction */ unsigned dir,
381: /* flags */ unsigned f,
382: /* level */ unsigned l)
383: {
384: mach_port_t dst_port;
385: struct evioSpecialKeyMsg *msg;
386:
387: static const struct evioSpecialKeyMsg init_msg =
388: { { MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, // mach3xxx, is the right?
389: MACH_MSG_TYPE_MAKE_SEND), // mach_msg_bits_t msgh_bits;
390: sizeof (struct evioSpecialKeyMsg), // mach_msg_size_t msgh_size;
391: MACH_PORT_NULL, // mach_port_t msgh_remote_port;
392: MACH_PORT_NULL, // mach_port_t msgh_local_port;
393: 0, // mach_msg_size_t msgh_reserved;
394: EV_SPECIAL_KEY_MSG_ID // mach_msg_id_t msgh_id;
395: },
396: 0, /* key */
397: 0, /* direction */
398: 0, /* flags */
399: 0 /* level */
400: };
401:
402: if ( (dst_port = specialKeyPort(key)) == MACH_PORT_NULL )
403: return;
404: msg = (struct evioSpecialKeyMsg *) IOMalloc(
405: sizeof (struct evioSpecialKeyMsg) );
406: if ( msg == NULL )
407: return;
408:
409: // Initialize the message.
410: bcopy( &init_msg, msg, sizeof (struct evioSpecialKeyMsg) );
411: msg->Head.msgh_remote_port = dst_port;
412: msg->key = key;
413: msg->direction = dir;
414: msg->flags = f;
415: msg->level = l;
416:
417: // Send the message out from the I/O thread.
418: sendWorkLoopCommand(this,(IOHIDAction)_performSpecialKeyMsg,(void*)msg);
419: }
420:
421: //
422: // Reset instance variables to their default state for mice/pointers
423: //
424: void IOHIDSystem::_resetMouseParameters()
425: {
426:
427: IOTakeLock( driverLock);
428: if ( eventsOpen == false )
429: {
430: IOUnlock( driverLock);
431: return;
432: }
433: nanoseconds_to_absolutetime( EV_DCLICKTIME, &clickTimeThresh);
434: clickSpaceThresh.x = clickSpaceThresh.y = EV_DCLICKSPACE;
435: AbsoluteTime_to_scalar( &clickTime) = 0;
436: clickLoc.x = clickLoc.y = -EV_DCLICKSPACE;
437: clickState = 1;
438: nanoseconds_to_absolutetime( DAUTODIMPERIOD, &autoDimPeriod);
439: clock_get_uptime( &autoDimTime);
440: ADD_ABSOLUTETIME( &autoDimTime, &autoDimPeriod);
441: dimmedBrightness = DDIMBRIGHTNESS;
442:
443: IOUnlock( driverLock);
444: }
445:
446: void IOHIDSystem::_resetKeyboardParameters()
447: {
448: }
449:
450: /*
451: * Methods exported by the EventDriver.
452: *
453: * The screenRegister protocol is used by frame buffer drivers to register
454: * themselves with the Event Driver. These methods are called in response
455: * to a registerSelf or unregisterSelf message received from the Event
456: * Driver.
457: */
458:
459: int IOHIDSystem::registerScreen(IOGraphicsDevice * instance,
460: /* bounds */ Bounds * bp)
461: // /* shmem */ void ** addr,
462: // /* size */ int * size)
463: {
464: EvScreen *esp;
465:
466:
467:
468: if ( eventsOpen == false )
469: {
470: // *addr = (void *)0;
471: // *size = 0;
472: return -1;
473: }
474: if ( lastShmemPtr == (void *)0 )
475: lastShmemPtr = evs;
476:
477: /* shmemSize and bounds already set */
478: esp = &((EvScreen*)evScreen)[screens];
479: esp->instance = instance;
480: #if 0
481: /* If this driver wants private shmem, then set its shmemPtr */
482: if (esp->shmemSize)
483: esp->shmemPtr = lastShmemPtr;
484: lastShmemPtr += esp->shmemSize;
485: /* Fill in parameters for the requesting instance */
486: *addr = esp->shmemPtr;
487: *size = esp->shmemSize;
488: bcopy( (char *)&esp->bounds, (char *)bp, sizeof (Bounds) );
489: #else
490: esp->bounds = bp;
491: // Update our idea of workSpace bounds
492: if ( bp->minx < workSpace.minx )
493: workSpace.minx = bp->minx;
494: if ( bp->miny < workSpace.miny )
495: workSpace.miny = bp->miny;
496: if ( bp->maxx < workSpace.maxx )
497: workSpace.maxx = bp->maxx;
498: if ( esp->bounds->maxy < workSpace.maxy )
499: workSpace.maxy = bp->maxy;
500: #endif
501: return(SCREENTOKEN + screens++);
502: }
503:
504:
505: void IOHIDSystem::unregisterScreen(int index)
506: {
507: int i;
508:
509: index -= SCREENTOKEN;
510:
511: IOTakeLock( driverLock);
512: if ( eventsOpen == false || index < 0 || index >= screens )
513: {
514: IOUnlock( driverLock);
515: return;
516: }
517: hideCursor();
518: // clear the state for the screen
519: ((EvScreen*)evScreen)[index].instance = 0;
520: // Put the cursor someplace reasonable if it was on the destroyed screen
521: if ( currentScreen == index ) // Uh oh...
522: {
523: for ( i = screens; --i != -1; ) // Pick a new currentScreen
524: {
525: if ( ((EvScreen*)evScreen)[i].instance != 0 )
526: {
527: currentScreen = i;
528: break;
529: }
530: }
531: // This will jump the cursor back on screen
532: setCursorPosition((Point *)&evg->cursorLoc);
533: }
534: else
535: showCursor();
536: IOUnlock( driverLock);
537: }
538:
539: /* Member of EventClient protocol
540: *
541: * Absolute position input devices and some specialized output devices
542: * may need to know the bounding rectangle for all attached displays.
543: * The following method returns a Bounds* for the workspace. Please note
544: * that the bounds are kept as signed values, and that on a multi-display
545: * system the minx and miny values may very well be negative.
546: */
547: Bounds * IOHIDSystem::workspaceBounds()
548: {
549: return &workSpace;
550: }
551:
552: IOReturn IOHIDSystem::createShmem(void* p1, void*, void*, void*, void*, void*)
553: { // IOMethod
554: int shmemVersion = (int)p1;
555: IOByteCount size;
556:
557: if( shmemVersion != kIOHIDCurrentShmemVersion)
558: return( kIOReturnUnsupported);
559:
560: IOTakeLock( driverLock);
561:
562: if( 0 == globalMemory) {
563:
564: // rounded up to avoid mapping nonshared data
565: size = round_page(sizeof(EvOffsets) + sizeof(EvGlobals));
566: globalMemory = IOBufferMemoryDescriptor::withCapacity( size,
567: kIODirectionNone, false);
568:
569: if( !globalMemory) {
570: IOUnlock( driverLock);
571: return( kIOReturnNoMemory );
572: }
573: globalMemory->setLength(size);
574: shmem_addr = (vm_offset_t) globalMemory->getBytesNoCopy();
575: shmem_size = size;
576: }
577:
578: initShmem();
579: IOUnlock( driverLock);
580:
581: return kIOReturnSuccess;
582: }
583:
584:
585: // Initialize the shared memory area.
586: //
587: // On entry, the driverLock should be set.
588: void IOHIDSystem::initShmem()
589: {
590: int i;
591: EvOffsets *eop;
592:
593: pointerLoc.x = INIT_CURSOR_X;
594: pointerLoc.y = INIT_CURSOR_Y;
595:
596: pointerDelta.x = 0;
597: pointerDelta.y = 0;
598:
599: /* top of sharedMem is EvOffsets structure */
600: eop = (EvOffsets *) shmem_addr;
601:
602: bzero( (void*)shmem_addr, shmem_size);
603:
604: /* fill in EvOffsets structure */
605: eop->evGlobalsOffset = sizeof(EvOffsets);
606: eop->evShmemOffset = eop->evGlobalsOffset + sizeof(EvGlobals);
607:
608: /* find pointers to start of globals and private shmem region */
609: evg = (EvGlobals *)((char *)shmem_addr + eop->evGlobalsOffset);
610: evs = (void *)((char *)shmem_addr + eop->evShmemOffset);
611:
612: evg->version = kIOHIDCurrentShmemVersion;
613: evg->structSize = sizeof( EvGlobals);
614:
615: /* Set default wait cursor parameters */
616: evg->waitCursorEnabled = TRUE;
617: evg->globalWaitCursorEnabled = TRUE;
618: evg->waitThreshold = (12 * EV_TICKS_PER_SEC) / 10;
619: clock_interval_to_absolutetime_interval(DefaultWCFrameRate, kNanosecondScale,
620: &waitFrameRate);
621: clock_interval_to_absolutetime_interval(DefaultWCSustain, kNanosecondScale,
622: &waitSustain);
623: AbsoluteTime_to_scalar(&waitSusTime) = 0;
624: AbsoluteTime_to_scalar(&waitFrameTime) = 0;
625:
626: EV_TICK_TO_NS(10,&periodicEventDelta);
627:
628: /* Set up low-level queues */
629: lleqSize = LLEQSIZE;
630: for (i=lleqSize; --i != -1; ) {
631: evg->lleq[i].event.type = 0;
632: #if EVENT_SYSTEM_VERSION > 1
633: AbsoluteTime_to_scalar(&evg->lleq[i].event.time) = 0;
634: #else
635: evg->lleq[i].event.time = 0;
636: #endif
637: evg->lleq[i].event.flags = 0;
638: ev_init_lock(&evg->lleq[i].sema);
639: evg->lleq[i].next = i+1;
640: }
641: evg->LLELast = 0;
642: evg->lleq[lleqSize-1].next = 0;
643: evg->LLEHead =
644: evg->lleq[evg->LLELast].next;
645: evg->LLETail =
646: evg->lleq[evg->LLELast].next;
647: evg->buttons = 0;
648: evg->eNum = INITEVENTNUM;
649: evg->eventFlags = 0;
650:
651: AbsoluteTime ts;
652: unsigned tick;
653: clock_get_uptime( &ts);
654: tick = EV_NS_TO_TICK(&ts);
655: if ( tick == 0 )
656: tick = 1; // No zero values allowed!
657: evg->VertRetraceClock = tick;
658:
659: evg->cursorLoc.x = pointerLoc.x;
660: evg->cursorLoc.y = pointerLoc.y;
661: evg->dontCoalesce = 0;
662: evg->dontWantCoalesce = 0;
663: evg->wantPressure = 0;
664: evg->wantPrecision = 0;
665: evg->mouseRectValid = 0;
666: evg->movedMask = 0;
667: ev_init_lock( &evg->cursorSema );
668: ev_init_lock( &evg->waitCursorSema );
669: // Set eventsOpen last to avoid race conditions.
670: eventsOpen = true;
671: }
672:
673: //
674: // Set the event port. The event port is both an ownership token
675: // and a live port we hold send rights on. The port is owned by our client,
676: // the WindowServer. We arrange to be notified on a port death so that
677: // we can tear down any active resources set up during this session.
678: // An argument of PORT_NULL will cause us to forget any port death
679: // notification that's set up.
680: //
681: // The driverLock should be held on entry.
682: //
683: void IOHIDSystem::setEventPort(mach_port_t port)
684: {
685: static struct _eventMsg init_msg = { {
686: // mach_msg_bits_t msgh_bits;
687: MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,0),
688: // mach_msg_size_t msgh_size;
689: sizeof (struct _eventMsg),
690: // mach_port_t msgh_remote_port;
691: MACH_PORT_NULL,
692: // mach_port_t msgh_local_port;
693: MACH_PORT_NULL,
694: // mach_msg_size_t msgh_reserved;
695: 0,
696: // mach_msg_id_t msgh_id;
697: 0
698: } };
699:
700: if ( eventMsg == NULL )
701: eventMsg = IOMalloc( sizeof (struct _eventMsg) );
702: eventPort = port;
703: // Initialize the events available message.
704: *((struct _eventMsg *)eventMsg) = init_msg;
705:
706: ((struct _eventMsg *)eventMsg)->h.msgh_remote_port = port;
707: }
708:
709: //
710: // Set the port to be used for a special key notification. This could be more
711: // robust about letting ports be set...
712: //
713: IOReturn IOHIDSystem::setSpecialKeyPort(
714: /* keyFlavor */ int special_key,
715: /* keyPort */ mach_port_t key_port)
716: {
717: if ( special_key >= 0 && special_key < NX_NUM_SCANNED_SPECIALKEYS )
718: _specialKeyPort[special_key] = key_port;
719: return kIOReturnSuccess;
720: }
721:
722: mach_port_t IOHIDSystem::specialKeyPort(int special_key)
723: {
724: if ( special_key >= 0 && special_key < NX_NUM_SCANNED_SPECIALKEYS )
725: return _specialKeyPort[special_key];
726: return MACH_PORT_NULL;
727: }
728:
729: //
730: // Helper functions for postEvent
731: //
732: static inline int myAbs(int a) { return(a > 0 ? a : -a); }
733:
734: short IOHIDSystem::getUniqueEventNum()
735: {
736: while (++evg->eNum == NULLEVENTNUM)
737: ; /* sic */
738: return(evg->eNum);
739: }
740:
741: // postEvent
742: //
743: // This routine actually places events in the event queue which is in
744: // the EvGlobals structure. It is called from all parts of the ev
745: // driver.
746: //
747: // On entry, the driverLock should be set.
748: //
749:
750: void IOHIDSystem::postEvent(int what,
751: /* at */ Point * location,
752: /* atTime */ AbsoluteTime ts,
753: /* withData */ NXEventData * myData)
754: {
755: NXEQElement * theHead = (NXEQElement *) &evg->lleq[evg->LLEHead];
756: NXEQElement * theLast = (NXEQElement *) &evg->lleq[evg->LLELast];
757: NXEQElement * theTail = (NXEQElement *) &evg->lleq[evg->LLETail];
758: int wereEvents;
759: unsigned theClock = EV_NS_TO_TICK(&ts);
760:
761: /* Some events affect screen dimming */
762: if (EventCodeMask(what) & NX_UNDIMMASK) {
763: autoDimTime = ts;
764: ADD_ABSOLUTETIME( &autoDimTime, &autoDimPeriod);
765: if (autoDimmed)
766: undoAutoDim();
767: }
768: // Update the PS VertRetraceClock off of the timestamp if it looks sane
769: if ( theClock > (unsigned)evg->VertRetraceClock
770: && theClock < (unsigned)(evg->VertRetraceClock + (20 * EV_TICK_TIME)) )
771: evg->VertRetraceClock = theClock;
772:
773: wereEvents = EventsInQueue();
774:
775: xpr_ev_post("postEvent: what %d, X %d Y %d Q %d, needKick %d\n",
776: what,location->x,location->y,
777: EventsInQueue(), needToKickEventConsumer);
778:
779: if ((!evg->dontCoalesce) /* Coalescing enabled */
780: && (theHead != theTail)
781: && (theLast->event.type == what)
782: && (EventCodeMask(what) & COALESCEEVENTMASK)
783: && ev_try_lock(&theLast->sema)) {
784: /* coalesce events */
785: theLast->event.location.x = location->x;
786: theLast->event.location.y = location->y;
787: #if EVENT_SYSTEM_VERSION > 1
788: absolutetime_to_nanoseconds(ts, &theLast->event.time);
789: #else
790: theLast->event.time = theClock;
791: #endif
792: if (myData != NULL)
793: theLast->event.data = *myData;
794: ev_unlock(&theLast->sema);
795: } else if (theTail->next != evg->LLEHead) {
796: /* store event in tail */
797: theTail->event.type = what;
798: theTail->event.location.x = location->x;
799: theTail->event.location.y = location->y;
800: theTail->event.flags = evg->eventFlags;
801: #if EVENT_SYSTEM_VERSION > 1
802: absolutetime_to_nanoseconds(ts, &theLast->event.time);
803: #else
804: theLast->event.time = theClock;
805: #endif
806: theTail->event.window = 0;
807: if (myData != NULL)
808: theTail->event.data = *myData;
809: switch(what) {
810: case NX_LMOUSEDOWN:
811: theTail->event.data.mouse.eventNum =
812: leftENum = getUniqueEventNum();
813: break;
814: case NX_RMOUSEDOWN:
815: theTail->event.data.mouse.eventNum =
816: rightENum = getUniqueEventNum();
817: break;
818: case NX_LMOUSEUP:
819: theTail->event.data.mouse.eventNum = leftENum;
820: leftENum = NULLEVENTNUM;
821: break;
822: case NX_RMOUSEUP:
823: theTail->event.data.mouse.eventNum = rightENum;
824: rightENum = NULLEVENTNUM;
825: break;
826: }
827: if (EventCodeMask(what) & PRESSUREEVENTMASK) {
828: theTail->event.data.mouse.pressure = lastPressure;
829: }
830: if (EventCodeMask(what) & MOUSEEVENTMASK) { /* Click state */
831: AbsoluteTime delta = ts;
832: SUB_ABSOLUTETIME( &delta, &clickTime);
833: if ((CMP_ABSOLUTETIME(&delta, &clickTimeThresh) <= 0)
834: && (myAbs(location->x - clickLoc.x) <= clickSpaceThresh.x)
835: && (myAbs(location->y - clickLoc.y) <= clickSpaceThresh.y)) {
836: if ((what == NX_LMOUSEDOWN)||(what == NX_RMOUSEDOWN)) {
837: clickTime = ts;
838: theTail->event.data.mouse.click = ++clickState;
839: } else {
840: theTail->event.data.mouse.click = clickState;
841: }
842: } else if ((what == NX_LMOUSEDOWN)||(what == NX_RMOUSEDOWN)) {
843: clickLoc = *location;
844: clickTime = ts;
845: clickState = 1;
846: theTail->event.data.mouse.click = clickState;
847: } else
848: theTail->event.data.mouse.click = 0;
849: }
850: #if PMON
851: pmon_log_event(PMON_SOURCE_EV,
852: KP_EV_POST_EVENT,
853: what,
854: evg->eventFlags,
855: theClock);
856: #endif
857: evg->LLETail = theTail->next;
858: evg->LLELast = theLast->next;
859: if ( ! wereEvents ) // Events available, so wake event consumer
860: kickEventConsumer();
861: }
862: else
863: {
864: /*
865: * if queue is full, ignore event, too hard to take care of all cases
866: */
867: IOLog("%s: postEvent LLEventQueue overflow.\n", getName());
868: kickEventConsumer();
869: #if PMON
870: pmon_log_event( PMON_SOURCE_EV,
871: KP_EV_QUEUE_FULL,
872: what,
873: evg->eventFlags,
874: theClock);
875: #endif
876: }
877: }
878:
879: /*
880: * - kickEventConsumer
881: *
882: * Try to send a message out to let the event consumer know that
883: * there are now events available for consumption.
884: */
885:
886: void IOHIDSystem::kickEventConsumer()
887: {
888: IOReturn err;
889:
890: #if 0
891: _performKickEventConsumer(0)];
892: #else
893:
894: IOTakeLock( kickConsumerLock);
895: xpr_ev_post("kickEventConsumer (need == %d)\n",
896: needToKickEventConsumer,2,3,4,5);
897: if ( needToKickEventConsumer == true )
898: {
899: IOUnlock( kickConsumerLock);
900: return; // Request is already pending
901: }
902: needToKickEventConsumer = true; // Posting a request now
903: IOUnlock( kickConsumerLock);
904:
905: err = sendWorkLoopCommand(this, (IOHIDAction)_performKickEventConsumer,
906: NULL);
907:
908: if( err)
909: IOLog("%s: cmdQ fail %d\n", getName(), err);
910: #endif
911: }
912:
913: /*
914: * Event sources may need to use an I/O thread from time to time.
915: * Rather than have each instance running it's own thread, we provide
916: * a callback mechanism to let all the instances share a common Event I/O
917: * thread running in the IOTask space, and managed by the Event Driver.
918: */
919:
920: IOReturn IOHIDSystem::sendWorkLoopCommand(OSObject * target,
921: IOHIDAction action,
922: void * data)
923: {
924: kern_return_t err;
925:
926: err = cmdQ->enqueueCommand( /* sleep */ true,
927: /* field0 */ target,
928: /* field1 */ (void *) action,
929: /* field2 */ data );
930:
931: return (err == KERN_SUCCESS) ? kIOReturnSuccess : kIOReturnNoMemory;
932: }
933:
934: /*
935: * The following methods are executed from the I/O thread only.
936: */
937:
938: /*
939: * This routine is run within the I/O thread, on demand from the
940: * sendWorkLoopCommand method above. We attempt to dispatch a message
941: * to the specified selector and instance.
942: */
943: void IOHIDSystem::_doPerformInIOThread(void* self,
944: void* target, /* IOCommandQueueAction */
945: void* action,
946: void* data,
947: void* /* unused */)
948: {
949: (*((IOHIDAction)action))((OSObject *)target, data);
950: }
951:
952: /*
953: * This is run in the I/O thread, to perform the actual message send operation.
954: */
955:
956: void IOHIDSystem::_performSpecialKeyMsg(IOHIDSystem * self,
957: struct evioSpecialKeyMsg *msg)
958: /* IOHIDAction */
959: {
960: kern_return_t r;
961:
962: xpr_ev_post("_performSpecialKeyMsg 0x%x\n", msg,2,3,4,5);
963:
964:
965: /* FIXME: Don't block */
966: r = mach_msg_send_from_kernel( &msg->Head, msg->Head.msgh_size);
967:
968: xpr_ev_post("_performSpecialKeyMsg: msg_send() == %d\n",r,2,3,4,5);
969: if ( r != MACH_MSG_SUCCESS )
970: {
971: IOLog("%s: _performSpecialKeyMsg msg_send returned %d\n",
972: self->getName(), r);
973: }
974: if ( r == MACH_SEND_INVALID_DEST ) /* Invalidate the port */
975: {
976: self->setSpecialKeyPort(
977: /* keyFlavor */ msg->key,
978: /* keyPort */ MACH_PORT_NULL);
979: }
980: IOFree( (void *)msg, sizeof (struct evioSpecialKeyMsg) );
981: }
982:
983: /*
984: * This is run in the I/O thread, to perform the actual message send operation.
985: * Note that we perform a non-blocking send. The Event port in the event
986: * consumer has a queue depth of 1 message. Once the consumer picks up that
987: * message, it runs until the event queue is exhausted before trying to read
988: * another message. If a message is pending,there is no need to enqueue a
989: * second one. This also keeps us from blocking the I/O thread in a msg_send
990: * which could result in a deadlock if the consumer were to make a call into
991: * the event driver.
992: */
993: void IOHIDSystem::_performKickEventConsumer(IOHIDSystem * self, void *) /* IOHIDAction */
994: {
995: kern_return_t r;
996: mach_msg_header_t *msgh
997:
998: xpr_ev_post("_performKickEventConsumer\n", 1,2,3,4,5);
999: IOTakeLock( self->kickConsumerLock);
1000: self->needToKickEventConsumer = false; // Request received and processed
1001: IOUnlock( self->kickConsumerLock);
1002:
1003: msgh = (mach_msg_header_t *)self->eventMsg;
1004: if( msgh) {
1005:
1006: r = mach_msg_send_from_kernel( msgh, msgh->msgh_size);
1007: switch ( r )
1008: {
1009: case MACH_SEND_TIMED_OUT:/* Already has a message posted */
1010: case MACH_MSG_SUCCESS: /* Message is posted */
1011: break;
1012: default: /* Log the error */
1013: IOLog("%s: _performKickEventConsumer msg_send returned %d\n",
1014: self->getName(), r);
1015: break;
1016: }
1017: }
1018: }
1019:
1020: //
1021: // Schedule the next periodic event to be run, based on the current state of
1022: // the event system. We have to consider things here such as when the last
1023: // periodic event pass ran, if there is currently any mouse delta accumulated,
1024: // and how long it has been since the last event was consumed by an app (for
1025: // driving the wait cursor).
1026: //
1027: // This code should only be run from the periodicEvents method or
1028: // _setCursorPosition.
1029: //
1030: void IOHIDSystem::scheduleNextPeriodicEvent()
1031: {
1032: if ( AbsoluteTime_to_scalar(&waitFrameTime) != 0)
1033: {
1034: AbsoluteTime time_for_next_run;
1035:
1036: clock_get_uptime(&time_for_next_run);
1037: ADD_ABSOLUTETIME( &time_for_next_run, &periodicEventDelta);
1038:
1039: if (CMP_ABSOLUTETIME( &waitFrameTime, &time_for_next_run) < 0) {
1040: timerES->wakeAtTime(waitFrameTime);
1041: return;
1042: }
1043: }
1044:
1045: timerES->setTimeout(periodicEventDelta);
1046: }
1047:
1048: // Periodic events are driven from this method.
1049: // After taking care of all pending work, the method
1050: // calls scheduleNextPeriodicEvent to compute and set the
1051: // next callout.
1052: //
1053:
1054: void IOHIDSystem::_periodicEvents(IOHIDSystem * self,
1055: IOTimerEventSource *timer)
1056: {
1057: self->periodicEvents(timer);
1058: }
1059:
1060: void IOHIDSystem::periodicEvents(IOTimerEventSource * /* timer */)
1061: /* IOTimerEventSource::Action, IOHIDAction */
1062: {
1063: unsigned int tick;
1064:
1065: // If eventsOpen is false, then the driver shmem is
1066: // no longer valid, and it is in the process of shutting down.
1067: // We should give up without rescheduling.
1068: IOTakeLock( driverLock);
1069: if ( eventsOpen == false )
1070: {
1071: IOUnlock( driverLock);
1072: return;
1073: }
1074:
1075: // Increment event time stamp last
1076: clock_get_uptime(&thisPeriodicRun);
1077:
1078: // Temporary hack til we wean CGS off of VertRetraceClock
1079: tick = EV_NS_TO_TICK(&thisPeriodicRun);
1080: if ( tick == 0 )
1081: tick = 1;
1082: evg->VertRetraceClock = tick;
1083:
1084: // Update cursor position if needed
1085: if ( needSetCursorPosition == true )
1086: _setCursorPosition(&pointerLoc);
1087:
1088: // WAITCURSOR ACTION
1089: if ( ev_try_lock(&evg->waitCursorSema) )
1090: {
1091: if ( ev_try_lock(&evg->cursorSema) )
1092: {
1093: // See if the current context has timed out
1094: if ( (evg->AALastEventSent != evg->AALastEventConsumed)
1095: && ((evg->VertRetraceClock - evg->AALastEventSent >
1096: evg->waitThreshold)))
1097: evg->ctxtTimedOut = TRUE;
1098: // If wait cursor enabled and context timed out, do waitcursor
1099: if (evg->waitCursorEnabled && evg->globalWaitCursorEnabled &&
1100: evg->ctxtTimedOut)
1101: {
1102: /* WAIT CURSOR SHOULD BE ON */
1103: if (!evg->waitCursorUp)
1104: showWaitCursor();
1105: } else
1106: {
1107: /* WAIT CURSOR SHOULD BE OFF */
1108: if (evg->waitCursorUp &&
1109: CMP_ABSOLUTETIME(&waitSusTime, &thisPeriodicRun) <= 0)
1110: hideWaitCursor();
1111: }
1112: /* Animate cursor */
1113: if (evg->waitCursorUp &&
1114: CMP_ABSOLUTETIME(&waitFrameTime, &thisPeriodicRun) <= 0)
1115: animateWaitCursor();
1116: ev_unlock(&evg->cursorSema);
1117: if ((CMP_ABSOLUTETIME(&thisPeriodicRun, &autoDimTime) > 0)
1118: && (!autoDimmed))
1119: doAutoDim();
1120: }
1121: ev_unlock(&evg->waitCursorSema);
1122: }
1123:
1124: scheduleNextPeriodicEvent();
1125: IOUnlock( driverLock);
1126:
1127: return;
1128: }
1129:
1130: //
1131: // Start the cursor system running. Invoked via setParameterInt:EVIOST from
1132: // the Window Server.
1133: //
1134: // At this point, the WindowServer is up, running, and ready to process events.
1135: // We will attach the keyboard and mouse, if none are available yet.
1136: //
1137:
1138: bool IOHIDSystem::resetCursor()
1139: {
1140: volatile Point * p;
1141:
1142: p = &evg->cursorLoc;
1143:
1144: cursorPin = *(((EvScreen*)evScreen)[currentScreen].bounds);
1145: cursorPin.maxx--; // Set the range the cursor is pinned
1146: cursorPin.maxy--; // to for this display [closed range]
1147:
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);
1155:
1156: return( true );
1157: }
1158:
1159: bool IOHIDSystem::startCursor()
1160: {
1161: bool ok;
1162:
1163: if ( (currentScreen = pointToScreen((Point *) &evg->cursorLoc)) < 0 )
1164: return( false);
1165:
1166: resetCursor();
1167: setBrightness();
1168: showCursor();
1169: // attachDefaultEventSources();
1170:
1171: // Start the cursor control callouts
1172: ok = (kIOReturnSuccess ==
1173: sendWorkLoopCommand(this, (IOHIDAction)_periodicEvents, timerES));
1174:
1175: cursorStarted = ok;
1176: return( ok );
1177: }
1178:
1179: //
1180: // Wait Cursor machinery. The driverLock should be held on entry to
1181: // these methods, and the shared memory area must be set up.
1182: //
1183: void IOHIDSystem::showWaitCursor()
1184: {
1185: xpr_ev_cursor("showWaitCursor\n",1,2,3,4,5);
1186: evg->waitCursorUp = true;
1187: changeCursor(EV_WAITCURSOR);
1188: // Set animation and sustain absolute times.
1189:
1190: waitSusTime = waitFrameTime = thisPeriodicRun;
1191: ADD_ABSOLUTETIME( &waitFrameTime, &waitFrameRate);
1192: ADD_ABSOLUTETIME( &waitSusTime, &waitSustain);
1193: }
1194:
1195: void IOHIDSystem::hideWaitCursor()
1196: {
1197: xpr_ev_cursor("hideWaitCursor\n",1,2,3,4,5);
1198: evg->waitCursorUp = false;
1199: changeCursor(EV_STD_CURSOR);
1200: AbsoluteTime_to_scalar(&waitFrameTime) = 0;
1201: AbsoluteTime_to_scalar(&waitSusTime ) = 0;
1202: }
1203:
1204: void IOHIDSystem::animateWaitCursor()
1205: {
1206: xpr_ev_cursor("animateWaitCursor\n",1,2,3,4,5);
1207: changeCursor(evg->frame + 1);
1208: // Set the next animation time.
1209: waitFrameTime = thisPeriodicRun;
1210: ADD_ABSOLUTETIME( &waitFrameTime, &waitFrameRate);
1211: }
1212:
1213: void IOHIDSystem::changeCursor(int frame)
1214: {
1215: evg->frame =
1216: (frame > EV_MAXCURSOR) ? EV_WAITCURSOR : frame;
1217: xpr_ev_cursor("changeCursor %d\n",evg->frame,2,3,4,5);
1218: moveCursor();
1219: }
1220:
1221: //
1222: // Return the screen number in which point p lies. Return -1 if the point
1223: // lies outside of all registered screens.
1224: //
1225: int IOHIDSystem::pointToScreen(Point * p)
1226: {
1227: int i;
1228: EvScreen *screen = (EvScreen *)evScreen;
1229: for (i=screens; --i != -1; ) {
1230: if (screen[i].instance != 0
1231: && (p->x >= screen[i].bounds->minx)
1232: && (p->x < screen[i].bounds->maxx)
1233: && (p->y >= screen[i].bounds->miny)
1234: && (p->y < screen[i].bounds->maxy))
1235: return i;
1236: }
1237: return(-1); /* Cursor outside of known screen boundary */
1238: }
1239:
1240: //
1241: // API used to manipulate screen brightness
1242: //
1243: // On entry to each of these, the driverLock should be set.
1244: //
1245: // Set the current brightness
1246: void IOHIDSystem::setBrightness(int b)
1247: {
1248: if ( b < EV_SCREEN_MIN_BRIGHTNESS )
1249: b = EV_SCREEN_MIN_BRIGHTNESS;
1250: else if ( b > EV_SCREEN_MAX_BRIGHTNESS )
1251: b = EV_SCREEN_MAX_BRIGHTNESS;
1252: if ( b != curBright )
1253: {
1254: curBright = b;
1255: if ( autoDimmed == false )
1256: setBrightness();
1257: }
1258: }
1259:
1260: int IOHIDSystem::brightness()
1261: {
1262: return curBright;
1263: }
1264:
1265: // Set the current brightness
1266: void IOHIDSystem::setAutoDimBrightness(int b)
1267: {
1268: if ( b < EV_SCREEN_MIN_BRIGHTNESS )
1269: b = EV_SCREEN_MIN_BRIGHTNESS;
1270: else if ( b > EV_SCREEN_MAX_BRIGHTNESS )
1271: b = EV_SCREEN_MAX_BRIGHTNESS;
1272: if ( b != dimmedBrightness )
1273: {
1274: dimmedBrightness = b;
1275: if ( autoDimmed == true )
1276: setBrightness();
1277: }
1278: }
1279:
1280: int IOHIDSystem::autoDimBrightness()
1281: {
1282: return dimmedBrightness;
1283: }
1284:
1285: int IOHIDSystem::currentBrightness() // Return the current brightness
1286: {
1287: if ( autoDimmed == true && dimmedBrightness < curBright )
1288: return dimmedBrightness;
1289: else
1290: return curBright;
1291: }
1292:
1293: void IOHIDSystem::doAutoDim()
1294: {
1295: autoDimmed = true;
1296: setBrightness();
1297: }
1298:
1299: // Return display brightness to normal
1300: void IOHIDSystem::undoAutoDim()
1301: {
1302: autoDimmed = false;
1303: setBrightness();
1304: }
1305:
1306: void IOHIDSystem::forceAutoDimState(bool dim)
1307: {
1308: if ( dim == true )
1309: {
1310: if ( autoDimmed == false )
1311: {
1312: if ( eventsOpen == true )
1313: clock_get_uptime( &autoDimTime);
1314: doAutoDim();
1315: }
1316: }
1317: else
1318: {
1319: if ( autoDimmed == true )
1320: {
1321: if ( eventsOpen == true ) {
1322: clock_get_uptime( &autoDimTime);
1323: ADD_ABSOLUTETIME( &autoDimTime, &autoDimPeriod);
1324: }
1325: undoAutoDim();
1326: }
1327: }
1328: }
1329:
1330: //
1331: // API used to manipulate sound volume/attenuation
1332: //
1333: // Set the current brightness.
1334: void IOHIDSystem::setAudioVolume(int v)
1335: {
1336: if ( v < EV_AUDIO_MIN_VOLUME )
1337: v = EV_AUDIO_MIN_VOLUME;
1338: else if ( v > EV_AUDIO_MAX_VOLUME )
1339: v = EV_AUDIO_MAX_VOLUME;
1340: curVolume = v;
1341: }
1342:
1343: //
1344: // Volume set programatically, rather than from keyboard
1345: //
1346: void IOHIDSystem::setUserAudioVolume(int v)
1347: {
1348: setAudioVolume(v);
1349: // Let sound driver know about the change
1350: evSpecialKeyMsg( NX_KEYTYPE_SOUND_UP,
1351: /* direction */ NX_KEYDOWN,
1352: /* flags */ 0,
1353: /* level */ curVolume);
1354: }
1355:
1356: int IOHIDSystem::audioVolume()
1357: {
1358: return curVolume;
1359: }
1360:
1361: //
1362: // API used to drive event state out to attached screens
1363: //
1364: // On entry to each of these, the driverLock should be set.
1365: //
1366: void IOHIDSystem::setBrightness() // Propagate state out to screens
1367: {
1368: int i;
1369: for ( i = 0; i < screens; ++i )
1370: evDispatch(i, /* command */ EVLEVEL);
1371: }
1372: void IOHIDSystem::showCursor()
1373: {
1374: evDispatch(currentScreen, /* command */ EVSHOW);
1375: }
1376: void IOHIDSystem::hideCursor()
1377: {
1378: evDispatch(currentScreen, /* command */ EVHIDE);
1379: }
1380: void IOHIDSystem::moveCursor()
1381: {
1382: evDispatch(currentScreen, /* command */ EVMOVE);
1383: }
1384:
1385: //
1386: // - attachDefaultEventSources
1387: // Attach the default event sources.
1388: //
1389: void IOHIDSystem::attachDefaultEventSources()
1390: {
1391: OSObject * source;
1392: OSIterator * sources;
1393:
1394:
1395: sources = getProviderIterator();
1396:
1397: if (!sources) return;
1398:
1399: while( (source = sources->getNextObject())) {
1400: if (OSDynamicCast(IOHIDevice, source)) {
1401:
1402: registerEventSource((IOHIDevice *)source);
1403: }
1404: }
1405: sources->release();
1406: }
1407:
1408: //
1409: // - detachEventSources
1410: // Detach all event sources
1411: //
1412: void IOHIDSystem::detachEventSources()
1413: {
1414: OSIterator * iter;
1415: IOHIDevice * srcInstance;
1416:
1417: iter = getOpenProviderIterator();
1418: if( iter) {
1419: while( (srcInstance = (IOHIDevice *) iter->getNextObject())) {
1420: #ifdef DEBUG
1421: kprintf("detachEventSource:%s\n", srcInstance->getName());
1422: #endif
1423: srcInstance->close(this);
1424: }
1425: iter->release();
1426: }
1427: }
1428:
1429: //
1430: // EventSrcClient implementation
1431: //
1432:
1433: //
1434: // A new device instance desires to be added to our list.
1435: // Try to get ownership of the device. If we get it, add it to
1436: // the list.
1437: //
1438: bool IOHIDSystem::registerEventSource(IOHIDevice * source)
1439: {
1440: bool success = false;
1441:
1442: #ifdef DEBUG
1443: kprintf("registerEventSource:%s\n", ((IOHIDevice*)source)->getName());
1444: #endif
1445:
1446: if ( OSDynamicCast(IOHIKeyboard, source) ) {
1447: success = ((IOHIKeyboard*)source)->open(this, kIOServiceSeize,
1448: (KeyboardEventAction) _keyboardEvent,
1449: (KeyboardSpecialEventAction) _keyboardSpecialEvent,
1450: (UpdateEventFlagsAction) _updateEventFlags);
1451: } else if ( OSDynamicCast(IOHIPointing, source) ) {
1452: success = ((IOHIPointing*)source)->open(this, kIOServiceSeize,
1453: (RelativePointerEventAction) _relativePointerEvent,
1454: (AbsolutePointerEventAction) _absolutePointerEvent,
1455: (ScrollWheelEventAction) _scrollWheelEvent);
1456: }
1457:
1458: if ( success == false )
1459: IOLog("%s: Sieze of %s failed.\n", getName(), source->getName());
1460:
1461: return success;
1462: }
1463:
1464: IOReturn IOHIDSystem::message(UInt32 type, IOService * provider,
1465: void * argument)
1466: {
1467: IOReturn status = kIOReturnSuccess;
1468:
1469: switch (type)
1470: {
1471: case kIOMessageServiceIsTerminated:
1472: #ifdef DEBUG
1473: kprintf("detachEventSource:%s\n", provider->getName());
1474: #endif
1475: provider->close( this );
1476: case kIOMessageServiceWasClosed:
1477: break;
1478:
1479: default:
1480: status = super::message(type, provider, argument);
1481: break;
1482: }
1483:
1484: return status;
1485: }
1486:
1487: //
1488: // This will scale the point at location in the coordinate system represented by bounds
1489: // to the coordinate system of the current screen.
1490: // This is needed for absolute pointer events that come from devices with different bounds.
1491: //
1492: void IOHIDSystem::_scaleLocationToCurrentScreen(Point *location, Bounds *bounds)
1493: {
1494: Bounds *screenBounds = ((EvScreen*)evScreen)[currentScreen].bounds;
1495:
1496: // We probably also need to look at current screen offsets as well
1497: // but that shouldn't matter until we provide tablets with a way to
1498: // switch screens...
1499: location->x = ((location->x - bounds->minx) * (screenBounds->maxx - screenBounds->minx) / (bounds->maxx - bounds->minx)) + screenBounds->minx;
1500: location->y = ((location->y - bounds->miny) * (screenBounds->maxy - screenBounds->miny) / (bounds->maxy - bounds->miny)) + screenBounds->miny;
1501:
1502: return;
1503: }
1504:
1505:
1506: //
1507: // Process a mouse status change. The driver should sign extend
1508: // it's deltas and perform any bit flipping needed there.
1509: //
1510: // We take the state as presented and turn it into events.
1511: //
1512: void IOHIDSystem::_relativePointerEvent(IOHIDSystem * self,
1513: int buttons,
1514: /* deltaX */ int dx,
1515: /* deltaY */ int dy,
1516: /* atTime */ AbsoluteTime ts)
1517: {
1518: self->relativePointerEvent(buttons, dx, dy, ts);
1519: }
1520:
1521: void IOHIDSystem::relativePointerEvent(int buttons,
1522: /* deltaX */ int dx,
1523: /* deltaY */ int dy,
1524: /* atTime */ AbsoluteTime ts)
1525: {
1526: if ( displayManager != NULL ) // if there is a display manager, tell
1527: displayManager->activityTickle(0,0); // it there is user activity
1528:
1529: IOTakeLock( driverLock);
1530: if ( eventsOpen == false )
1531: {
1532: IOUnlock( driverLock);
1533: return;
1534: }
1535: // Fake up pressure changes from button state changes
1536: if ( (buttons & EV_LB) != (evg->buttons & EV_LB) )
1537: {
1538: if ( buttons & EV_LB )
1539: lastPressure = MAXPRESSURE;
1540: else
1541: lastPressure = MINPRESSURE;
1542: }
1543: _setButtonState(buttons, /* atTime */ ts);
1544:
1545: //IOLog("{%d,%d}\n\033M", dx,dy);
1546: // figure cursor movement
1547: if ( dx || dy )
1548: {
1549: pointerLoc.x += dx;
1550: pointerLoc.y += dy;
1551: pointerDelta.x += dx;
1552: pointerDelta.y += dy;
1553: _setCursorPosition(&pointerLoc);
1554: }
1555: IOUnlock( driverLock);
1556: }
1557:
1558: void IOHIDSystem::_absolutePointerEvent(IOHIDSystem * self,
1559: int buttons,
1560: /* at */ Point * newLoc,
1561: /* withBounds */ Bounds * bounds,
1562: /* inProximity */ bool proximity,
1563: /* withPressure */ int pressure,
1564: /* withAngle */ int stylusAngle,
1565: /* atTime */ AbsoluteTime ts)
1566: {
1567: self->absolutePointerEvent(buttons, newLoc, bounds, proximity,
1568: pressure, stylusAngle, ts);
1569: }
1570:
1571: void IOHIDSystem::absolutePointerEvent(int buttons,
1572: /* at */ Point * newLoc,
1573: /* withBounds */ Bounds * bounds,
1574: /* inProximity */ bool proximity,
1575: /* withPressure */ int pressure,
1576: /* withAngle */ int /* stylusAngle */,
1577: /* atTime */ AbsoluteTime ts)
1578:
1579: {
1580: /*
1581: * If you don't know what to pass for the following fields, pass the
1582: * default values below:
1583: * pressure = MINPRESSURE or MAXPRESSURE
1584: * stylusAngle = 90
1585: */
1586:
1587: NXEventData outData; /* dummy data */
1588:
1589: if ( displayManager != NULL ) { // if there is a display manager, tell
1590: displayManager->activityTickle(0,0); // it there is user activity
1591: }
1592:
1593: IOTakeLock( driverLock);
1594: if ( eventsOpen == false )
1595: {
1596: IOUnlock( driverLock);
1597: return;
1598: }
1599:
1600: lastPressure = pressure;
1601:
1602: _scaleLocationToCurrentScreen(newLoc, bounds);
1603: if ( newLoc->x != pointerLoc.x || newLoc->y != pointerLoc.y )
1604: {
1605: pointerDelta.x += (newLoc->x - pointerLoc.x);
1606: pointerDelta.y += (newLoc->y - pointerLoc.y);
1607: pointerLoc = *newLoc;
1608: _setCursorPosition(&pointerLoc);
1609: }
1610: if ( lastProximity != proximity && proximity == true )
1611: {
1612: evg->eventFlags |= NX_STYLUSPROXIMITYMASK;
1613: bzero( (char *)&outData, sizeof outData );
1614: postEvent( NX_FLAGSCHANGED,
1615: /* at */ (Point *)&pointerLoc,
1616: /* atTime */ ts,
1617: /* withData */ &outData);
1618: }
1619: if ( proximity == true )
1620: _setButtonState(buttons, /* atTime */ ts);
1621: if ( lastProximity != proximity && proximity == false )
1622: {
1623: evg->eventFlags &= ~NX_STYLUSPROXIMITYMASK;
1624: bzero( (char *)&outData, sizeof outData );
1625: postEvent( NX_FLAGSCHANGED,
1626: /* at */ (Point *)&pointerLoc,
1627: /* atTime */ ts,
1628: /* withData */ &outData);
1629: }
1630: lastProximity = proximity;
1631: IOUnlock( driverLock);
1632: }
1633:
1634: void IOHIDSystem::_scrollWheelEvent(IOHIDSystem * self,
1635: short deltaAxis1,
1636: short deltaAxis2,
1637: short deltaAxis3,
1638: /* atTime */ AbsoluteTime ts)
1639: {
1640: self->scrollWheelEvent(deltaAxis1, deltaAxis2, deltaAxis3, ts);
1641: }
1642:
1643: void IOHIDSystem::scrollWheelEvent(short deltaAxis1,
1644: short deltaAxis2,
1645: short deltaAxis3,
1646: /* atTime */ AbsoluteTime ts)
1647:
1648: {
1649: NXEventData wheelData;
1650:
1651: if ((deltaAxis1 == 0) && (deltaAxis2 == 0) && (deltaAxis3 == 0)) {
1652: return;
1653: }
1654:
1655: IOTakeLock( driverLock);
1656: if (!eventsOpen)
1657: {
1658: IOUnlock(driverLock);
1659: return;
1660: }
1661:
1662: bzero((char *)&wheelData, sizeof wheelData);
1663: wheelData.scrollWheel.deltaAxis1 = deltaAxis1;
1664: wheelData.scrollWheel.deltaAxis2 = deltaAxis2;
1665: wheelData.scrollWheel.deltaAxis3 = deltaAxis3;
1666:
1667: postEvent( NX_SCROLLWHEELMOVED,
1668: /* at */ (Point *)&evg->cursorLoc,
1669: /* atTime */ ts,
1670: /* withData */ &wheelData);
1671:
1672: IOUnlock(driverLock);
1673: return;
1674: }
1675:
1676: void IOHIDSystem::_tabletEvent(IOHIDSystem *self,
1677: NXEventData *tabletData,
1678: AbsoluteTime ts)
1679: {
1680: self->tabletEvent(tabletData, ts);
1681: }
1682:
1683: void IOHIDSystem::tabletEvent(NXEventData *tabletData,
1684: AbsoluteTime ts)
1685: {
1686: IOTakeLock(driverLock);
1687:
1688: if (eventsOpen) {
1689: postEvent(NX_TABLETPOINTER,
1690: (Point *)&evg->cursorLoc,
1691: ts,
1692: tabletData);
1693: }
1694:
1695: IOUnlock(driverLock);
1696:
1697: return;
1698: }
1699:
1700: void IOHIDSystem::_proximityEvent(IOHIDSystem *self,
1701: NXEventData *proximityData,
1702: AbsoluteTime ts)
1703: {
1704: self->proximityEvent(proximityData, ts);
1705: }
1706:
1707: void IOHIDSystem::proximityEvent(NXEventData *proximityData,
1708: AbsoluteTime ts)
1709: {
1710: IOTakeLock(driverLock);
1711:
1712: if (eventsOpen) {
1713: postEvent(NX_TABLETPROXIMITY,
1714: (Point *)&evg->cursorLoc,
1715: ts,
1716: proximityData);
1717: }
1718:
1719: IOUnlock(driverLock);
1720:
1721: return;
1722: }
1723:
1724: //
1725: // Process a keyboard state change.
1726: //
1727: void IOHIDSystem::_keyboardEvent(IOHIDSystem * self,
1728: unsigned eventType,
1729: /* flags */ unsigned flags,
1730: /* keyCode */ unsigned key,
1731: /* charCode */ unsigned charCode,
1732: /* charSet */ unsigned charSet,
1733: /* originalCharCode */ unsigned origCharCode,
1734: /* originalCharSet */ unsigned origCharSet,
1735: /* repeat */ bool repeat,
1736: /* atTime */ AbsoluteTime ts)
1737: {
1738: self->keyboardEvent(eventType, flags, key, charCode, charSet,
1739: origCharCode, origCharSet, repeat, ts);
1740: }
1741:
1742: void IOHIDSystem::keyboardEvent(unsigned eventType,
1743: /* flags */ unsigned flags,
1744: /* keyCode */ unsigned key,
1745: /* charCode */ unsigned charCode,
1746: /* charSet */ unsigned charSet,
1747: /* originalCharCode */ unsigned origCharCode,
1748: /* originalCharSet */ unsigned origCharSet,
1749: /* repeat */ bool repeat,
1750: /* atTime */ AbsoluteTime ts)
1751: {
1752: NXEventData outData;
1753:
1754: if ( displayManager != NULL ) { // if there is a display manager, tell
1755: displayManager->activityTickle(0,0); // it there is user activity
1756: }
1757:
1758: outData.key.repeat = repeat;
1759: outData.key.keyCode = key;
1760: outData.key.charSet = charSet;
1761: outData.key.charCode = charCode;
1762: outData.key.origCharSet = origCharSet;
1763: outData.key.origCharCode = origCharCode;
1764:
1765: IOTakeLock( driverLock);
1766: if ( eventsOpen == false )
1767: {
1768: IOUnlock( driverLock);
1769: return;
1770: }
1771: evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
1772: | (flags & KEYBOARD_FLAGSMASK);
1773:
1774: postEvent( eventType,
1775: /* at */ (Point *)&pointerLoc,
1776: /* atTime */ ts,
1777: /* withData */ &outData);
1778:
1779: IOUnlock( driverLock);
1780: }
1781:
1782: void IOHIDSystem::_keyboardSpecialEvent(IOHIDSystem * self,
1783: unsigned eventType,
1784: /* flags */ unsigned flags,
1785: /* keyCode */ unsigned key,
1786: /* specialty */ unsigned flavor,
1787: /* atTime */ AbsoluteTime ts)
1788: {
1789: self->keyboardSpecialEvent(eventType, flags, key, flavor, ts);
1790: }
1791:
1792:
1793: void IOHIDSystem::keyboardSpecialEvent(unsigned eventType,
1794: /* flags */ unsigned flags,
1795: /* keyCode */ unsigned /* key */,
1796: /* specialty */ unsigned flavor,
1797: /* atTime */ AbsoluteTime ts)
1798: {
1799: NXEventData outData;
1800: int level = -1;
1801:
1802: bzero( (void *)&outData, sizeof outData );
1803:
1804: IOTakeLock( driverLock);
1805: if ( eventsOpen == false )
1806: {
1807: IOUnlock( driverLock);
1808: return;
1809: }
1810: // Update flags.
1811: evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
1812: | (flags & KEYBOARD_FLAGSMASK);
1813: // Most of these keys don't generate events. Forcibly undo autodim.
1814: if ( autoDimmed == true )
1815: forceAutoDimState(false);
1816: if ( eventType == NX_KEYDOWN )
1817: {
1818: switch ( flavor )
1819: {
1820: case NX_KEYTYPE_SOUND_UP:
1821: if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 ) {
1822: level = IOAudioManager::sharedInstance()->incrementMasterVolume();
1823: }
1824: break;
1825: case NX_KEYTYPE_SOUND_DOWN:
1826: if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 ) {
1827: level = IOAudioManager::sharedInstance()->decrementMasterVolume();
1828: }
1829: break;
1830: case NX_KEYTYPE_MUTE:
1831: if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 ) {
1832: level = IOAudioManager::sharedInstance()->toggleMasterMute();
1833: }
1834: break;
1835: case NX_KEYTYPE_BRIGHTNESS_UP:
1836: if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 )
1837: setBrightness(brightness() + 1);
1838: level = brightness();
1839: break;
1840: case NX_KEYTYPE_BRIGHTNESS_DOWN:
1841: if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 )
1842: setBrightness(brightness() - 1);
1843: level = brightness();
1844: break;
1845: case NX_POWER_KEY:
1846: outData.compound.subType = 1;
1847: postEvent( NX_SYSDEFINED,
1848: /* at */ (Point *)&pointerLoc,
1849: /* atTime */ ts,
1850: /* withData */ &outData);
1851: break;
1852: }
1853: }
1854: #if 0 /* So far, nothing to do on keyup */
1855: else if ( eventType == NX_KEYUP )
1856: {
1857: switch ( flavor )
1858: {
1859: case NX_KEYTYPE_SOUND_UP:
1860: break;
1861: case NX_KEYTYPE_SOUND_DOWN:
1862: break;
1863: case NX_KEYTYPE_BRIGHTNESS_UP:
1864: break;
1865: case NX_KEYTYPE_BRIGHTNESS_DOWN:
1866: break;
1867: case NX_POWER_KEY:
1868: break;
1869: }
1870: }
1871: #endif
1872: IOUnlock( driverLock);
1873: if ( level != -1 ) // An interesting special key event occurred
1874: {
1875: evSpecialKeyMsg( flavor,
1876: /* direction */ eventType,
1877: /* flags */ flags,
1878: /* level */ level);
1879: }
1880: }
1881:
1882: /*
1883: * Update current event flags. Restricted to keyboard flags only, this
1884: * method is used to silently update the flags state for keys which both
1885: * generate characters and flag changes. The specs say we don't generate
1886: * a flags-changed event for such keys. This method is also used to clear
1887: * the keyboard flags on a keyboard subsystem reset.
1888: */
1889: void IOHIDSystem::_updateEventFlags(IOHIDSystem * self, unsigned flags)
1890: {
1891: self->updateEventFlags(flags);
1892: }
1893:
1894: void IOHIDSystem::updateEventFlags(unsigned flags)
1895: {
1896: IOTakeLock( driverLock);
1897: if ( eventsOpen )
1898: evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
1899: | (flags & KEYBOARD_FLAGSMASK);
1900: IOUnlock( driverLock);
1901: }
1902:
1903: //
1904: // - _setButtonState:(int)buttons atTime:(int)t
1905: // Update the button state. Generate button events as needed
1906: //
1907: void IOHIDSystem::_setButtonState(int buttons,
1908: /* atTime */ AbsoluteTime ts)
1909: {
1910: if ((evg->buttons & EV_LB) != (buttons & EV_LB))
1911: {
1912: if (buttons & EV_LB)
1913: {
1914: postEvent( NX_LMOUSEDOWN,
1915: /* at */ (Point *)&evg->cursorLoc,
1916: /* atTime */ ts,
1917: /* withData */ NULL);
1918: evg->buttons |= EV_LB;
1919: }
1920: else
1921: {
1922: postEvent( NX_LMOUSEUP,
1923: /* at */ (Point *)&evg->cursorLoc,
1924: /* atTime */ ts,
1925: /* withData */ NULL);
1926: evg->buttons &= ~EV_LB;
1927: }
1928: // After entering initial up/down event, set up
1929: // coalescing state so drags will behave correctly
1930: evg->dontCoalesce = evg->dontWantCoalesce;
1931: if (evg->dontCoalesce)
1932: evg->eventFlags |= NX_NONCOALSESCEDMASK;
1933: else
1934: evg->eventFlags &= ~NX_NONCOALSESCEDMASK;
1935: }
1936:
1937: if ((evg->buttons & EV_RB) != (buttons & EV_RB)) {
1938: if (buttons & EV_RB) {
1939: postEvent( NX_RMOUSEDOWN,
1940: /* at */ (Point *)&evg->cursorLoc,
1941: /* atTime */ ts,
1942: /* withData */ NULL);
1943: evg->buttons |= EV_RB;
1944: } else {
1945: postEvent( NX_RMOUSEUP,
1946: /* at */ (Point *)&evg->cursorLoc,
1947: /* atTime */ ts,
1948: /* withData */ NULL);
1949: evg->buttons &= ~EV_RB;
1950: }
1951: }
1952: }
1953: //
1954: // Sets the cursor position (evg->cursorLoc) to the new
1955: // location. The location is clipped against the cursor pin rectangle,
1956: // mouse moved/dragged events are generated using the given event mask,
1957: // and a mouse-exited event may be generated. The cursor image is
1958: // moved.
1959: // On entry, the driverLock should be set.
1960: //
1961: void IOHIDSystem::setCursorPosition(Point * newLoc)
1962: {
1963: if ( eventsOpen == true )
1964: {
1965: pointerDelta.x += (newLoc->x - pointerLoc.x);
1966: pointerDelta.y += (newLoc->y - pointerLoc.y);
1967: pointerLoc = *newLoc;
1968: _setCursorPosition(newLoc);
1969: }
1970: }
1971:
1972: //
1973: // This mechanism is used to update the cursor position, possibly generating
1974: // messages to registered frame buffer devices and posting drag, tracking, and
1975: // mouse motion events.
1976: //
1977: // On entry, the driverLock should be set.
1978: // This can be called from setCursorPosition:(Point *)newLoc to set the
1979: // position by a _IOSetParameterFromIntArray() call, directly from the absolute or
1980: // relative pointer device routines, or on a timed event callback.
1981: //
1982: void IOHIDSystem::_setCursorPosition(Point * newLoc)
1983: {
1984: int newScreen = -1;
1985:
1986: if (!screens || !cursorEnabled)
1987: return;
1988:
1989: if ( ev_try_lock(&evg->cursorSema) == 0 ) // host using shmem
1990: {
1991: needSetCursorPosition = true; // try again later
1992: // scheduleNextPeriodicEvent();
1993: return;
1994: }
1995: // Past here we hold the cursorSema lock. Make sure the lock is
1996: // cleared before returning or the system will be wedged.
1997:
1998: needSetCursorPosition = false; // We WILL succeed
1999:
2000: /* Check to see if cursor ventured outside of current screen bounds
2001: before worrying about which screen it may have gone to. */
2002:
2003: if (!PtInRect(newLoc, ((EvScreen*)evScreen)[currentScreen].bounds)) {
2004: /* At this point cursor has gone off screen. Check to see if moved
2005: to another screen. If not, just clip it to current screen. */
2006:
2007: if ((newScreen = pointToScreen(newLoc)) < 0) {
2008: /* Pin new cursor position to cursorPin rect */
2009: newLoc->x = (newLoc->x < cursorPin.minx) ?
2010: cursorPin.minx : ((newLoc->x > cursorPin.maxx) ?
2011: cursorPin.maxx : newLoc->x);
2012: newLoc->y = (newLoc->y < cursorPin.miny) ?
2013: cursorPin.miny : ((newLoc->y > cursorPin.maxy) ?
2014: cursorPin.maxy : newLoc->y);
2015: }
2016: }
2017:
2018: pointerLoc = *newLoc; // Sync up pointer with clipped cursor
2019: /* Catch the no-move case */
2020: if (evg->cursorLoc.x == newLoc->x && evg->cursorLoc.y == newLoc->y)
2021: {
2022: ev_unlock(&evg->cursorSema);
2023: return;
2024: }
2025: evg->cursorLoc.x = newLoc->x;
2026: evg->cursorLoc.y = newLoc->y;
2027:
2028: /* If newScreen is zero or positive, then cursor crossed screens */
2029: if (newScreen >= 0) {
2030: /* cursor changed screens */
2031: hideCursor(); /* hide cursor on old screen */
2032: currentScreen = newScreen;
2033: cursorPin = *(((EvScreen*)evScreen)[currentScreen].bounds);
2034: cursorPin.maxx--; /* Make half-open rectangle */
2035: cursorPin.maxy--;
2036: showCursor();
2037: } else {
2038: /* cursor moved on same screen */
2039: moveCursor();
2040: }
2041:
2042: AbsoluteTime ts;
2043: clock_get_uptime(&ts);
2044:
2045: /* See if anybody wants the mouse moved or dragged events */
2046: if (evg->movedMask) {
2047: if ((evg->movedMask&NX_LMOUSEDRAGGEDMASK)&&(evg->buttons& EV_LB))
2048: _postMouseMoveEvent(NX_LMOUSEDRAGGED, newLoc, ts);
2049: else
2050: if ((evg->movedMask&NX_RMOUSEDRAGGEDMASK) &&
2051: (evg->buttons & EV_RB))
2052: _postMouseMoveEvent(NX_RMOUSEDRAGGED, newLoc, ts);
2053: else
2054: if (evg->movedMask & NX_MOUSEMOVEDMASK)
2055: _postMouseMoveEvent(NX_MOUSEMOVED, newLoc, ts);
2056: }
2057:
2058: /* check new cursor position for leaving evg->mouseRect */
2059: if (evg->mouseRectValid && (!PtInRect(newLoc, &evg->mouseRect)))
2060: {
2061: if (evg->mouseRectValid)
2062: {
2063: postEvent( NX_MOUSEEXITED,
2064: /* at */ newLoc,
2065: /* atTime */ ts,
2066: /* withData */ NULL);
2067: evg->mouseRectValid = 0;
2068: }
2069: }
2070: ev_unlock(&evg->cursorSema);
2071: }
2072:
2073: void IOHIDSystem::_postMouseMoveEvent(int what,
2074: Point * location,
2075: AbsoluteTime ts)
2076: {
2077: NXEventData data;
2078:
2079: #if EVENT_SYSTEM_VERSION > 1
2080: data.mouseMove.dx = pointerDelta.x;
2081: data.mouseMove.dy = pointerDelta.y;
2082: #endif
2083: pointerDelta.x = 0;
2084: pointerDelta.y = 0;
2085:
2086: postEvent(what, location, ts, &data);
2087: }
2088:
2089: /**
2090: ** IOUserClient methods
2091: **/
2092:
2093: IOReturn IOHIDSystem::newUserClient(task_t /* owningTask */,
2094: /* withToken */ void * /* security_id */,
2095: /* ofType */ UInt32 type,
2096: /* client */ IOUserClient ** handler)
2097: {
2098: IOUserClient * newConnect = 0;
2099: IOReturn err = kIOReturnNoMemory;
2100:
2101: IOTakeLock( driverLock);
2102:
2103: do {
2104: if( type == kIOHIDParamConnectType) {
2105: if( paramConnect) {
2106: newConnect = paramConnect;
2107: newConnect->retain();
2108: } else if( eventsOpen) {
2109: newConnect = new IOHIDParamUserClient;
2110: } else {
2111: err = kIOReturnNotOpen;
2112: continue;
2113: }
2114:
2115: } else if( type == kIOHIDServerConnectType) {
2116: newConnect = new IOHIDUserClient;
2117: } else
2118: err = kIOReturnUnsupported;
2119:
2120: if( !newConnect)
2121: continue;
2122:
2123: // initialization is getting out of hand
2124:
2125: if( (newConnect != paramConnect) && (
2126: (false == newConnect->init())
2127: || (false == newConnect->attach( this ))
2128: || (false == newConnect->start( this ))
2129: || ((type == kIOHIDServerConnectType)
2130: && (err = evOpen()))
2131: )) {
2132: newConnect->detach( this );
2133: newConnect->release();
2134: newConnect = 0;
2135: continue;
2136: }
2137: if( type == kIOHIDParamConnectType)
2138: paramConnect = newConnect;
2139: err = kIOReturnSuccess;
2140:
2141: } while( false );
2142:
2143: IOUnlock( driverLock);
2144:
2145: *handler = newConnect;
2146: return( err );
2147: }
2148:
2149:
2150: IOReturn IOHIDSystem::setEventsEnable(void*p1,void*,void*,void*,void*,void*)
2151: { // IOMethod
2152: bool enable = (bool)p1;
2153:
2154: if( enable) {
2155: attachDefaultEventSources();
2156: _resetMouseParameters();
2157: _resetKeyboardParameters();
2158: }
2159: return( kIOReturnSuccess);
2160: }
2161:
2162: IOReturn IOHIDSystem::setCursorEnable(void*p1,void*,void*,void*,void*,void*)
2163: { // IOMethod
2164: bool enable = (bool)p1;
2165: IOReturn err = kIOReturnSuccess;
2166:
2167: IOTakeLock( driverLock);
2168: if ( eventsOpen == false ) {
2169: IOUnlock( driverLock);
2170: return( kIOReturnNotOpen );
2171: }
2172:
2173: if( 0 == screens) { // Should be at least 1!
2174: IOUnlock( driverLock);
2175: return( kIOReturnNoDevice );
2176: }
2177:
2178: if( enable) {
2179: if( cursorStarted)
2180: cursorEnabled = resetCursor();
2181: else
2182: cursorEnabled = startCursor();
2183: } else
2184: cursorEnabled = enable;
2185:
2186: IOUnlock( driverLock);
2187:
2188: return( err);
2189: }
2190:
2191: IOReturn IOHIDSystem::extPostEvent(void*p1,void*,void*,void*,void*,void*)
2192: { // IOMethod
2193: struct evioLLEvent * event = (struct evioLLEvent *)p1;
2194:
2195: IOTakeLock( driverLock);
2196:
2197: if( event->setCursor)
2198: setCursorPosition(&event->location);
2199:
2200: if( event->setFlags)
2201: evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK)
2202: | (event->flags & KEYBOARD_FLAGSMASK);
2203:
2204: AbsoluteTime ts;
2205: clock_get_uptime(&ts);
2206: postEvent( event->type,
2207: /* at */ &event->location,
2208: /* atTime */ ts,
2209: /* withData */ &event->data);
2210:
2211: IOUnlock( driverLock);
2212: return( kIOReturnSuccess);
2213: }
2214:
2215: IOReturn IOHIDSystem::extSetMouseLocation(void*p1,void*,void*,void*,void*,void*)
2216: { // IOMethod
2217: Point * loc = (Point *)p1;
2218:
2219: IOTakeLock( driverLock);
2220: setCursorPosition(loc);
2221: IOUnlock( driverLock);
2222: return( kIOReturnSuccess);
2223: }
2224:
2225: IOReturn IOHIDSystem::extGetButtonEventNum(void*p1,void*p2,void*,void*,void*,void*)
2226: { // IOMethod
2227: NXMouseButton button = (NXMouseButton)(int)p1;
2228: int * eventNum = (int *)p2;
2229: IOReturn err = kIOReturnSuccess;
2230:
2231: IOTakeLock( driverLock);
2232: switch( button) {
2233: case NX_LeftButton:
2234: *eventNum = leftENum;
2235: break;
2236: case NX_RightButton:
2237: *eventNum = rightENum;
2238: break;
2239: default:
2240: err = kIOReturnBadArgument;
2241: }
2242:
2243: IOUnlock( driverLock);
2244: return( err);
2245: }
2246:
2247: bool IOHIDSystem::updateProperties( void )
2248: {
2249: UInt64 clickTimeThreshNano;
2250: UInt64 autoDimThresholdNano;
2251: UInt64 autoDimTimeNano;
2252: UInt64 idleTimeNano;
2253: AbsoluteTime time1, time2;
2254: bool ok;
2255:
2256: absolutetime_to_nanoseconds( clickTimeThresh, &clickTimeThreshNano);
2257: absolutetime_to_nanoseconds( autoDimPeriod, &autoDimThresholdNano);
2258: if( eventsOpen) {
2259: clock_get_uptime( &time1);
2260: if( autoDimmed) {
2261: autoDimTimeNano = 0;
2262: // now - (autoDimTime - autoDimPeriod)
2263: SUB_ABSOLUTETIME( &time1, &autoDimTime);
2264: ADD_ABSOLUTETIME( &time1, &autoDimPeriod);
2265: absolutetime_to_nanoseconds( time1, &idleTimeNano);
2266: } else {
2267: // autoDimTime - now
2268: time2 = autoDimTime;
2269: SUB_ABSOLUTETIME( &time2, &time1);
2270: absolutetime_to_nanoseconds( time2, &autoDimTimeNano);
2271: // autoDimPeriod - (autoDimTime - evg->VertRetraceClock)
2272: time1 = autoDimPeriod;
2273: SUB_ABSOLUTETIME( &time1, &time2);
2274: absolutetime_to_nanoseconds( time1, &idleTimeNano);
2275: }
2276: } else {
2277: absolutetime_to_nanoseconds( autoDimPeriod, &autoDimTimeNano);
2278: idleTimeNano = 0; // user is active
2279: }
2280:
2281: ok = setProperty( kIOHIDClickTimeKey, &clickTimeThreshNano,
2282: sizeof( UInt64))
2283: & setProperty( kIOHIDClickSpaceKey, &clickSpaceThresh,
2284: sizeof( clickSpaceThresh))
2285: & setProperty( kIOHIDAutoDimThresholdKey, &autoDimThresholdNano,
2286: sizeof( UInt64))
2287: & setProperty( kIOHIDAutoDimTimeKey, &autoDimTimeNano,
2288: sizeof( UInt64))
2289: & setProperty( kIOHIDIdleTimeKey, &idleTimeNano,
2290: sizeof( UInt64))
2291: & setProperty( kIOHIDAutoDimStateKey, &autoDimmed,
2292: sizeof( autoDimmed))
2293: & setProperty( kIOHIDBrightnessKey, &curBright,
2294: sizeof( curBright))
2295: & setProperty( kIOHIDAutoDimBrightnessKey, &dimmedBrightness,
2296: sizeof( dimmedBrightness));
2297:
2298: return( ok );
2299: }
2300:
2301: bool IOHIDSystem::serializeProperties( OSSerialize * s ) const
2302: {
2303: ((IOHIDSystem *) this)->updateProperties();
2304:
2305: return( super::serializeProperties( s ));
2306: }
2307:
2308: IOReturn IOHIDSystem::setParamProperties( OSDictionary * dict )
2309: {
2310: OSData * data;
2311: IOReturn err = kIOReturnSuccess;
2312:
2313: IOTakeLock( driverLock);
2314: if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDClickTimeKey))))
2315: {
2316: UInt64 nano = *((UInt64 *)(data->getBytesNoCopy()));
2317: nanoseconds_to_absolutetime(nano, &clickTimeThresh);
2318: }
2319: if( (data = OSDynamicCast( OSData,
2320: dict->getObject(kIOHIDClickSpaceKey)))) {
2321: clickSpaceThresh.x = ((UInt32 *) (data->getBytesNoCopy()))[EVSIOSCS_X];
2322: clickSpaceThresh.y = ((UInt32 *) (data->getBytesNoCopy()))[EVSIOSCS_Y];
2323: }
2324:
2325: if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDAutoDimThresholdKey)))) {
2326: AbsoluteTime oldPeriod = autoDimPeriod;
2327: UInt64 nano = *((UInt64 *)(data->getBytesNoCopy()));
2328: nanoseconds_to_absolutetime(nano, &autoDimPeriod);
2329: // autoDimTime = autoDimTime - oldPeriod + autoDimPeriod;
2330: SUB_ABSOLUTETIME( &autoDimTime, &oldPeriod);
2331: ADD_ABSOLUTETIME( &autoDimTime, &autoDimPeriod);
2332: }
2333:
2334: if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDAutoDimStateKey))))
2335: forceAutoDimState( 0 != *((SInt32 *) (data->getBytesNoCopy())));
2336:
2337: if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDBrightnessKey))))
2338: setBrightness( *((SInt32 *) (data->getBytesNoCopy())));
2339:
2340: if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDAutoDimBrightnessKey))))
2341: setAutoDimBrightness( *((SInt32 *) (data->getBytesNoCopy())));
2342:
2343: IOUnlock( driverLock);
2344:
2345: return( err );
2346: }
2347:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.