|
|
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.