1/* 2 * IOFireWireLibAsyncStreamListener.cpp 3 * IOFireWireFamily 4 * 5 * Created by Arul on Thu Sep 28 2006. 6 * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. 7 * 8 * $ Log:IOFireWireLibAsyncStreamListener.cpp,v $ 9 */ 10 11#import "IOFireWireLibAsyncStreamListener.h" 12#import "IOFireWireLibDevice.h" 13#import "IOFireWireLibPriv.h" 14 15#import <IOKit/iokitmig.h> 16 17namespace IOFireWireLib { 18 19#pragma mark AsyncStreamListener - 20 21 // ============================================================ 22 // AsyncStreamListener 23 // ============================================================ 24 AsyncStreamListener::AsyncStreamListener( const IUnknownVTbl& interface, 25 Device& userclient, 26 UserObjectHandle inKernAddrSpaceRef, 27 void* inBuffer, 28 UInt32 inBufferSize, 29 void* inCallBack, 30 void* inRefCon ) 31 : IOFireWireIUnknown( interface ), 32 mUserClient(userclient), 33 mKernAsyncStreamListenerRef(inKernAddrSpaceRef), 34 mBuffer((char*)inBuffer), 35 mNotifyIsOn(false), 36 mUserRefCon(inRefCon), 37 mBufferSize(inBufferSize), 38 mListener( (AsyncStreamListenerHandler) inCallBack ), 39 mSkippedPacketHandler( nil ), 40 mRefInterface( reinterpret_cast<AsyncStreamListenerRef>( & GetInterface() ) ) 41 { 42 userclient.AddRef() ; 43 } 44 45 46 AsyncStreamListener::~AsyncStreamListener() 47 { 48 uint32_t outputCnt = 0; 49 const uint64_t inputs[1]={(const uint64_t)mKernAsyncStreamListenerRef}; 50 51 IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(), 52 kReleaseUserObject, 53 inputs,1, 54 NULL,&outputCnt); 55 56 if( mBuffer and mBufferSize > 0 ) 57 { 58 delete[] mBuffer; 59 mBuffer = 0; 60 mBufferSize = 0; 61 } 62 63 mUserClient.Release() ; 64 } 65 66 const IOFWAsyncStreamListenerHandler 67 AsyncStreamListener::SetListenerHandler ( AsyncStreamListenerRef self, 68 AsyncStreamListenerHandler inReceiver ) 69 { 70 AsyncStreamListenerHandler oldListener = mListener ; 71 mListener = inReceiver ; 72 73 return oldListener ; 74 } 75 76 const IOFWAsyncStreamListenerSkippedPacketHandler 77 AsyncStreamListener::SetSkippedPacketHandler( AsyncStreamListenerRef self, 78 AsyncStreamSkippedPacketHandler inHandler ) 79 { 80 AsyncStreamSkippedPacketHandler oldHandler = mSkippedPacketHandler; 81 mSkippedPacketHandler = inHandler; 82 83 return oldHandler; 84 } 85 86 Boolean 87 AsyncStreamListener::NotificationIsOn ( AsyncStreamListenerRef self ) 88 { 89 return mNotifyIsOn ; 90 } 91 92 Boolean 93 AsyncStreamListener::TurnOnNotification ( AsyncStreamListenerRef self ) 94 { 95 IOReturn err = kIOReturnSuccess ; 96 io_connect_t connection = mUserClient.GetUserClientConnection() ; 97 98 // if notification is already on, skip out. 99 if (mNotifyIsOn) 100 return true ; 101 102 if (!connection) 103 err = kIOReturnNoDevice ; 104 105 if ( kIOReturnSuccess == err ) 106 { 107 uint64_t refrncData[kOSAsyncRef64Count]; 108 refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0; 109 refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0; 110 const uint64_t inputs[3] = {(const uint64_t)mKernAsyncStreamListenerRef,(const uint64_t)& Listener,(const uint64_t)self}; 111 uint32_t outputCnt = 0; 112 err = IOConnectCallAsyncScalarMethod(connection, 113 kSetAsyncStreamRef_Packet, 114 mUserClient.GetIsochAsyncPort(), 115 refrncData,kOSAsyncRef64Count, 116 inputs,3, 117 NULL,&outputCnt); 118 } 119 120 if ( kIOReturnSuccess == err) 121 { 122 123 uint64_t refrncData[kOSAsyncRef64Count]; 124 refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0; 125 refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0; 126 const uint64_t inputs[3] = {(const uint64_t)mKernAsyncStreamListenerRef,(const uint64_t)& SkippedPacket,(const uint64_t)self}; 127 uint32_t outputCnt = 0; 128 err = IOConnectCallAsyncScalarMethod(connection, 129 kSetAsyncStreamRef_SkippedPacket, 130 mUserClient.GetIsochAsyncPort(), 131 refrncData,kOSAsyncRef64Count, 132 inputs,3, 133 NULL,&outputCnt); 134 } 135 136 if ( kIOReturnSuccess == err ) 137 { 138 uint32_t outputCnt = 0; 139 const uint64_t inputs[1]={(const uint64_t)mKernAsyncStreamListenerRef}; 140 141 err = IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(), 142 kAsyncStreamListener_TurnOnNotification, 143 inputs,1, 144 NULL,&outputCnt); 145 } 146 147 148 if ( kIOReturnSuccess == err ) 149 mNotifyIsOn = true ; 150 151 return ( kIOReturnSuccess == err ) ; 152 } 153 154 void 155 AsyncStreamListener::TurnOffNotification ( AsyncStreamListenerRef self ) 156 { 157 IOReturn err = kIOReturnSuccess ; 158 io_connect_t connection = mUserClient.GetUserClientConnection() ; 159 160 // if notification isn't on, skip out. 161 if (!mNotifyIsOn) 162 return ; 163 164 if (!connection) 165 err = kIOReturnNoDevice ; 166 167 if ( kIOReturnSuccess == err ) 168 { 169 uint64_t refrncData[kOSAsyncRef64Count]; 170 refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0; 171 refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0; 172 const uint64_t inputs[3] = {(const uint64_t)mKernAsyncStreamListenerRef,0,(const uint64_t)self}; 173 uint32_t outputCnt = 0; 174 175 // set callback for writes to 0 176 err = IOConnectCallAsyncScalarMethod(connection, 177 kSetAsyncStreamRef_Packet, 178 mUserClient.GetIsochAsyncPort(), 179 refrncData,kOSAsyncRef64Count, 180 inputs,3, 181 NULL,&outputCnt); 182 183 outputCnt = 0; 184 // set callback for skipped packets to 0 185 err = IOConnectCallAsyncScalarMethod(connection, 186 kSetAsyncStreamRef_SkippedPacket, 187 mUserClient.GetIsochAsyncPort(), 188 refrncData,kOSAsyncRef64Count, 189 inputs,3, 190 NULL,&outputCnt); 191 } 192 193 if ( kIOReturnSuccess == err ) 194 { 195 uint32_t outputCnt = 0; 196 const uint64_t inputs[1]={(const uint64_t)mKernAsyncStreamListenerRef}; 197 198 err = IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(), 199 kAsyncStreamListener_TurnOffNotification, 200 inputs,1, 201 NULL,&outputCnt); 202 } 203 204 mNotifyIsOn = false ; 205 } 206 207 void 208 AsyncStreamListener::ClientCommandIsComplete ( AsyncStreamListenerRef self, 209 FWClientCommandID commandID ) 210 { 211 uint32_t outputCnt = 0; 212 const uint64_t inputs[2] = {(const uint64_t)mKernAsyncStreamListenerRef, (const uint64_t)commandID}; 213 214 #if IOFIREWIREUSERCLIENTDEBUG > 0 215 OSStatus err = 216 #endif 217 218 IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(), 219 kAsyncStreamListener_ClientCommandIsComplete, 220 inputs,2, 221 NULL,&outputCnt); 222 223#ifdef __LP64__ 224 DebugLogCond( err, "AsyncStreamListener::ClientCommandIsComplete: err=0x%08X\n", err ) ; 225#else 226 DebugLogCond( err, "AsyncStreamListener::ClientCommandIsComplete: err=0x%08lX\n", err ) ; 227#endif 228 } 229 230 void* 231 AsyncStreamListener::GetRefCon ( AsyncStreamListenerRef self ) 232 { 233 return mUserRefCon; 234 } 235 236 void 237 AsyncStreamListener::SetFlags ( AsyncStreamListenerRef self, 238 UInt32 flags ) 239 { 240 uint32_t outputCnt = 0; 241 const uint64_t inputs[2] = {(const uint64_t)mKernAsyncStreamListenerRef, flags}; 242 IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(), 243 kAsyncStreamListener_SetFlags, 244 inputs,2, 245 NULL,&outputCnt); 246 247 mFlags = flags; 248 } 249 250 UInt32 251 AsyncStreamListener::GetFlags ( AsyncStreamListenerRef self ) 252 { 253 uint32_t outputCnt = 1; 254 uint64_t outputVal = 0; 255 const uint64_t inputs[1]={(const uint64_t)mKernAsyncStreamListenerRef}; 256 257 IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(), 258 kAsyncStreamListener_GetFlags, 259 inputs,1, 260 &outputVal,&outputCnt); 261 mFlags = outputVal & 0xFFFFFFFF; 262 263 return mFlags; 264 } 265 266 UInt32 267 AsyncStreamListener::GetOverrunCounter ( AsyncStreamListenerRef self ) 268 { 269 UInt32 counter = 0; 270 uint32_t outputCnt = 1; 271 uint64_t outputVal = 0; 272 const uint64_t inputs[1]={(const uint64_t)mKernAsyncStreamListenerRef}; 273 274 IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(), 275 kAsyncStreamListener_GetOverrunCounter, 276 inputs,1, 277 &outputVal,&outputCnt); 278 counter = outputVal & 0xFFFFFFFF; 279 return counter; 280 } 281 282 void 283 AsyncStreamListener::Listener( AsyncStreamListenerRef refcon, IOReturn result, void** args, int numArgs) 284 { 285 AsyncStreamListener* me = IOFireWireIUnknown::InterfaceMap<AsyncStreamListener>::GetThis(refcon) ; 286 287 if ( ! me->mListener ) 288 { 289 me->ClientCommandIsComplete( (AsyncStreamListenerRef) refcon, args[0] ) ; 290 return ; 291 } 292 else 293 { 294 (me->mListener)( 295 (AsyncStreamListenerRef) refcon, 296 (FWClientCommandID) args[0], // commandID, 297 (unsigned long)(args[1]), // size 298 me->mBuffer + (unsigned long)(args[2]), // packet 299 (void*) me->mUserRefCon) ; // refcon 300 } 301 } 302 303 void 304 AsyncStreamListener::SkippedPacket( AsyncStreamListenerRef refcon, IOReturn result, FWClientCommandID commandID, UInt32 packetCount) 305 { 306 AsyncStreamListener* me = IOFireWireIUnknown::InterfaceMap<AsyncStreamListener>::GetThis(refcon) ; 307 308 if (me->mSkippedPacketHandler) 309 (me->mSkippedPacketHandler)( refcon, commandID, packetCount) ; 310 else 311 me->ClientCommandIsComplete( refcon, commandID ) ; 312 } 313 314 315#pragma mark AsyncStreamListenerCOM - 316 317 AsyncStreamListenerCOM::Interface AsyncStreamListenerCOM::sInterface = 318 { 319 INTERFACEIMP_INTERFACE, 320 1, 0, 321 322 &AsyncStreamListenerCOM::SSetListenerHandler, 323 &AsyncStreamListenerCOM::SSetSkippedPacketHandler, 324 &AsyncStreamListenerCOM::SNotificationIsOn, 325 &AsyncStreamListenerCOM::STurnOnNotification, 326 &AsyncStreamListenerCOM::STurnOffNotification, 327 &AsyncStreamListenerCOM::SClientCommandIsComplete, 328 &AsyncStreamListenerCOM::SGetRefCon, 329 &AsyncStreamListenerCOM::SSetFlags, 330 &AsyncStreamListenerCOM::SGetFlags, 331 &AsyncStreamListenerCOM::SGetOverrunCounter 332 } ; 333 334 // 335 // --- ctor/dtor ----------------------- 336 // 337 338 AsyncStreamListenerCOM::AsyncStreamListenerCOM( Device& userclient, 339 UserObjectHandle inKernAddrSpaceRef, 340 void* inBuffer, 341 UInt32 inBufferSize, 342 void* inCallBack, 343 void* inRefCon ) 344 : AsyncStreamListener( reinterpret_cast<const IUnknownVTbl &>( sInterface ), userclient, inKernAddrSpaceRef, inBuffer, 345 inBufferSize, inCallBack, inRefCon ) 346 { 347 } 348 349 AsyncStreamListenerCOM::~AsyncStreamListenerCOM() 350 { 351 } 352 353 // 354 // --- IUNKNOWN support ---------------- 355 // 356 357 IUnknownVTbl** 358 AsyncStreamListenerCOM::Alloc( Device& userclient, 359 UserObjectHandle inKernAddrSpaceRef, 360 void* inBuffer, 361 UInt32 inBufferSize, 362 void* inCallBack, 363 void* inRefCon ) 364 { 365 AsyncStreamListenerCOM* me = nil ; 366 367 try { 368 me = new AsyncStreamListenerCOM( userclient, inKernAddrSpaceRef, inBuffer, inBufferSize, inCallBack, inRefCon ) ; 369 } catch(...) { 370 } 371 372 return ( nil == me ) ? nil : reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()) ; 373 } 374 375 HRESULT 376 AsyncStreamListenerCOM::QueryInterface(REFIID iid, void ** ppv ) 377 { 378 HRESULT result = S_OK ; 379 *ppv = nil ; 380 381 CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ; 382 383 if ( CFEqual(interfaceID, IUnknownUUID) || CFEqual(interfaceID, kIOFireWireAsyncStreamListenerInterfaceID) ) 384 { 385 *ppv = & GetInterface() ; 386 AddRef() ; 387 } 388 else 389 { 390 *ppv = nil ; 391 result = E_NOINTERFACE ; 392 } 393 394 CFRelease(interfaceID) ; 395 return result ; 396 } 397 398 // 399 // --- static methods ------------------ 400 // 401 const IOFWAsyncStreamListenerHandler 402 AsyncStreamListenerCOM::SSetListenerHandler ( AsyncStreamListenerRef self, 403 AsyncStreamListenerHandler inReceiver ) 404 { 405 return IOFireWireIUnknown::InterfaceMap<AsyncStreamListenerCOM>::GetThis(self)->SetListenerHandler( self, inReceiver ) ; 406 } 407 408 const IOFWAsyncStreamListenerSkippedPacketHandler 409 AsyncStreamListenerCOM::SSetSkippedPacketHandler( AsyncStreamListenerRef self, 410 AsyncStreamSkippedPacketHandler inHandler ) 411 { 412 return IOFireWireIUnknown::InterfaceMap<AsyncStreamListenerCOM>::GetThis(self)->SetSkippedPacketHandler( self, inHandler ) ; 413 } 414 415 Boolean 416 AsyncStreamListenerCOM::SNotificationIsOn ( AsyncStreamListenerRef self ) 417 { 418 return IOFireWireIUnknown::InterfaceMap<AsyncStreamListenerCOM>::GetThis(self)->NotificationIsOn( self ) ; 419 } 420 421 Boolean 422 AsyncStreamListenerCOM::STurnOnNotification ( AsyncStreamListenerRef self ) 423 { 424 return IOFireWireIUnknown::InterfaceMap<AsyncStreamListenerCOM>::GetThis(self)->TurnOnNotification( self ) ; 425 } 426 427 void 428 AsyncStreamListenerCOM::STurnOffNotification ( AsyncStreamListenerRef self ) 429 { 430 return IOFireWireIUnknown::InterfaceMap<AsyncStreamListenerCOM>::GetThis(self)->TurnOffNotification( self ) ; 431 } 432 433 void 434 AsyncStreamListenerCOM::SClientCommandIsComplete ( AsyncStreamListenerRef self, 435 FWClientCommandID commandID, 436 IOReturn status ) 437 { 438 IOFireWireIUnknown::InterfaceMap<AsyncStreamListenerCOM>::GetThis(self)->ClientCommandIsComplete( self, commandID ) ; 439 } 440 441 void* 442 AsyncStreamListenerCOM::SGetRefCon ( AsyncStreamListenerRef self ) 443 { 444 return IOFireWireIUnknown::InterfaceMap<AsyncStreamListenerCOM>::GetThis(self)->GetRefCon( self ); 445 } 446 447 void 448 AsyncStreamListenerCOM::SSetFlags ( AsyncStreamListenerRef self, 449 UInt32 flags ) 450 { 451 IOFireWireIUnknown::InterfaceMap<AsyncStreamListenerCOM>::GetThis(self)->SetFlags( self, flags ); 452 } 453 454 UInt32 455 AsyncStreamListenerCOM::SGetFlags ( AsyncStreamListenerRef self ) 456 { 457 return IOFireWireIUnknown::InterfaceMap<AsyncStreamListenerCOM>::GetThis(self)->GetFlags( self ); 458 } 459 460 UInt32 461 AsyncStreamListenerCOM::SGetOverrunCounter ( AsyncStreamListenerRef self ) 462 { 463 return IOFireWireIUnknown::InterfaceMap<AsyncStreamListenerCOM>::GetThis(self)->GetOverrunCounter( self ); 464 } 465} 466