1/* 2 * 3 * @APPLE_LICENSE_HEADER_START@ 4 * 5 * Copyright (c) 1999-2009 Apple Computer, Inc. All Rights Reserved. 6 * 7 * This file contains Original Code and/or Modifications of Original Code 8 * as defined in and that are subject to the Apple Public Source License 9 * Version 2.0 (the 'License'). You may not use this file except in 10 * compliance with the License. Please obtain a copy of the License at 11 * http://www.opensource.apple.com/apsl/ and read it before using this 12 * file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 19 * Please see the License for the specific language governing rights and 20 * limitations under the License. 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24 25#include "IOHIDEventSystem.h" 26#include "IOHIDWorkLoop.h" 27 28 29typedef struct _EventServiceInfo 30{ 31 IOHIDEventService * service; 32 33} EventServiceInfo, * EventServiceInfoRef; 34 35typedef struct _HIDEventArgs 36{ 37 void * refCon; 38 AbsoluteTime timeStamp; 39 UInt32 eventCount; 40 IOHIDEvent * events; 41 IOOptionBits options; 42} HIDEventArgs, * HIDEventArgsRef; 43 44 45#define super IOService 46OSDefineMetaClassAndStructors(IOHIDEventSystem, IOService) 47 48 49//==================================================================================================== 50// IOHIDEventService::init 51//==================================================================================================== 52bool IOHIDEventSystem::init(OSDictionary * properties) 53{ 54 if ( super::init(properties) == false ) 55 return false; 56 57 _eventServiceInfoArray = OSArray::withCapacity(4); 58 59 return true; 60 61} 62 63//==================================================================================================== 64// IOHIDEventService::start 65//==================================================================================================== 66bool IOHIDEventSystem::start(IOService * provider) 67{ 68 if ( super::start(provider) == false ) 69 return false; 70 71 _workLoop = IOHIDWorkLoop::workLoop(); 72 _commandGate = IOCommandGate::commandGate(this); 73 74 if ( !_workLoop || !_commandGate ) 75 return false; 76 77 if ( _workLoop->addEventSource(_commandGate) != kIOReturnSuccess ) 78 return false; 79 80 _publishNotify = addNotification( 81 gIOPublishNotification, 82 serviceMatching("IOHIDEventService"), 83 OSMemberFunctionCast(IOServiceNotificationHandler, this, &IOHIDEventSystem::notificationHandler), 84 this, 85 (void *)OSMemberFunctionCast(IOCommandGate::Action, this, &IOHIDEventSystem::handleServicePublicationGated) ); 86 87 _terminateNotify = addNotification( 88 gIOTerminatedNotification, 89 serviceMatching("IOHIDEventService"), 90 OSMemberFunctionCast(IOServiceNotificationHandler, this, &IOHIDEventSystem::notificationHandler), 91 this, 92 (void *)OSMemberFunctionCast(IOCommandGate::Action, this, &IOHIDEventSystem::handleServiceTerminationGated) ); 93 94 if (!_publishNotify || !_terminateNotify) 95 return false; 96 97 _eventsOpen = true; 98 99 registerService(); 100 101 return true; 102} 103 104//==================================================================================================== 105// IOHIDEventService::free 106//==================================================================================================== 107void IOHIDEventSystem::free() 108{ 109 if (workLoop) { 110 workLoop->disableAllEventSources(); 111 } 112 113 if ( _publishNotify ) { 114 _publishNotify->remove(); 115 _publishNotify = 0; 116 } 117 118 if ( _terminateNotify ) { 119 _terminateNotify->remove(); 120 _terminateNotify = 0; 121 } 122 123 if ( _eventServiceInfoArray ) { 124 _eventServiceInfoArray->release(); 125 _eventServiceInfoArray = 0; 126 } 127 128 if ( _commandGate ) { 129 _commandGate->release(); 130 _commandGate = 0; 131 } 132 133 if ( _workLoop ) { 134 _workLoop->release(); 135 _workLoop = 0; 136 } 137 super::free(); 138} 139 140//==================================================================================================== 141// IOHIDEventService::message 142//==================================================================================================== 143IOReturn IOHIDEventSystem::message(UInt32 type, IOService * provider, void * argument) 144{ 145 return super::message(type, provider, argument); 146} 147 148//==================================================================================================== 149// IOHIDEventService::setProperties 150//==================================================================================================== 151IOReturn IOHIDEventSystem::setProperties( OSObject * properties ) 152{ 153 return super::setProperties(properties); 154} 155 156//==================================================================================================== 157// IOHIDEventService::notificationHandler 158//==================================================================================================== 159bool IOHIDEventSystem::notificationHandler( void * refCon, IOService * service ) 160{ 161 IOLog("IOHIDEventSystem::notificationHandler\n"); 162 163 _commandGate->runAction((IOCommandGate::Action)refCon, service); 164 165 return true; 166} 167 168//==================================================================================================== 169// IOHIDEventService::handleServicePublicationGated 170//==================================================================================================== 171void IOHIDEventSystem::handleServicePublicationGated(IOService * service) 172{ 173 IOLog("IOHIDEventSystem::handleServicePublicationGated\n"); 174 175 EventServiceInfo tempEventServiceInfo; 176 OSData * tempData; 177 IOHIDEventService * eventService; 178 179 if ( !(eventService = OSDynamicCast(IOHIDEventService, service)) ) 180 return; 181 182 attach( eventService ); 183 184 tempEventServiceInfo.service = eventService; 185 186 tempData = OSData::withBytes(&tempEventServiceInfo, sizeof(EventServiceInfo)); 187 188 if ( tempData ) 189 { 190 _eventServiceInfoArray->setObject(tempData); 191 tempData->release(); 192 } 193 194 if ( _eventsOpen ) 195 registerEventSource( eventService ); 196 197} 198 199//==================================================================================================== 200// IOHIDEventService::handleServiceTerminationGated 201//==================================================================================================== 202void IOHIDEventSystem::handleServiceTerminationGated(IOService * service) 203{ 204 EventServiceInfoRef tempEventServiceInfoRef; 205 OSData * tempData; 206 UInt32 index; 207 208 IOLog("IOHIDEventSystem::handleServiceTerminationGated\n"); 209 210 if ( _eventsOpen ) 211 service->close(this); 212 213 for ( index = 0; index<_eventServiceInfoArray->getCount(); index++ ) 214 { 215 if ( (tempData = OSDynamicCast(OSData, _eventServiceInfoArray->getObject(index))) 216 && (tempEventServiceInfoRef = (EventServiceInfoRef)tempData->getBytesNoCopy()) 217 && (tempEventServiceInfoRef->service == service) ) 218 { 219 _eventServiceInfoArray->removeObject(index); 220 break; 221 } 222 } 223 224 detach(service); 225} 226 227//==================================================================================================== 228// IOHIDEventService::registerEventSource 229//==================================================================================================== 230void IOHIDEventSystem::registerEventSource(IOHIDEventService * service) 231{ 232 EventServiceInfoRef tempEventServiceInfoRef; 233 OSData * tempData = NULL; 234 UInt32 index; 235 236 IOLog("IOHIDEventSystem::registerEventSource\n"); 237 238 for ( index = 0; index<_eventServiceInfoArray->getCount(); index++ ) 239 { 240 if ( (tempData = OSDynamicCast(OSData, _eventServiceInfoArray->getObject(index))) 241 && (tempEventServiceInfoRef = (EventServiceInfoRef)tempData->getBytesNoCopy()) 242 && (tempEventServiceInfoRef->service == service) ) 243 break; 244 245 tempData = NULL; 246 } 247 248 service->open(this, 0, tempData, 249 OSMemberFunctionCast(IOHIDEventService::HIDEventCallback, this, &IOHIDEventSystem::handleHIDEvent)); 250} 251 252 253//==================================================================================================== 254// IOHIDEventService::handleHIDEvent 255//==================================================================================================== 256void IOHIDEventSystem::handleHIDEvent( 257 void * refCon, 258 AbsoluteTime timeStamp, 259 UInt32 eventCount, 260 IOHIDEvent * events, 261 IOOptionBits options) 262{ 263 IOLog("IOHIDEventSystem::handleHIDEvent\n"); 264 265 HIDEventArgs args; 266 267 args.refCon = refCon; 268 args.timeStamp = timeStamp; 269 args.eventCount = eventCount; 270 args.events = events; 271 args.options = options; 272 273 _commandGate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &IOHIDEventSystem::handleHIDEventGated), (void *)&args); 274} 275 276//==================================================================================================== 277// IOHIDEventService::handleHIDEventGated 278//==================================================================================================== 279void IOHIDEventSystem::handleHIDEventGated(void * args) 280{ 281 HIDEventArgsRef eventArgsRef = (HIDEventArgsRef)args; 282 283 if ( !eventArgsRef->events ) 284 { 285 IOLog("IOHIDEventSystem::handleHIDEventGated: type=%d timestamp=%lld\n", 0, *((UInt64 *)&(eventArgsRef->timeStamp))); 286 return; 287 } 288 289 IOLog("IOHIDEventSystem::handleHIDEventGated: eventCount=%d timestamp=%lld\n", eventArgsRef->eventCount, *((UInt64 *)&(eventArgsRef->timeStamp))); 290 for ( UInt32 i=0; i<eventArgsRef->eventCount; i++) 291 { 292 IOHIDEvent * event = &(eventArgsRef->events[i]); 293 294 IOLog("IOHIDEventSystem::handleHIDEventGated: type=%d", event->type); 295 switch ( event->type ) 296 { 297 case kIOHIDKeyboardEvent: 298 IOLog(" usagePage=%x usage=%x value=%d repeat=%d", event->data.keyboard.usagePage, event->data.keyboard.usage, event->data.keyboard.value, event->data.keyboard.repeat); 299 break; 300 301 case kIOHIDMouseEvent: 302 IOLog(" buttons=%x dx=%d dy=%d", event->data.mouse.buttons, event->data.mouse.dx, event->data.mouse.dy); 303 break; 304 305 case kIOHIDScrollEvent: 306 IOLog(" deltaAxis1=%d deltaAxis2=%d deltaAxis3=%d", event->data.scroll.lines.deltaAxis1, event->data.scroll.lines.deltaAxis2, event->data.scroll.lines.deltaAxis3); 307 break; 308 309 default: 310 break; 311 } 312 IOLog("\n"); 313 } 314 315} 316